Major Vulnerabilities in Foscam Cameras

For the past several months, VDOO’s security research teams have been undertaking broad-scale security research of leading IoT products, from the fields of safety and security. In most cases, the research was carried out together with the device vendors for the sake of efficiency and transparency.

As part of this research, VDOO researchers found zero-day vulnerabilities in devices of several vendors. These vulnerabilities were disclosed to the vendors, in accordance with responsible disclosure best practices, and will be shared gradually after the disclosure periods are concluded.

One of the vendors for which we found vulnerable devices was Foscam. Our team discovered a critical chain of vulnerabilities in Foscam security cameras. Combining the discovered vulnerabilities, an adversary who successfully obtains the address of the camera, can remotely gain root access to the cameras (via LAN or internet). VDOO has responsibly disclosed these vulnerabilities (CVE-2018-6830, CVE-2018-6831 and CVE-2018-6832) and engaged with Foscam’s security team to solve the matter.

VDOO’s security research team enjoyed full collaboration and transparency with Foscam and are appreciative of their openness in sharing the information discovered with the security community. This constitutes a meaningful contribution to the IoT industry as a whole and specifically to the privacy and security of Foscam’s customers.

To the best of our knowledge, these vulnerabilities were not exploited in the field, and therefore, did not lead to any concrete privacy violation or security threat to Foscam customers. The Foscam team acted promptly to patch these vulnerabilities and push them to the vulnerable products.

We strongly recommend that Foscam customers who did not update their cameras do so immediately or mitigate the risk in alternative ways. See instructions in FAQ section below.

We also recommend that other camera vendors follow our recommendations at the end of this report to avoid and mitigate similar threats.

About VDOO

VDOO is a technology driven company that strives to change the reality of unprotected connected devices. VDOO is building a line of products to support device manufacturers in embedding security into their connected devices at the development stage and enable post-development security.

In addition to developing products and services, VDOO invests significant efforts in wide scope research of connected devices. Safety and security products are two of the focus groups of this research.

VDOO’s research goal is to contribute knowledge and tools to mitigate risks, as well as encourage device vendors to implement the right security for their products. We at VDOO believe that an appropriate implementation of the security essentials will dramatically decrease the chances of exploiting vulnerabilities on the device.

This is a first of a series of blogs that will cover technical deep dives as part of our wide scope research. Stay tuned.

Technical Overview

The camera is running a Linux operating system and all processes run with root privileges. The web server is a lighttpd with additional vendor code, and it forwards API requests to its internal CGIProxy.fcgi process, by using the FastCGI protocol. The CGIProxy.fcgi executable forwards requests (by using a proprietary IPC mechanism) to the webService process – that verifies the user’s credentials (if needed) and runs the handler for the desired API command. Depending on the command, the handler may call additional code from the devMng process, that in turn usually runs shell commands by using the system() or popen() library calls, to configure system services. A watchdog daemon restarts important processes after they are terminated.

Camera's Process Layout

The attack scenario on a network-accessible camera is as follows:

  • Step 1: An adversary must first obtain the camera’s IP address or DNS name. It can be achieved in several ways, including:
    • If the camera and the network are configured by the user such that the camera has direct interface to the internet, its address might be revealed by some internet scanners.
    • If the adversary gained unauthorized (remote or local) access to a network to which the camera is connected, he might be able to find the local address of the camera.
    • If dynamic DNS is enabled by the user, the adversary might find a way to resolve the device name
  • Step 2: The adversary then uses CVE-2018-6830, an arbitrary file deletion vulnerability, to delete certain critical files that will result in authentication bypass when the webService process reloads.
  • Step 3: The adversary crashes the webService process by exploiting CVE-2018-6832, a stack-based buffer overflow vulnerability in the webService process. After it crashes, the webService process is automatically restarted by the watchdog daemon, and during the process reload, the changes from step 2 take effect. The adversary is now able to gain administrative credentials.
  • Step 4: The adversary executes root commands by exploiting CVE-2018-6831. This is a shell command injection vulnerability that requires administrator credentials. Since the adversary gained administrator credentials in the previous stage, he can now use this vulnerability to execute commands as the root user for privilege escalation. Full details appear in the Technical Deep Dive below.

Technical Deep-Dive

This section provides the details of each vulnerability and explains the full attack sequence.

CVE-2018-6830 – Arbitrary File Deletion Vulnerability

This vulnerability allows an attacker to delete arbitrary files from the camera’s filesystem, by crafting a special GET request to the camera’s Web management interface; no user credentials are required.

This vulnerability is related to custom vendor code added to the open source lighttpd web server code. The function of this code is to delete temporary snapshot pictures taken using the snapPicture API command immediately after they are uploaded from the camera to the user (the same functionality is assigned to the exportConfig API command).

When a GET request is sent to the web server (over port 88), after processing the request, the request’s URI path component (con->request.uri->ptr) is searched for either the string /configs/export/ or /snapPic/. If the request contains one of these strings, the server uses the strncat function to combine the the document-root path /tmp/www with the URI’s path component to form a full path. It then verifies the existence of the file (by calling access(path, F_OK)) and proceeds to delete the file by calling remove(path).

This code suffers from a path-traversal vulnerability, by which an attacker can use dot-dot-slash (‘../’) sequences in the GET request that will end in the con->request.uri->ptr component. Since the /snapPic/ directory already exists in the server’s document-root, the attacker can use the /snapPic/ URI as a valid path that will also trigger execution of this code branch. The attacker then continues adding dot-dot-slash sequences to travel up the directory tree until reaching the root directory (‘/’), and then add the path for the file to be deleted. For example, the URI /snapPic/../../../tmp/abc indicates that the file /tmp/abc, if exists, will be deleted.

PoC

This PoC shows how we use the vulnerability to delete an arbitrary file from the device. The _FILE_TO_DELETE shell variable holds a file’s absolute path.

CVE-2018-6832 – Stack-based Buffer Overflow Vulnerability

This vulnerability allows an attacker to crash the device’s webService process. It is triggered by sending a specially crafted GET request to the camera’s Web management interface, without the need for any user credentials.

The camera’s web-server offers a FastCGI API with many commands. Among the possible commands is the getSWFlag command, which is invoked by sending an unauthenticated HTTP GET request to /CGIProxy.fcgi?cmd=getSWFlag. The GET request parameters are forwarded from the CGIProxy.fcgi process to webService‘s getSWFlag function code (let’s call it getSWFlag_func). getSWFlag_func can optionally receive a query-string parameter named callbackJson.

getSWFlag_func first reads the value of the callbackJson parameter to a local variable, callbackJson_var, of size 0x400 bytes on the stack. This is done by invoking the get_param function with a reference to callbackJson_var, with a size limit of up to 0x400 characters.

After that, getSWFlag invokes the prepare_reply_func function with a reference to callbackJson_var. This function prepares some of the HTTP response that will be sent back to the user.

If callbackJson_var isn’t an empty string – prepare_reply_func appends various string data to the callbackJson_var string in place (at its original location on the stack of getSWFlag_func) using strcat. In total approximately 0x48 characters are added. (the appended string is:'({“key”:”<CGI_Result><result>0</result><flag>0011</flag></CGI_Result>”})’).

Thus, if an attacker sets the value of the query string’s parameter, callbackJson to hold enough characters (above a certain threshold), the resulting concatenation generated by prepare_reply_func will cause an overflow of callbackJson_var in the stack for getSWFlag_func. Writing a large number of bytes will cause an overwriting of saved stack registers (including the PC register) and cause a crash. Thus, the attacker can crash the webService process, which leads to a restart of this process a few seconds later by the /usr/bin/watchdog process.

CVE-2018-6831 – Shell Command Injection Vulnerability

This vulnerability requires administrator credentials, which were achieved in the previous stages. It allows an attacker to execute commands as the root user, for escalating privileges. It bypasses a patch of an older vulnerability, CVE-2017-2879, disclosed by Cisco Talos, in June 2017.

The camera’s web-server FastCGI API includes a command for setting a custom NTP server (/CGIProxy.fcgi?cmd=setSystemTime). This command requires administrator credentials. The parameter ntpServer, required by this command, holds the string value to be used to set the NTP_Server_URL. This parameter is not sanitized of special characters and can even contain spaces and semicolons.

When the API command setSystemTime is called, CGIProxy.fcgi forwards the request to the webService process, which reads its parameters and sends an IPC message that invokes the devMng function OnDevMngMsgSetSystemTime (command 0x6034).

Among other things, OnDevMngMsgSetSystemTime sets the new NTP_Server_URL in a global structure.

A separate thread, NTP update thread, within devMng, runs the setSystemTimeNTP function once every second in an infinite loop.

setSystemTimeNTP takes the NTP_Server_URL value from the global structure (set earlier) and calls gethostbyname(NTP_Server_URL) using this value. If the hostname is successfully resolved, it proceeds to call the following vulnerable code: sprintf(buf, “ntpclient -h %s -c 3 -s”, NTP_Server_URL); and popen(buf, “r”); (see IDA screenshot below).

The popen function runs a shell command by running sh -c with the provided string argument. If we set NTP_Server_URL to be ;SOME_COMMAND;, and could bypass the gethostbyname(NTP_Server_URL) call – popen would then call sh -c “ntpclient -h ;SOME_COMMAND; -c 3 -s”. The semicolon facilitates breaking the shell command and causing a command injection. As the devMng process runs as root, we will be able to run any command as the root user.

As noted earlier, it is our understanding that the code that proceeds only upon a successful gethostbyname() call was added in order to patch the CVE-2017-2879 vulnerability. Our speculation is that the patch authors assumed that using the gethostbyname() call would be a sufficient solution to sanitize the input of NTP_Server_URL. We refuted this assumption, as we observed that uclibc’s (the camera’s C standard library) gethostbyname() implementation does not fail to resolve hostnames that include semi-colons or spaces.

In order to bypass the gethostbyname call, we perform the following steps (see corresponding step numbers in the ‘CVE-2018-6831 Steps’ diagram below):

  1. We set up our own DNS server in advance, and configure it to responds to any DNS query (even if it contained spaces and semicolons) bearing a predefined static IP address (e.g., 1.2.3.4).
  2. Then, we set the Camera’s DNS server address to our own DNS server using the /CGIProxy.fcgi?cmd=setIpInfo API command.
  3. We then trigger the vulnerability by crafting a malicious request to the setSystemTime API command with an NTP_Server_URL of “;SOME COMMAND;”.
  4. At this stage, gethostbyname runs, causing the camera to send a DNS query for “;SOME_COMMAND;”.
  5. Our DNS server sends a valid response, which makes the gethostbyname() call succeed.
  6. The code proceeds to execute the command injection, enabling the attacker to execute commands as root.

PoC

  1. Preparations for the vulnerability – Setting up a Bind9 DNS server with the following configuration:
  2. Setting the camera’s DNS Server to point to our DNS server: (using the administrator’s username and password)
  3. Triggering the vulnerability (we chose to execute a telnet server and then connect to it):

Below is also a screenshot from Wireshark – showing the DNS traffic emitted throughout the attack.

Recommendations for Device Makers

We would like to relate to some bad architectural practices that were found in the cameras analyzed in this research, that make it easier for an attacker to discover and exploit vulnerabilities. We encourage device makers to take the below recommendations into consideration.

  • All the device’s processes run as root. This violates the concept of privilege separation (https://en.wikipedia.org/wiki/Privilege_separation), which states that a program should be divided into parts – each part limitied to its own needed privileges. While every process in the system runs as root – a code-execution bug in any of the system’s processes will allow the attacker to escalate to root privileges. On the other hand, if less processes were running with high privileges – an attacker would have to discover vulnerabilities in a more restricted set of processes in order to escalate privileges, which is a harder task. Specifically, network-facing processes such as webservers should run with the minimum set of privileges and not as root.
  • Executing external processes to perform tasks (such as configuring the device or its operating system) instead of using existing API for the programming language (library functions), if such exists. Executing external processes, and specifically running shell commands introduces the possibility of new vulnerability types to the program. A developer should be aware of such vulnerability types and protect from them. One such type, which made CVE-2018-6831 possible is command injection. While it could have prevented by strict input sanitization, the practice or running shell commands requires the device maker to sanitize for all shell control symbols. Another example is the possibility that an attacker is able to substitute the executable that the program is about to run – enabling him to run code in a more privileged context.
  • Bad input sanitization. CVE-2018-6831 was possible since instead of using a suitable method to input sanitization, the code authors relied on the gethostbyname library call – that is not built for this purpose. A better way to protect from bad input is by whitelisting – allowing only specific character range to be found in the input field.
  • In practice, the fact that the vendor firmware file was encrypted using a short guessable pattern as a key for the openssl command with aes-128-cbc, allowed us to quickly get our hands on the firmware content. We could then immediately start analyzing the firmware for security issues. Moreover, the device contained unstripped binaries with symbols like function names. This aided us in understanding how the code works. On the other hand, it is worth noting that the security by obscurity approach for firmware content may contribute to a situation in which issues exists but are not being discovered and remediated since the firmware is encrypted properly. Vendors should consider this tradeoff carefully.

Acknowledgment

We would like to thank Foscam’s security team for efficiently and promptly handling this security issue.

Credit

Or Peles (@peles_o), VDOO

FAQ Section

Q1. How do I know if my device is vulnerable?

You need to check that your camera’s firmware is at least the version appearing in ‘Table I’ below with the associated security patch. To check which firmware version your camera uses, you can do the following:

Method 1

  1. Using a web browser, access your camera. The address line normally looks like this: 192.168.0.1:88 (replace “192.168.0.1” by the actual address of the camera).
  2. Enter your username and password
  3. Click “Settings” and then “Device Information”
  4. On the right pane, look for “Application Firmware Version”.

Method 2

If you have multiple devices, it may be worthwhile to retrieve the firmware programmatically by issuing the following command:

curl “<Camera IP Address>:88/cgi-bin/CGIProxy.fcgi?cmd=getDevInfo&usr=admin&pwd=<Password>

For example:

curl “192.168.0.200:88/cgi-bin/CGIProxy.fcgi?cmd=getDevInfo&usr=admin&pwd=abc1234

The reply should look like this:

<CGI_Result>

    <result>0</result>

    <productName>FI9816P+V3</productName>

    <serialNo>0000000000000001</serialNo>

    <devName>Acme</devName>

    <mac>00626E860232</mac>

    <year>2018</year>

    <mon>5</mon>

    <day>25</day>

    <hour>19</hour>

    <min>40</min>

    <sec>19</sec>

    <timeZone>0</timeZone>

    <firmwareVer>2.81.2.29</firmwareVer>

    <hardwareVer>1.12.5.2</hardwareVer>

    <pkgTime>2017-06-15_17%3A21%3A35</pkgTime>

</CGI_Result>

Look for the line with “firmwareVer”.

Table I – Latest vulnerable firmware versions.

These are the latest vulnerable firmware versions. The addition of a corresponding patch mitigates the vulnerabilities.

Camera models Application firmware version
C1 Lite V3 2.82.2.33
C1 V3 2.82.2.33
FI9800P V3 2.84.2.33
FI9803P V4 2.84.2.33
FI9816P V3 2.81.2.33
FI9821EP V2 2.81.2.33
FI9821P V3 2.81.2.33
FI9826P V3 2.81.2.33
FI9831P V3 2.81.2.33
FI9851P V3 2.84.2.33
FI9853EP V2 2.84.2.33
C1 2.52.2.47
C1 V2 2.52.2.47
C1 Lite 2.52.2.47
C1 Lite V2 2.52.2.47
FI9800P 2.54.2.47
FI9800P V2 2.54.2.47
FI9803P V2 2.54.2.47
FI9803P V3 2.54.2.47
FI9815P 2.51.2.47
FI9815P V2 2.51.2.47
FI9816P 2.51.2.47
FI9816P V2 2.51.2.47
FI9851P V2 2.54.2.47
R2 2.71.1.59
C2 2.72.1.59
R4 2.71.1.59
FI9900EP 2.74.1.59
FI9900P 2.74.1.59
FI9901EP 2.74.1.59
FI9961EP 2.72.1.59
FI9928P 2.74.1.58
FI9803EP 2.22.2.31
FI9803P 2.24.2.31
FI9853EP 2.22.2.31
FI9851P 2.24.2.31
FI9821P V2 2.21.2.31
FI9826P V2 2.21.2.31
FI9831P V2 2.21.2.31
FI9821EP 2.21.2.31
FI9821W V2 2.11.1.120
FI9818W V2 2.13.2.120
FI9831W 2.11.1.120
FI9826W 2.11.1.120
FI9821P 2.11.1.120
FI9831P 2.11.1.120
FI9826P 2.11.1.120
FI9805W 2.14.1.120
FI9804W 2.14.1.120
FI9804P 2.14.1.120
FI9805E 2.14.1.120
FI9805P 2.14.1.120
FI9828P 2.13.1.120
FI9828W 2.13.1.120
FI9828P V2 2.11.1.133

Q2. How can I tell if my device was breached?

As botnet malware is normally crafted to go undetected, there’s no easy way to know for sure. Any suspicious change to the device may indicate the existence of a botnet malware on your device.

A few ways to check:

  1. Your password is not working anymore (and not because you forgot it) – this is a strong indication for a device that has been taken over.
  2. Your device settings were modified – for example, videos are now sent to a different server.
  3. Spike in network traffic – if possible, examine your router network statistics. A botnet could increase the amount of network traffic originated from the camera. Any spikes should alert you since unless you are streaming video from the camera, this number should be relatively low.

Q3. Is there a way to remediate my device if it was breached?

At the time of publication, we are not aware of any malware abusing this issue. If you suspect your device is breached, restore the camera to its factory settings. Doing so will restore the configuration to default settings, allowing you to connect and upgrade the firmware.  Keep in mind that if you’re using a firmware susceptible to the vulnerabilities detected by VDOO, the device might be targeted and can become infected again shortly. So, after resetting the device, make sure to immediately perform the firmware upgrade, prior to connecting the camera directly to the internet.

Q4. How to mitigate the risk if I can’t update the camera’s firmware?

In order to reduce the camera’s exposure and the ability to manage it remotely, it is recommended to place the device behind a firewall blocking port 88 and 443 (or the ports specified in the camera’s configuration) and consider not allowing the camera to initiate any outbound connections (please keep in mind, this could affect the Foscam cloud service). Another option is to put the device behind a reverse proxy that blocks the URLs we are using for the exploit (see above for additional details). Please contact security@vdoo.com if additional help is necessary.

Q5. How to upgrade the firmware in the camera?

Click here to find the vendor’s instructions for firmware update.

One Reply to “Major Vulnerabilities in Foscam Cameras”

Comments are closed.