Welcome back to the next part of our blog series. If you haven’t checked out the earlier posts yet, I suggest giving a read to the first post. In that part, we talked about how we picked our target, got the firmware from the camera, and got into the shell.
After installing the firmware version 1.0.5-0185
on the camera, we started with the reconnaissance phase, a crucial step in understanding our target. The aim here is to gather information about the target and identify potential vulnerabilities. This data not only gives us a snapshot of the target’s weak points but is also handy when crafting a strategy for the attack.
Now, let’s get started by discovering all the services the camera has exposed, shall we?
Using nmap
we were able to list all the TCP services that the IP camera exposes:
$ nmap -p- -Pn -T4 10.0.0.2
...
PORT STATE SERVICE
80/tcp open http
443/tcp open https
554/tcp open rtsp
49152/tcp open unknown
...
We ran a similar command to detect all the accessible UDP ports, but unfortunately, none could be identified.
Let’s now take a look at all the exposed ports identified as open by nmap:
Now, let’s conduct a brief analysis of the identified services.
The web server requires authentication for most of the exposed URLs. In the next blog post we’ll take a close look at how the web server checks and approves or rejects the incoming HTTP requests.
As mentioned in the previous blog post, the password for the synodebug
user is updated whenever we change the password for the camera web interface user, using the same password for both users. You may have also noticed in a screenshot from the first part of this blog series that the used function appends both the username and the provided password to a shell command without any validation. This allows for command injection.
To validate our assumption, we can change the user’s password through the web interface and insert the command injection payload into both the new password and confirm password textboxes. For instance, we used the following command injection payload to create a file named file123
inside the tmp
folder:
First let us verify that no files with name file123
exist in the tmp
directory:
$ ls -la /tmp/file123
ls: /tmp/file123: No such file or directory
Upon altering the password using the command injection payload shown above, the file file123
was indeed generated by the root user:
$ ls -la /tmp/file123
-rw-r--r-- 1 root root 0 Sep 21 02:19 /tmp/file123
Great! Now that we’ve confirmed the command injection vulnerability, it’s important to note that this endpoint requires authentication. While we’ve uncovered similar command injection vulnerabilities in other endpoints, it’s noteworthy that all of them require authentication.
Surprisingly, we discovered that WebDAV (Web Distributed Authoring and Versioning) is enabled on the web server. This service is usually used for collaborative editing and management of files over the web.
$ nmap -p- -Pn -sV -sC -T4 10.0.0.2
...
PORT STATE SERVICE VERSION
...
80/tcp open webdav
...
| http-webdav-scan:
| Allowed Methods: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL
| WebDAV type: Unknown
|_ Server Date: Fri, 22 Sep 1970 00:13:42 GMT
...
443/tcp open ssl/webdav
...
| http-webdav-scan:
| Allowed Methods: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, PROPFIND, MKCOL
| WebDAV type: Unknown
|_ Server Date: Fri, 22 Sep 1970 00:13:42 GMT
...
After running some tests, we discovered a few misconfigurations. We found that the web server let WebDAV modification actions to happen on specific paths without needing a login. However, because the camera file system was mounted as read-only, these modifications were blocked by the operating system.
But here’s the interesting part about the DELETE
action – when we used it on the root path (/
), it deleted all files on the SD card linked to the camera. Why? Because that was the only writable file system, and a reference to the SD card folder was present in the web server’s root directory.
Sadly, we couldn’t remove any configuration files that might have let us reset the user’s credentials and access the management interface. This might seem like a Denial of Service (DoS) vulnerability, but it doesn’t really help in the Pwn2Own competition.
The Real-Time Streaming Protocol (RTSP) is a protocol for creating and managing time-synchronized streams for multimedia communications.
The OPTIONS
response (shown in blue in the screenshot below) displays a list of the available commands supported by the service:
When attempting to connect to the RTSP protocol without valid credentials, an unauthorized error is triggered, prompting the user to provide valid credentials through HTTP Digest authentication. This is shown in the following image:
Universal Plug and Play (UPnP) is a service often found in IoT devices, simplifying network setup. Essentially, devices supporting the UPnP passive discovery method protocol periodically share their services on the network through NOTIFY
messages that are sent to the multicast address 239.255.255.250
on UDP port 1900
. These messages usually include a URL pointing to an XML file that describes the device’s UPnP profile. Here’s an example of a NOTIFY
message sent by the camera:
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
CACHE-CONTROL: max-age=100
LOCATION: http://10.0.0.2:49152/device_desc.xml
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS: 20282198-1dd2-11b2-845a-c2d8cde546a4
NT: upnp:rootdevice
NTS: ssdp:alive
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: redsonic
USN: uuid:Upnp-IPCamera-1_0-9009D03F28AD::upnp:rootdevice
The camera tells us that the XML description file is available at port 49152
, accessible through the /device_desc.xml
path. Unfortunately, the XML description file doesn’t offer much information about additional services:
<?xml version="1.0"?>
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<deviceType>urn:schemas-upnp-org:device:IPCamera:1</deviceType>
<friendlyName>BC500</friendlyName>
<manufacturer>Synology</manufacturer>
<manufacturerURL>https://www.synology.com</manufacturerURL>
<modelDescription>Synology Camera BC500</modelDescription>
<modelName>BC500</modelName>
<modelURL>https://www.synology.com</modelURL>
<modelNumber>BC500</modelNumber>
<serialNumber>2340VSRZPTFGD</serialNumber>
<UDN>uuid:Upnp-IPCamera-1_0-9009D03F28AD</UDN>
<Activated>true</Activated>
<UPC></UPC>
<serviceList></serviceList>
<presentationURL>https://10.0.0.2:443</presentationURL>
</device>
<URLBase>http://10.0.0.2:49152/</URLBase>
</root>
We didn’t discover any notable weaknesses in the exposed service that could be combined with the vulnerabilities we’ve identified thus far to execute commands arbitrarily on the camera.
However, during our investigation, we encountered a curious behavior in the server’s response headers. The "
character must be present an even number of times in HTTP headers. If not, the request pauses for 30 seconds before ultimately resulting in a 400 error:
An even number of "
characters, results in a proper response in 29 milliseconds.
This behavior appears to be independent of where the "
characters are positioned. For instance, in this request, the same behavior is observed with 3 "
characters placed in 3 different headers:
After reverse engineering the systemd
binary, responsible for handling incoming UPnP requests, we found that the root cause of this delay lies in the code responsible for string detection in the received request. In short, when the code encounters the initial "
character, it continues reading characters until it hits the closing "
, failing to identify the end of the request. It’s worth noting that, despite this issue, we found no vulnerabilities that could be leveraged to manipulate the binary’s execution flow.
So, after going through all the services identified by nmap, our next move was to dig into the services exposed internally. We executed netstat as the root user to get a more comprehensive perspective on all active network connections and listening services.
root@BC500_AD:~$ netstat -tunap
...
tcp 0 0. 0.0.0:554 0.0.0.0:* LISTEN 738/streamd
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 2228/webd
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 2228/webd
tcp 0 0 10.0.0.2:49152 0.0.0.0:* LISTEN 527/systemd
tcp 0 0 :::554 :::* LISTEN 738/streamd
udp 0 0 127.0.0.1:34802 0.0.0.0:* 527/systemd
udp 0 0 0.0.0.0:19998 0.0.0.0:* 2228/webd
udp 0 0 10.0.0.2:68 0.0.0.0:* 584/dhcpcd:eth0[i
udp 0 0 0.0.0.0:1900 0.0.0.0:* 527/systemd
The Netstat output revealed an additional UDP port that was not detected by Nmap. This discrepancy could be caused by the usage of a custom protocol or the service never sending a response.
We decompiled the webd
binary to find the code responsible for handling these UDP packets. After extracting values from the incoming packet, the code checks whether the Custom.Activated
option is enabled and jumps to the function r0x00030d5c
if it is not:
The mentioned code is responsible for updating the network information of the camera:
Unfortunately, the camera we are targeting is expected to have already been activated. As a result, this service doesn’t appear to offer many exploitable functionalities.
During the reconnaissance phase, we discovered from the documentation that the camera can be integrated with the Surveillance Station software, allowing centralized management of Synology cameras across one or multiple offices. Intrigued by this, we went ahead and purchased the Synology NAS DS233, setting up a mock office scenario where the IP camera is linked to the Surveillance Station running on the NAS.
During our analysis, we found that the Surveillance Station software supports both plaintext HTTP and encrypted HTTPS connections. Because of the IP camera’s self-signed certificate, it allowed for potential man-in-the-middle attacks using tools like Burp, as the Surveillance Station would trust the self-signed certificate or prompt the user to trust it. For simplicity, we chose to establish the connection using the plaintext HTTP protocol and monitored the traffic using Wireshark.
The Wireshark traffic revealed a peculiar behavior: every HTTP request is sent twice:
By intercepting the first HTTP request, it becomes possible to steal the cleartext credentials of the web user:
As described in RFC 7617, the characters following the Basic
string in the displayed HTTP header represent a base64-encoded form of the following string: <username>:<password>
. In the intercepted traffic, the password of the web user is Password.1
:
$ echo -n "Y29tcGFzczpQYXNzd29yZC4x" | base64 -d
compass:Password.1
By combining this issue with the command injection vulnerability in the password change functionality, it is possible to perform remote code execution starting as anonymous users in a man-in-the-middle scenario inside a network where the Synology NAS is configured. However, our goal is to identify a weakness exploitable by anonymous users without any specific setup. Therefore, we continued our exploration for other potential vulnerabilities.
We’ve gained a better understanding of the camera’s exposed services and what they can do. In the next blog post, we dive deep into the analysis of the web server as it exposes most of the available functionalities, making it an interesting area for exploration.
Articles in this series: