The Zyxel WRE2205
The Zyxel WRE2205 (rebranded Edimax EW-7303APN V2) is a plug-formed wireless extender. What's interesting to me about this device is its extremely small size. Many of my standard power bricks like are larger than this unit -- but they don't contain a small Linux minicomputer and advanced wireless functionality.
Trying out the WRE2205 for its intended purpose, I discovered that its wireless performance was quite subpar, slower than my actual Internet connection, but still very usable. Of course, that's understandable. It has no antenna. So I replaced it with a faster AirPort Express, which can also act as a wireless bridge.
No longer needing the device for its intended purpose, I thought about how cool it would be to have an actual Linux plug PC I could SSH to and use for all sorts for home automation purposes, or leave it somewhere public, name the SSID "FreeWifi" and install Upside-Down-Ternet. The possibilities are endless!
So I started getting the desire to hack this thing. And having seen some bad router software in the many devices I've owned, I thought that there could be a chance of rooting this thing.
As anyone who've poked around with consumer network equipment knows, a good place to start is binwalk. binwalk is a utility that lists and extracts filesystems embedded in files like router firmware updates. What these "update" files actually do, is that they replace the whole contents of the operating system partition with a completely new version. This is why these devices may "brick" when cutting the power during an upgrade: it may not boot without all the files.
To my delight, binwalk came up with a squashfs filesystem embedded in the latest firmware update from Zyxel's Web site.
simon@workstation:~$ binwalk -v wre2205.bin
Scan Time: 2014-06-18 22:44:24
Signatures: 212
Target File: wre2205.bin
MD5 Checksum: e2aa557aa38e70f376d3a3b7dfb4e36f
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------
509 0x1FD LZMA compressed data, properties:
0x88, dictionary size: 1048576 bytes,
uncompressed size: 65535 bytes
11280 0x2C10 LZMA compressed data, properties: 0x5D,
dictionary size: 8388608 bytes,
uncompressed size: 2019328 bytes
655360 0xA0000 Squashfs filesystem, big endian,
version 2.0, size: 1150773 bytes, 445 inodes,
blocksize: 65536 bytes,
created: Wed Mar 26 04:14:59 2014
binwalk is so great that it can even extract it for us:
simon@workstation:~$ binwalk -Me wre2205.bin
Target File: _wre2205.bin.extracted/2C10
MD5 Checksum: a47fd986435b2f3b0af9db1a3e666cf1
DECIMAL HEX DESCRIPTION
-------------------------------------------------------------
1626688 0x18D240 Linux kernel version "2.4.18-MIPS-01.00
([email protected]) (gcc version
3.4st.localdomain) (gcc version 3.4.6-1.3.6)
#720 Wed Mar 26 11:10"
It's all the files for the park... It tells me everything!
We can see it's a Linux 2.4 MIPS kernel. Good. "I know this", as they say in Jurassic Park.
What we get is a directory containing the whole Linux system. What's interesting is you can see the configuration and especially all the shell scripts. There are so many shell scripts. Also the source for the Web interface is of course included.
However, most of the functionality is actually not written with whatever scripting language it's using. It comes from within the Web server, which apparently is heavily modified. The Web files mainly display some variables and send some forms. Not yet that exciting.
The Web server, by the way, is something called boa, an open source http server. Studying the config file, something interesting is located in the file /etc/boa/boa.passwd. The contents:
root:$1$iNT/snisG/y7YBVbw0tQaaaA
An MD5-hashed password, it seems. A kind of creepy thing because the default username for the admin user is admin, not root. And it's referenced in the Auth directive of boa’s config file. So Zyxel has their own little backdoor. I didn't get to cracking that password, because I moved on to the /web directory, containing all the web files.
The WRE2205 Web Interface
The standard things are there, of course. The jQuery library (version 1.7), some JavaScript, some graphics and some language files. The standard header/footer pages (in this case, though, because Zyxel is stuck in the 1990s, a frameset), and so on.
Beginning to look through file filenames, two interesting ones were to find: /web/debug.asp and /web/mp.asp. None of these are referenced in the "public" Web interface. Having access to debug files is always a good thing when trying to break into something.
The first file, debug.asp, looks like a password prompt of some sort.
One might reasonably assume it has something to do with showing some different log files, despite the weird sentence structure. No clues in the config file, and typing some random passwords didn't work (1). Let's move on. The next file, mp.asp, looks much more interesting:
There are several good signs here despite the rather minimalist interface. First, it actually looks like a command prompt: the text box selects itself upon loading the page, there's a # sign, usually an indicator of a system shell. Here there was also a clue in the source code, the input field's name is actually command. Simply entering nothing and pressing GO yields the following result:
Bingo. It seems to launch a shell script where the input box is the parameter. Let's take a look at this rftest.sh fellow:
Lots of different debug commands that yield different things. So, entering ENABLEWIRELESS in the prompt would run /bin/rftest.sh ENABLEWIRELESS and return the output in HTML. (I have no idea what "interface" and yes/no switch does, entering eth0 doesn't work, so maybe it's an example?)
At the bottom there's even a COMMAND command that allows us to execute any command. At least they tried to make this a little secure by limiting the applications you can execute:
"COMMAND")
if [ "$2" = "ifconfig" ] || [ "$2" = "flash" ] || [ "$2" = "cat" ]
|| [ "$2" = "echo" ] || [ "$2" = "cd" ] || [ "$2" = "sleep" ]
|| [ "$2" = "kill" ] || [ "$2" = "iwpriv" ] || [ "$2" = "reboot" ]
|| [ "$2" = "ated" ] || [ "$2" = "AutoWPA" ]; then
$2 $3 $4 $5 $6
fi
;;
But, at this point there's really no point, since doing stuff like this will be completely broken in any case, and we can just do something like this:
And so we have full control. Since || means OR, and the rftest.sh command fails when there's no valid command, the last command will be run.
As we can see from the above screenshot, the web server is running as root so now we have full control of the little plug computer. Software like wget comes preinstalled, so you can just go ahead and download shell scripts, an SSH server, or otherwise have fun on the 1.5 megabytes of space you have to play with. Good luck!
I kind of expected that I had to use an exploit or buffer overflow, get out a disassembler like IDA, or do a port scan, or do some more digging -- but just below the surface there are some quite big security issues. Of course, you need to know the admin password since the whole /web directory is behind Basic authentication.
However, since the boa webserver is an old version with exploits available, you probably won't even need that. We can assume it's not a feature since it's hidden. So with such a big hole, I wonder what else lies below the surface?
Footnotes:
- I later found, by running strings on the http server executable, that typing report.txt shows some debug information.