Security warning! unpatched backdoor in latest (version 3.1.0.2) firmware. Site seems down (Wayback Machine or PDF) |
Work in Progress! This page is a continuous work in progress. You can edit this page to contribute information |
Conflicting information, please clarify!
CPU | Ram | Flash | Network | USB | Serial | JTAG |
---|---|---|---|---|---|---|
Ralink RT3883 | 64MiB | 8MiB | 4 x 1 | Yes | Yes | ? |
Architecture: | MIPS 74Kc |
Vendor: | Sitecom |
bootloader: | U-Boot |
System-On-Chip: | Ralink RT3883 |
CPU/Speed | 500 MHz |
Flash-Chip: | Macronix MX25L6406E (not 05D) |
Flash size: | 8192 KiB |
RAM: | 64 MiB (Nanya NT5TU32M16DG-AC) |
Wireless: | Ralink RT3883 |
Wireless: | Ralink RT5392 |
Ethernet: | Atheros AR8327 |
USB: | Yes 1 x 2.0 |
Serial: | Yes |
JTAG: | ? |
Note: This will void your warranty!
Serial console is available on the J12 connector, 3.3V signals. See photo top, right side of the PCB just above the USB port. Pin 1 (bottom) has a small white triangle near it. The pitch is 0.1“. The solder can be removed with a 0.8 mm drill.
4 = RxD in
3 = TxD out
2 = GND
1 = Vcc 3.3V
DO NOT CONNECT Vcc. Use only TxD, RxD and GND.
Baud Rate: 57600
Data Bits: 8
Parity : No
Stop Bits: 1
With the front towards you and from left to right:
Description | 1 | 2 | Unpopulated | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|---|
Name | OPS | Power | n/a | 2.4 GHz | 5 GHz | WAN | LAN4 | LAN3 | LAN2 | LAN1 |
Color | White | Red | n/a | Blue | White | Blue | Blue | Blue | Blue | Blue |
PCB label | D11 | D2 | D8/D9 | D10 | D14 | D7 | D6 | D5 | D4 | D3 |
GPIO | 0 | 1 | unknown | RT5392 | RT3883 | Switch | Switch | Switch | Switch | Switch |
Notes: LEDs are “ACTIVE LOW”. WiFi LED 2.4 GHz / 5 GHz is on when WiFi is ON. LAN1/4 and WAN is ON when a cable is attached and blinks during activity.
Description | 1 | Unpopulated |
---|---|---|
Name | OPS | n/a |
PCB label | S3 | S6 |
GPIO | 26 | Unknown |
Notes: Buttons are “ACTIVE LOW”
Factory function OPS button:
Press 0-5 seconds for 2.4 GHz WPS mode |
Press 5-10 seconds for 5 GHz WPS mode |
Press 10 seconds to reset the router |
Press 15 Seconds to reset the router to factory defaults |
U-boot Ver:1.0.6.193 2011/09/22 Board: Ralink APSoC DRAM: 64 MB spi_wait_nsec: 48 spi device id: c2 20 17 c2 20 (2017c220) find flash: MX25L6405D raspi_read: from:30000 len:1000 .raspi_read: from:30000 len:1000 .============================================ ASIC 3883_MP (MAC to GigaPHY Mode) Product Name: WLR-6000 icache: sets:512, ways:4, linesz:32 ,total:65536 dcache: sets:256, ways:4, linesz:32 ,total:32768 Please choose the operation: 1: Load system code to SDRAM via TFTP. 3: System Boot system code via Flash. raspi_read: from:50000 len:40 .raspi_read: from:50040 len:1495fb ..................... LINUX started... THIS IS ASIC The CPU feqenuce set to 500 MHz spi flash -->[MX25L6405D] init started: BusyBox v1.7.5 (2011-12-12 15:13:23 CST) starting pid 216, tty '/dev/console': '/sbin/config_init' Config Init version: 2.0.1.16 date: 2011/12/12 starting pid 268, tty '/dev/ttyS1': '/sbin/config_term' ************************************************************************ * WLR-6000 * ************************************************************************ KernelApp/Ramdisk Ver:2.0.1.16 Date:2011/12/12 console> cat: can't open '/apps/lib/modules/2.6.21/modulesApp.dep': No such file or directory ln: /sbin/./apps_init: File exists ln: /sbin/./opmode.sh: File exists sh: cannot create /proc/switch/power_status: nonexistent directory sh: cannot create /proc/switch/power_status: nonexistent directory sh: cannot create /proc/switch/power_status: nonexistent directory
The following layout is for firmware version 3.1.0.2 and obtained with the root shell:
# cat /proc/mtd dev: size erasesize name mtd0: 00030000 00001000 "Bootloader" mtd1: 00010000 00001000 "Config " mtd2: 00008000 00001000 "Factory" mtd3: 00008000 00001000 "iNIC_rf" mtd4: 00713000 00001000 "Kernel" mtd5: 005ca000 00001000 "app" mtd6: 0007d000 00001000 "manufacture" mtd7: 00010000 00001000 "backup" mtd8: 00010000 00001000 "storage"
The following experiments give hopefully the necessary information to install OpenWrt on this router. There are two routes to tackle the challenge: by dissecting the firmware and through serial connection. Sometimes there is a third route through telnet or ssh but both can't be started in the web-interface. When the GPL source code is available it can also give information. However in most cases the released GPL is incomplete or has configuration settings for other router models. This route is only usefull if the other routes fail...
A request for the latest firmware gave a direct (alternative) link. The zip contains a .dlf and that is an encrypted uImage with an extra header. The encryption is just a xor with key 0x783c9ecf67b359ac which is derived from the magic number 0x12345678 and a formula. Sitecom is a Senao ODM so we can use mksenaofw (soure or binary in OpenWrt-SDK):
hvdkamer@idefix:~/sitecom$ ./mksenaofw -t 2 -r 2 -p 2 -d WLR-6000-V1001-FW-V3-1-0-2.dlf -o wlr-6000-firmware-31.bin hvdkamer@idefix:~/sitecom$ ls -l ... -rw-rw-r-- 1 hvdkamer hvdkamer 3711093 mei 23 2012 WLR-6000-V1001-FW-V3-1-0-2.dlf -rw-rw-r-- 1 hvdkamer hvdkamer 3710997 sep 2 14:45 wlr-6000-firmware-31.bin
The DLF-header is 96 bytes in size and stripped in the output. What remains is a normal U-Boot image as shown by binwalk:
hvdkamer@idefix:~/sitecom$ binwalk wlr-6000-firmware-31.bin DECIMAL HEX DESCRIPTION ------------------------------------------------------------------------------------------------------- 0 0x0 uImage header, header size: 64 bytes, header CRC: 0x9999C04D, created: Tue May 22 14:06:10 2012, image size: 1345140 bytes, Data Address: 0x80000000, Entry Point: 0x802CE000, data CRC: 0xF42EE226, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image" 64 0x40 LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 3402046 bytes 1347584 0x149000 Squashfs filesystem, little endian, non-standard signature, version 3.0, size: 2360085 bytes, 332 inodes, blocksize: 65536 bytes, created: Tue May 22 14:04:34 2012
In the first experiment we decoded the firmware. This router uses U-Boot so we found a uImage with binwalk. This contains a kernel and Squashfs filesystem. For initializing it is common to use a small initial root which contains the necessary binaries to initialize and load the final root. Nowadays the initial root is a initramfs which is added right after the kernel. So kernel and initramfs are one. To see if this is the case we extract the kernel from the firmware:
hvdkamer@idefix:~/sitecom$ dd bs=64 skip=1 count=21055 if=wlr-6000-firmware-31.bin of=kernel.7z
The bs=64 and skip=1 skips the first 64 bytes which are the uImage header. The count=21055 extracts this number of 64 bytes as indicated by the bs. This gives 1.347.520 which is the starting point of the Squashfs filesystem minus again the uImage header length. In the binwalk we saw 0x5D and that is the old LZMA format (used by lzma_alone) which can only be extracted by 7z (Ubuntu p7zip-full package) which explains the given extension for the output of dd. Extracting is simple:
hvdkamer@idefix:~/sitecom$ 7z e kernel.7z hvdkamer@idefix:~/sitecom$ binwalk kernel DECIMAL HEX DESCRIPTION ------------------------------------------------------------------------------------------------------- ... 2564096 0x272000 Linux kernel version "2.6.21 (root@kevin) (gcc version 4.3.4 (Buildroot 2010.05) ) #2n 4.3.4 (Buildroot 2010.05) ) #2 Tue May 22 20:06:07 CST 20122 Tue May 22 20:06:07 CST 2012" ... 3072000 0x2EE000 LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 1176576 bytes
The binwalk gives a lot of false positives but the shown one is promising. It has a size which is reasonable and also has the 0x5D variation of LZMA. Let's extract this one:
hvdkamer@idefix:~/sitecom$ dd bs=1 skip=3072000 if=kernel of=initramfs.bin.7z hvdkamer@idefix:~/sitecom$ 7z e initramfs.bin.7z hvdkamer@idefix:~/sitecom$ mkdir initramfs hvdkamer@idefix:~/sitecom$ cd initramfs/ hvdkamer@idefix:~/sitecom/initramfs$ cpio --no-absolute-filenames -i < ../initramfs.bin cpio: Removing leading `/' from member names cpio: dev/kmem: Cannot mknod: Operation not permitted ...
The --no-absolute-filenames is needed because all files in the initramfs are relative to / (root). The files in /dev can only be created by root and not a normal user which explains the error message. Afterwards we have a filesystem which the usual directories.
As expected most commands are done by symlinks to busybox. In the root we have a init-symlink which is started by the kernel after it is done starting. The init is nothing fancy as shown in /etc/inittab:
console::sysinit:/sbin/config_init ttyS1::respawn:/sbin/config_term ::ctrlaltdel:/etc/reboot.sh ::shutdown:/etc/reboot.sh ::shutdown:/etc/reboot.sh /sbin/swapoff -a
The console-line is started by default and the ttyS1 when we connect through a serial connection. The strings command shows an important password:
hvdkamer@idefix:~/sitecom/initramfs$ strings sbin/config_term ... password: lin17 /bin/sh console> admin /sbin/cli /sbin/manufac_test SitecomSenao !!! wrong password !!! ...
It seems that lin17 is a hardcoded password for the serial connection. On version 2.0 of the firmware it is sn2450 and both are found all over the internet and in this wiki as well. Luckily a serial connection usually works only with physical access.
As expected there is not a lot of interesting stuff in the initramfs. This part is only used to initialize. In the first experiment we found a Squasfs filesystem. Let's extract and analyze this:
hvdkamer@idefix:~/sitecom$ dd bs=64 skip=21056 if=wlr-6000-firmware-31.bin of=rootfs.7z hvdkamer@idefix:~/sitecom$ mkdir rootfs hvdkamer@idefix:~/sitecom$ cd rootfs hvdkamer@idefix:~/sitecom/rootfs$ 7z x ../rootfs.7z ... Extracting usr/sbin/pppd Everything is Ok Folders: 36 Files: 295 Size: 8023078 Compressed: 2363413
In this case we use x instead of e because there is a directory structure. We find a httpd binary which probably uses etc/web_scr/ in this filesystem. A cgi-bin directory is missing so the communication between hardware and web interface is done in a different way. There is a sbin/utelnetd but the old trick doesn't work because of the missing cgi-bin directory. May be someone can find a bug in the web interface to execute this binary?
The analyses of the firmware in the first four experiments only gives a glance at how the software works. For more understanding we have to have shell access. The found utelnetd is promising, but without a way to start it from the web interface it is at the moment useless. The next step is a serial connection. That gives us also access to the U-Boot. Press one of the following options immediately after the first text appears. A complete bootlog from powering on to pressing a number is available (keuze is Dutch for choice).
From the first experiment we know that option 4 gives the U-Boot prompt. The following changes the default op_mode from 0 to 1. That gives more information during boot. Give the following commands (without the RT3883 # prompt):
RT3883 # printenv RT3883 # setenv op_mode 1 RT3883 # saveenv RT3883 # reset
In the initramfs a sbin/opmode.sh can be found with the following explanation:
echo " 0:Set to Normal Mode" echo " 1:Set to Normal Operation with Debug Messages" echo " 2:Set to Developer Mode 2" echo " 3:Set to Factory Mode" echo " r:Read Operation Mode"
So there is also an option 2 and 3. The r is only used in the shell script to read the current value. The others are set in the U-Boot environment.
In the sixth experiment we got a lot more information. Lost in the output is a password: prompt. Press enter:
!!! wrong password !!! password:
Ignore the error, type lin17 (on older firmware use Ctrl-C instead of enter with password sn2450) and press enter again. This gives a root shell. The password was found in the third experiment.
In experiments 2 and 4 we found two filesystems. How are these combined into a running system? Let's see:
# mount none on /sys type sysfs (rw) /dev/mtdblock8 on /storage type jffs2 (rw) /dev/mtdblock5 on /apps type squashfs (ro) none on /proc/bus/usb type usbfs (rw)
So in the initramfs an /apps and /storage directory are created. On the first the Squashfs filesystem is mounted. The filesystem on /storage is not part of the firmware and contains probably configuration data. In /sbin and /bin extra symlinks appear which points to /apps/sbin and /apps/bin binaries. The utelnetd found in 4 can be started, but disconnects after a minute or so of no activity.
The root shell doesn't have many commands. But enough to extract (and thus back-up) the flash partitions. First let's see some information:
# cat /proc/mtd dev: size erasesize name mtd0: 00030000 00001000 "Bootloader" mtd1: 00010000 00001000 "Config " mtd2: 00008000 00001000 "Factory" mtd3: 00008000 00001000 "iNIC_rf" mtd4: 00713000 00001000 "Kernel" mtd5: 005ca000 00001000 "app" mtd6: 0007d000 00001000 "manufacture" mtd7: 00010000 00001000 "backup" mtd8: 00010000 00001000 "storage"
The storage and app are mounted and the Kernel is of course the kernel and initramfs. The easiest way to do the back-up is creating them on a flash drive. Probably a FAT formatted one will work, but we tested it with an ext3 partition. After plugging in:
# No disk exist for sda ==>OK No disk exist for sda1 USBMGR, add usb device (0x0781:0x5151@/tmp/usb/sda1) KC_SAMBA, usb event (add:/tmp/usb/sda1) received [KCODES]---> mount point:[/tmp/usb/sda1] ==>OK ==>OK ==>OK ==>OK ==>OK
For the extraction/back-up (don't type the # prompt) do:
# for i in 0 1 2 3 4 5 6 7 8; do cat /dev/mtdblock$i > /tmp/usb/sda1/mtd$i; done
The md5sum-program is available and could be used directly on the cat-output and created files.
After the back-up we have more bytes than the 8 MiB available the flash memory of this router. For the firmware upgrade it seems logical that mtd5 is part of a larger mtd4. If we added the sizes of all partitions except mtd5 the result is 8 MiB. Which gives the following flash lay-out:
In the first experiment we decoded the firmware. It seems logical that the resulting file is written to mtd4 and that the system knows where the kernel plus initramfs ends and the apps (mtd5) starts. Let's see:
hvdkamer@idefix:~/sitecom$ dd ibs=1 count=3710997 if=mtd4 of=mtd4_firmware-31 hvdkamer@idefix:~/sitecom$ md5sum wlr-6000-firmware-31.bin mtd4_firmware-31 5e0ade696caf1f37ff07584e7d081f7e wlr-6000-firmware-31.bin 5e0ade696caf1f37ff07584e7d081f7e mtd4_firmware-31
The decode firmware is 3.710.997 bytes and that's the amount we extract from mtd4. And yes, this means that we have enough room for OpenWrt firmware with more than the bare necessities. As shown both the firmware and first part of mtd4 are the same.
In experiment 9 we found a mysterious manufacture-partition. With the back-up we can analyze this as well:
hvdkamer@idefix:~/sitecom$ mkdir manufacture hvdkamer@idefix:~/sitecom$ cd manufacture/ hvdkamer@idefix:~/sitecom/manufacture$ 7z x ../mtd6 ... Extracting lib/RT2860.dat Extracting lib/iNIC_ap.dat Extracting lib/rt2860v2_ap.ko Extracting lib/rt5392_ap.ko Extracting sbin/ated Extracting sbin/linktester Extracting sbin/manufac_test Extracting sbin/mii_mgr Extracting sbin/tftp
In the backdoor the author found two sets of credentials hardcoded in the httpd-binary: senao_sitecom/sn_iktpwd and manufacture/snnsr9750. The first gives full administrative rights for the router. If you haven't changed the default password -- it is derived from the MAC address with the same character set as the WLR-4000 -- on the WiFi, anyone can change the settings if they are close enough. And of course anyone you granted access has this ability too, even if the passwords are changed. The latter activates this partition as shown in the next experiment. Read this first!
Warning This experiments is only advised if you have soldered a serial connection. It is possible to switch to normal mode again without a serial connection back-up route, but seeing what is done plus setting the right op_mode through U-Boot or the opmode.sh is much easier.
First start a new private session in your browser. Modern browsers are way to intelligent and remember passwords and logins during a session even if told not to. If you get back to the normal login-screen most of the times it automagically boots to the manufacture mode again. Now login with manufacture/snnsr9750 and you see:
After this a telnet server with IP-address 192.168.99.9 on the WAN-port is started. The login program is probably manufac_test which has some interesting commands. May be it is possible to get a real shell which would be nice for back-up without soldering. For going back to normal mode (don't type the / #-prompt):
/ # mode user cmd [setconfig -a 2 -s 5 -d 0 ] Setting user mode is ok / # misc saveconfig cmd [setconfig -a 5 ] OK / # misc reboot
Close the private window and try to log in with the normal admin credentials. If the router goes automatically back to the manufacture mode use the above again and use a different browser or computer to break the cycle. As said it is also possible to do this with the serial connection:
# /sbin/opmode.sh 1 # reboot
or in the U-Boot environment with:
RT3883 # printenv RT3883 # setenv op_mode 1 RT3883 # saveenv RT3883 # reset
All three routes do the same thing, setting the mode as described.
It would be nice if we can start the found utelntd. The busybox is compiled with the following commands:
Currently defined functions: [, [[, arp, ash, basename, cat, chmod, cmp, cp, date, df, dmesg, echo, eject, env, expr, grep, halt, hexdump, hostname, id, ifconfig, ifdown, ifup, inetd, init, insmod, ip, ipcs, kill, killall, ln, logger, ls, lsmod, md5sum, mkdir, mknod, modprobe, mv, netstat, nice, pidof, ping, poweroff, printf, ps, pwd, reboot, rm, rmmod, route, sh, sleep, sort, stty, sync, sysctl, syslogd, tail, test, tftp, time, touch, true, tty, uname, uptime, vconfig, wc
The inetd is not started as well. Starting this is easier then the telnet daemon. The latter is not present in the intramfs and there all the initialization is done. With some clever script it should be possible to wait a few seconds and then start utelnetd. But inetd can do this as well. Both routes means changing the Sitecom firmware. The GPL tarball is a mess and probably not complete. However we don't need to compile anything, just adding some lines and configuration files. That could be done with unpacking, make changes and repacking. It would be nice if we don't have to flash right away and that seems possible with option 1 in U-Boot. To test this we setup a TFTP server, give our computer the IP-address 192.168.99.8 and put the extracted firmware in the upload-directory:
hvdkamer@idefix:~/sitecom$ sudo cp wlr-6000-firmware-31.bin /var/lib/tftpboot/uboot.img
Then start the router and when the first text appears press 1. The conversation which follows:
1: System Load Linux to SDRAM via TFTP. Please Input new ones /or Ctrl-C to discard Input device IP (192.168.99.9) ==: Input server IP (192.168.99.8) ==: Input Linux Kernel filename (uboot.img) ==:
With our configuration pressing three times enter boots the firmware loaded in memory. The end result is the same as a normal boot, but proves that we can easily test changed firmware.
In the previous experiment we proved that U-Boot needs an unencrypted uImage firmware and not the encrypted DLF the Sitecom web interface wants. The uImage has four parts: uImage header (64 bytes), kernel, initramfs and rootfs. The initramfs doesn't show in a binwalk but is appended in the kernel part. But before we change this, lets see if we can repackage the kernel and create a uImage header:
hvdkamer@idefix:~/sitecom$ dd bs=64 skip=1 count=21055 if=wlr-6000-firmware-31.bin of=kernel.7z hvdkamer@idefix:~/sitecom$ 7z e kernel.7z hvdkamer@idefix:~/sitecom$ lzma_alone -d25 e kernel kernel2.7z hvdkamer@idefix:~/sitecom$ ls -l ... -rw-rw-r-- 1 hvdkamer hvdkamer 1347520 sep 11 17:10 kernel.7z -rw-rw-r-- 1 hvdkamer hvdkamer 1343817 sep 11 18:14 kernel2.7z
The first two lines are explained in experiment 2. The LZMA compression is implemented by different people all with there own idea of a file format. The 0x5D is the oldest implementation and can be extracted by 7z (Ubuntu p7zip-full package). Compressing again doesn't work or the right parameters are not found yet. The lzma_alone *Ubuntu lzama-alone package) is the original implementation. The -d25 means a directory size op 32 MiB as found in the outputs. The old file is padded with zeros because the Sitecom flash uses 4 KiB erase size. The rootfs must therefor start on a 4 KiB boundary:
hvdkamer@idefix:~/sitecom$ hexdump -C kernel.7z 00148660 13 42 94 1f 0e 6f ae 77 e1 d6 45 22 90 d8 d9 84 |.B...o.w..E"....| 00148670 81 2b 71 00 00 00 00 00 00 00 00 00 00 00 00 00 |.+q.............| 00148680 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 00148fc0
So the real size of the kernel is 0x148674 is 1345140 bytes. One zero is part of the compression. If stripped the 7z gives an error. The size is still larger than the new one (1343817 bytes). Probably because a different program is used in he original firmware. Whatever the reason the only thing needed is a working (re)packaging tool. The next step is adding a uImage header and padding with zeros to a full 4 KiB size. The first can be done with mkimage (Ubuntu u-boot-tools package):
hvdkamer@idefix:~/sitecom$ mkimage -A mips -O linux -T kernel -C lzma -a 80000000 -e 802ce000 -n "Linux Kernel Image" -d kernel2.7z kernel2.uimage hvdkamer@idefix:~/sitecom$ truncate -s 1347584 kernel2.uimage
The parameters were found in the original firmware uImage header (structure). The second command pads with zeros until the specified size (329 blocks of 4 KiB). The kernel2.uimage should boot if loaded in memory through TFTP. That is indeed the case. It even finds the rootfs in the flash chip and starts that as well.