Friday, February 01, 2013

DLink DIR-815 UPnP Command Injection

With all the excitement regarding UPnP vulnerabilities lately, I though I'd write up this one I found a few weeks back.  I had kind of forgotten about it.  But it's pretty straight forward, and kind of fun, so here it is.

In Tactical Network Solutions' Intro to Embedded Device Exploitation class, we use the D-Link DIR-815 for the practical exercises since there are tons of great 0-days for the students to find.  The last time we taught the class, I thought I'd try my hand at finding a new one. Twenty minutes in, voila! Command injection in a single multicast packet!

The DIR-815 has a single binary executable, /htdocs/cgibin, that is responsible for handling most, if not all, HTTP requests.  I found a symlink to cgibin called 'ssdpcgi':

zach@endor: dir-815-reva1/v1.00/squashfs-root/htdocs (0) $ ls -l upnp/ssdpcgi
lrwxrwxrwx 1 zach wheel 14 Jan  9 13:43 upnp/ssdpcgi -> /htdocs/cgibin

If we disassemble cgibin and look at ssdpcgi_main(), we see it executing a shell script called "/etc/scripts/upnp/M-SEARCH.sh".

IDA Screenshot: A shell script gets excecuted with the contents of the ST field as an argument.
A shell script gets excecuted with the contents of the ST field as an argument.
So let's look at M-SEARCH.sh:



The contents of the M-SEARCH packet get turned into shell arguments.  If we can get one of the arguments to be a string inside backticks, the string gets executed by system()'s 'sh -c' and its output gets handed to M-SEARCH.sh as arguments.

So what if we send an M-SEARCH packet with the ST: field containing the string `reboot`?

M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
ST:uuid:`reboot`
MX:2
MAN:"ssdp:discover"

If we send that packet to the 239.255.255.250 multicast address, on UDP port 1900, our D-Link router reboots! Nice!

But rebooting routers is bullshit.  Root or it didn't happen, right?  Okay, no problem.  D-Link routers generally come with a telnet server onboard, so lets use the command injection to fire it up:

Getting root via command injection on the D-Link DIR-815 wireless router

Ownage in a single multicast packet.  Not bad for 20 minutes of strings analysis and a few lines of Python.


Here's some proof-of-concept python code to try out.