- 27th April 2018
- Posted by: Fidus
- Category: Research
DLink DCS-5020L Day n’ Night Camera Remote Code Execution Walkthrough
“The DCS-5020L Wireless N Day & Night Pan/Tilt Cloud Camera is a day/night network camera that easily connects to your existing home network for remote viewing on a range of mobile devices. It features pan, tilt and digital zoom function to allow you to see a wider area with a single camera, built-in Wi-Fi extender to effortlessly expand your wireless coverage, night vision up to 5 metres, sound and motion detection for the ultimate in peace of mind, and H.264 video compression for a high-quality image.”
This walkthrough demonstrates just how easy it can be to find vulnerabilities in Internet of Things (IOT) devices. The process of finding the following command injection can be broken down into 3 steps that are more akin to a 100 point CTF challenge: download binary, run strings, trace input to system call to origin.
Extracting the Firmware
As with any IoT device, the first thing we need to do (if we have access to it) is extract the filesystem from the firmware image. In the case of this device, a first binwalk scan doesn’t really show anything up:
What we’re looking for is some form of embedded filesystem, such as squashfs. In the case where we don’t find one it’s usually because layered compression has been used. All we need to do here is run binwalk recursively using the –M option. It turns out the cpio filesystem is found under 2 layers of compression.
With the camera’s files, let’s take a look at the httpd binary responsible for the webserver.
As I mentioned at the start, let’s do the simplest thing and just run strings on the binary and see what turns up:
Those look like commands passed to system. The ‘sed’ command here is the interesting one, it looks like it’s taking input from somewhere. The next step involves tracing the input to see if we can control it (spoiler alert: we can).
We can see here there’s two functions that reference the string we’re interested in.
In turn, each of these functions is referenced in setFormDefineManagement:
These are both POST forms that we can send requests to. For example, if we change the password in the following form, we make a POST request to setSystemAdmin:
It should be noted that you need admin credentials to access this page, more on that later. A further note is that the setSystemUserModify form always returns a 404, so we stick to analysing setSystemAdmin instead.
So starting in sub_42DCCC the code gets values from non-volatile RAM as well as from websGetVar.
One crucial bit of information here is the call to CheckSystemVar, this code calls websGetVarCheck on a whole bunch of input values, including AdminID.
websGetVarCheck then calls checkVarString, which looks like this:
Not so much fun to reverse, but it’s obviously just one huge switch/case statement. The value we are interested in is AdminID, and we see that it has to have a value less than 13 bytes.
So we know a constraint for the AdminID is that it has to be less than 13 bytes. After all of this, a call to DoSystem is made with our AdminID parameter passed in the format string.
As is obvious here, an attacker can escape the ‘sed’ command with a simple payload, such as ‘`touch a`’. Another example that fits is AdminID=a’`telnetd`’, which allows a user to login as “a”, which becomes the new root account:
Note that we login with a blank password.
It was also found that we could segfault the web server by sending a long password in most of the password fields. If we send 198 bytes, the service would segfault, and anything over that would cause a bus error.
Unfortunately, I couldn’t find a way to get gdbserver onto the device, nor could I dump a core file and grab that.
Below is an example when a POST request is made to /setSystemNetwork with a DDNSPassword parameter of 210 A’s.
An attacker with credentials could use this vulnerability to cause a denial of service on the camera’s web interface. This could also lead to RCE if we could get a way of debugging the binary onto the device.
Currently, there are almost 7000 of these devices connected to the internet:
Affected Version – Firmware 1.14.09
Affected Binary – Alphapd – ea622a926c435e4637f4852536aafa8c
Credits – Tim Carrington – Part of Fidus’ Research Team
Patch – DLink’s announcement
21/11/17 – Disclosed to vendor, response received by William Brown, sent to R&D
29/11/17 – CVE requested from MITRE, assigned CVE 2017-17020. This was then sent to Dlink to update them. W. Brown responded asking when the public disclosure date is, I informed him that there is no date set, made him aware that public disclosure would only occur once a patch is released.
27/04/18 – Dlink’s fix goes live
27/04/18 – Blog goes live and CVE updated