Sunday, August 25, 2013

SIMET Box Firmware Analysis: Embedded Device Hacking & Forensics

For my first blog post I decided to have a quick look on the firmware from SIMET Box. SIMET is organized by the Brazilian NIC.br in order to test and monitor the Internet speed across the country. For more info (in portuguese) visit their site here. All the data collected is available to the community on reports and heat maps like this.

The organization is now handing out free Wi-Fi routers to Brazilians in order to measure the Internet quality on different regions. The SIMET Box equipment is a custom TL-WR740N pre-installed with OpenWRT. You can also download and install the standalone firmware on other TPLink's SOHO routers.



The project is quite interesting but in times of PRISM and NSA I don't like the idea of using a "black box" at home, so I decided to check its design.

Firmware

As I don't have the actual box, I'll analyze SIMET Box's firmware image. The firmware can be downloaded from http://simet.nic.br/firmware. For this initial analysis I'll be using simetbox-tl-wr740n-v4.bin (MD5 d08798093e1591bece897671e96b5983).


Let's start by using Craig Heffner's binwalk and firmware-mod-kit to unsquash the filesystem:

binwalk -Me simetbox-tl-wr740n-v4.bin


After extracting the files we can browse through the squashfs-root dir and grep files to identify OpenWrt's version base:


We now know that SIMET Box is based on Attitude Adjustment branch (v12.09) for Atheros AR71xx, downloadable on OpenWRT's official site: openwrt-ar71xx-generic-tl-wr740n-v4-squashfs-factory.bin.

After extracting the base firmware (using binwalk) we now have two directory trees to diff. We can use WinMerge or Kdiff3 to compare files.


 

There are some new init.d scripts like atualiza_arqs, autossh, miniupnpd and zabbix_agentd:


Lots of binaries (/bin/busibox for example) are quite similar: they may have a small version difference or were compiled using particular command line arguments:


List of files created by SIMET Box (not present on the OpenWrt's base firmware):
while read -r i ; do file $i ; done < list.txt
/etc/config/autossh: ASCII text
/etc/config/upnpd: ASCII text
/etc/dropbear/authorized_keys: OpenSSH DSA public key
/etc/dropbear/id_rsa: data
/etc/hotplug.d/button/00-button: ASCII text
/etc/hotplug.d/iface/20-autossh: POSIX shell script, ASCII text executable
/etc/hotplug.d/iface/50-miniupnpd: POSIX shell script, ASCII text executable
/etc/init.d/atualiza_arqs_simet: POSIX shell script, ASCII text executable
/etc/init.d/autossh: POSIX shell script, ASCII text executable
/etc/init.d/miniupnpd: POSIX shell script, ASCII text executable
/etc/init.d/zabbix_agentd: POSIX shell script, ASCII text executable
/etc/rc.d/S11sysctl: symbolic link to `../init.d/sysctl'
/etc/rc.d/S19firewall: symbolic link to `../init.d/firewall'
/etc/rc.d/S45atualiza_arqs_simet: symbolic link to `../init.d/atualiza_arqs_simet'
/etc/rc.d/S60zabbix_agentd: symbolic link to `../init.d/zabbix_agentd'
/etc/rc.d/S80autossh: symbolic link to `../init.d/autossh'
/etc/rc.d/S95miniupnpd: symbolic link to `../init.d/miniupnpd'
/etc/uci-defaults/50-reset: POSIX shell script, ASCII text executable
/etc/uci-defaults/50-reset-wps: POSIX shell script, ASCII text executable
/etc/uci-defaults/50-wifi: POSIX shell script, ASCII text executable
/etc/uci-defaults/99-miniupnpd: POSIX shell script, ASCII text executable
/etc/uci-defaults/luci-i18n-portuguese_brazilian: POSIX shell script, UTF-8 Unicode text executable
/etc/uci-defaults/luci-theme-bootstrap: POSIX shell script, ASCII text executable
/etc/uci-defaults/luci-upnp: POSIX shell script, ASCII text executable
/etc/zabbix_agentd.conf: ASCII text
/lib/libpthread-0.9.33.2.so: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked (uses shared libs), corrupted section header size
/lib/libpthread.so.0: symbolic link to `libpthread-0.9.33.2.so'
/root/.ssh/known_hosts: ASCII text, with very long lines
/sbin/fw3: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/bin/auto_upgrade: symbolic link to `simet_tools'
/usr/bin/checa_udhcpc.sh: POSIX shell script, ASCII text executable
/usr/bin/get_mac_address.sh: POSIX shell script, ASCII text executable
/usr/bin/simet_client: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/bin/simet_dns: symbolic link to `simet_tools'
/usr/bin/simet_porta25: symbolic link to `simet_tools'
/usr/bin/simet_tools: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/bin/sshreversetunnel: POSIX shell script, ASCII text executable
/usr/bin/teste_spoofing.sh: POSIX shell script, ASCII text executable
/usr/bin/wifionoff: POSIX shell script, ASCII text executable
/usr/lib/lua/luci/controller/simet.lua: ASCII text
/usr/lib/lua/luci/controller/upnp.lua: ASCII text
/usr/lib/lua/luci/i18n/base.pt-br.lmo: data
/usr/lib/lua/luci/i18n/upnp.ca.lmo: data
/usr/lib/lua/luci/i18n/upnp.cs.lmo: data
/usr/lib/lua/luci/i18n/upnp.de.lmo: data
/usr/lib/lua/luci/i18n/upnp.es.lmo: data
/usr/lib/lua/luci/i18n/upnp.fr.lmo: data
/usr/lib/lua/luci/i18n/upnp.hu.lmo: data
/usr/lib/lua/luci/i18n/upnp.it.lmo: data
/usr/lib/lua/luci/i18n/upnp.ja.lmo: data
/usr/lib/lua/luci/i18n/upnp.no.lmo: data
/usr/lib/lua/luci/i18n/upnp.pl.lmo: data
/usr/lib/lua/luci/i18n/upnp.pt-br.lmo: data
/usr/lib/lua/luci/i18n/upnp.pt.lmo: data
/usr/lib/lua/luci/i18n/upnp.ro.lmo: data
/usr/lib/lua/luci/i18n/upnp.ru.lmo: data
/usr/lib/lua/luci/i18n/upnp.vi.lmo: data
/usr/lib/lua/luci/i18n/upnp.zh-cn.lmo: data
/usr/lib/lua/luci/model/cbi/upnp/upnp.lua: ASCII text
/usr/lib/lua/luci/sgi/uhttpd.lua: ASCII text
/usr/lib/lua/luci/view/admin_status/index/upnp.htm: ASCII text
/usr/lib/lua/luci/view/simet/simet.htm: HTML document, UTF-8 Unicode text
/usr/lib/lua/luci/view/themes/bootstrap/footer.htm: HTML document, ASCII text
/usr/lib/lua/luci/view/themes/bootstrap/header.htm: HTML document, ASCII text
/usr/lib/lua/luci/view/upnp_status.htm: HTML document, ASCII text
/usr/lib/opkg/info/autossh.conffiles: ASCII text
/usr/lib/opkg/info/autossh.control: ASCII text
/usr/lib/opkg/info/autossh.list: ASCII text
/usr/lib/opkg/info/hping3.control: ASCII text
/usr/lib/opkg/info/hping3.list: ASCII text
/usr/lib/opkg/info/libip6tc.control: ASCII text
/usr/lib/opkg/info/libip6tc.list: ASCII text
/usr/lib/opkg/info/libnfnetlink.control: ASCII text
/usr/lib/opkg/info/libnfnetlink.list: ASCII text
/usr/lib/opkg/info/libopenssl.control: ASCII text
/usr/lib/opkg/info/libopenssl.list: ASCII text
/usr/lib/opkg/info/libpcap.control: ASCII text
/usr/lib/opkg/info/libpcap.list: ASCII text
/usr/lib/opkg/info/libpthread.control: ASCII text
/usr/lib/opkg/info/libpthread.list: ASCII text
/usr/lib/opkg/info/luci-app-simet.control: ASCII text
/usr/lib/opkg/info/luci-app-simet.list: ASCII text
/usr/lib/opkg/info/luci-app-upnp.control: ASCII text
/usr/lib/opkg/info/luci-app-upnp.list: ASCII text
/usr/lib/opkg/info/luci-i18n-portuguese-brazilian.control: ASCII text
/usr/lib/opkg/info/luci-i18n-portuguese-brazilian.list: ASCII text
/usr/lib/opkg/info/luci-sgi-uhttpd.control: ASCII text
/usr/lib/opkg/info/luci-sgi-uhttpd.list: ASCII text
/usr/lib/opkg/info/luci-theme-bootstrap.control: ASCII text
/usr/lib/opkg/info/luci-theme-bootstrap.list: ASCII text
/usr/lib/opkg/info/miniupnpd.conffiles: ASCII text
/usr/lib/opkg/info/miniupnpd.control: ASCII text
/usr/lib/opkg/info/miniupnpd.list: ASCII text
/usr/lib/opkg/info/simet-base-files.control: ASCII text
/usr/lib/opkg/info/simet-base-files.list: ASCII text
/usr/lib/opkg/info/simet-client.control: ASCII text
/usr/lib/opkg/info/simet-client.list: ASCII text
/usr/lib/opkg/info/simet-tools.control: ASCII text
/usr/lib/opkg/info/simet-tools.list: ASCII text
/usr/lib/opkg/info/uhttpd-mod-lua.control: ASCII text
/usr/lib/opkg/info/uhttpd-mod-lua.list: ASCII text
/usr/lib/opkg/info/zabbix-agentd.control: ASCII text
/usr/lib/opkg/info/zabbix-agentd.list: ASCII text
/usr/lib/opkg/info/zlib.control: ASCII text
/usr/lib/opkg/info/zlib.list: ASCII text
/usr/lib/libcrypto.so.1.0.0: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libip6tc.so: symbolic link to `libip6tc.so.0.0.0'
/usr/lib/libip6tc.so.0: symbolic link to `libip6tc.so.0.0.0'
/usr/lib/libip6tc.so.0.0.0: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libjson-c.so.2: symbolic link to `libjson-c.so.2.0.1'
/usr/lib/libjson-c.so.2.0.1: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libnfnetlink.so.0: symbolic link to `libnfnetlink.so.0.2.0'
/usr/lib/libnfnetlink.so.0.2.0: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libpcap.so: symbolic link to `libpcap.so.1.1'
/usr/lib/libpcap.so.1.1: symbolic link to `libpcap.so.1.1.1'
/usr/lib/libpcap.so.1.1.1: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libssl.so.1.0.0: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/libz.so: symbolic link to `libz.so.1.2.7'
/usr/lib/libz.so.1: symbolic link to `libz.so.1.2.7'
/usr/lib/libz.so.1.2.7: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/lib/uhttpd_lua.so: ELF 32-bit MSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, corrupted section header size
/usr/sbin/autossh: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/sbin/hping3: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/sbin/miniupnpd: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/sbin/zabbix_agentd: ELF 32-bit MSB executable, MIPS, MIPS32 rel2 version 1, dynamically linked (uses shared libs), corrupted section header size
/usr/share/libiwinfo/hardware.txt: ASCII text
/usr/share/miniupnpd/firewall.include: POSIX shell script, ASCII text executable
/www/luci-static/bootstrap/cascade.css: assembler source, ASCII text
/www/luci-static/bootstrap/favicon.ico: MS Windows icon resource - 1 icon
/www/luci-static/bootstrap/html5.js: HTML document, ASCII text, with very long lines
/www/simet/ceptro.png: PNG image data, 78 x 30, 8-bit colormap, non-interlaced
/www/simet/cgi.png: PNG image data, 46 x 30, 8-bit colormap, non-interlaced
/www/simet/nic.png: PNG image data, 47 x 25, 8-bit colormap, non-interlaced
/www/simet/nonet.htm: UTF-8 Unicode text
/www/simet/offline.jpg: JPEG image data, EXIF standard
/www/simet/simetbox_minilogo.png: PNG image data, 111 x 23, 8-bit colormap, non-interlaced
/www/simet/view_tab.css: assembler source, ASCII text
/www/simet/view_tab.js: UTF-8 Unicode text, with very long lines

This simple technique is quite useful for forensic analysis of embedded devices, as you have a white-list of known binaries and config files. It's important to review both created and modified files, but I'll focus on the ones listed above. Each binary and config file can be reviewed separately so we can find interesting entries like:

  • SSH reverse tunnel settings and authorized_keys:
  • Password changing scripts and Iptables rules:

  • The device management starting page has an external iframe and users are identified by their MAC Address via HTTP GET requests:

  • Cronjobs to test external access to port 25 and if the ISP allows IP spoofing:
  • Script using hping3 to test if the user's ISP allows packet spoofing:

  • Zabbix agent settings:

As a quick advice to SIMET engineers, it would be nice to have HTTPS for those external queries, a bit more of transparency on what the equipment does internally, who's able to access it (whose authorized_keys are those?), what external IP addresses it communicates with and what information is being collected. Securing SOHO modems is very important, specially here in Brazil where lots of recent attacks were targeting these devices (Fabio Assolini's talk "The tale of one thousand and one DSL modems" detailed this a year ago).

On the next post I'll detail how to run those MIPS32 binaries on a virtual environment using QEMU and analyze some of the files with IDA Pro.

Saturday, August 24, 2013

Hello world

I just started this new Blog to talk about some personal projects, exploits and hacking in general. I'm a Brazilian Infosec guy interested on embedded device hacking (modems, routers etc), webapp security, console hacking and forensics. My twitter handle is @bernardomr, feel free to ping me.