Rooting the Sphairon Speedlink 5501

Last week I was asked if I knew how to enable SSH access on a Sphairon (ZyXEL) Speedlink 5501. My previous technique for the HomeBox 3232 (also manufactured by Sphairon) did not work as the expected magic bytes in the configuration backup file of the Speedlink 5501 could not be found. So I had to reverse this new file format to see, if a similar technique can be applied here.

In this post I will explain the details of this new file format. With this knowledge we can unpack, modify and repack config files. Secondly, I will show you what config options have to be modified, in order to enable SSH access. Unfortunately, I have no time to write a ready-to-use tool this time. But anyone is invited to use these results to code their own unpacker. Please let me know, if you publish something so I can link to it from here.

Reversing the config file format

I downloaded the Firmware V4.37.2.4.4 from Deutsche Telekom. Using binwalk two lzma-compressed SquashFS file systems were easily spotted.

$ ./binwalk -m magic.binwalk Firmware_Speedlink_5501_V4.37.2.4.4.bin

DECIMAL         HEX             DESCRIPTION
-------------------------------------------------------------------------------------------------------
1643075         0x191243        uImage header, header size: 64 bytes, header CRC: 0x7AE0421E, created: Fri Jul 18 16:04:14 2014, image size: 9355264 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0xC9D77E84, OS: Linux, CPU: MIPS, image type: Filesystem Image, compression type: none, image name: rootfs#5.0.10.0.3_r81360_heinzm
1643139         0x191283        Squashfs filesystem, little endian, version 4.0, compression: lzma, size: 9352106 bytes, 1207 inodes, blocksize: 65536 bytes, created: Fri Jul 18 16:04:14 2014
[...]
10998403        0xA7D283        uImage header, header size: 64 bytes, header CRC: 0x2C7ABEA3, created: Fri Jul 18 13:55:41 2014, image size: 6889472 bytes, Data Address: 0x0, Entry Point: 0x0, data CRC: 0x28A47D11, OS: Linux, CPU: MIPS, image type: Filesystem Image, compression type: none, image name: servfs#1.0.0_r81360_heinzm
10998467        0xA7D2C3        Squashfs filesystem, little endian, version 4.0, compression: lzma, size: 6887693 bytes, 886 inodes, blocksize: 65536 bytes, created: Fri Jul 18 13:55:40 2014

These filesystems were unpacked using the squashfs-tools from SquashFS 4.3 on a Debian system running 3.2.60 kernel (read here why this is important).

After browsing the first filesystem (named rootfs) it turned out, that it most likely contained no code related to the config file handling. So I started to investigate the second filesystem (named servfs) and quickly found a library called libconfig-export-api.so which sounded interesting to me.

By reverse engineering a part of the library’s code, the config file structure of the Speedlink 5501 could be reconstructed. It uses a 72 byte header followed by a gzipped tar archive (.tgz) of arbitary length.

struct header
{
  char magic[2]; // magic bytes \x45 \x72
  uint16_t unknown; // unknown
  uint32_t timesamp; // big endian unix timestamp of creation
  char tgz_sha1[20]; // SHA-1 hash over tgz archive
  char unused1[12]; // empty
  char header_sha1[20]; // SHA-1 hash from beginning of header up to header_sha1
  char unused2[12]; // empty
};

The header contains two SHA-1 hashes. The first hash, tgz_sha1, is computed over the .tgz archive in which the actual configuration is stored. The second hash, header_sha1, is computed over the first 40 bytes of the header (i. e. up to header_sha1). Therefore, tgz_sha1 must be computed first, when assembling the header.

Enabling SSH access

After you have unpacked the .tgz file, you will have several subdirectories of which one is named sql. Inside you will find several .sql files. Open sql/persistent-network.db.sql with a text editor.

First we will modify the firewall to allow access on port 22. Search for “FirewallRulesStatic” and you will see the existing firewall rules (in my case 9 rules, IDs 0..8).

INSERT INTO "FirewallRulesStatic" VALUES(0,1,'IPv4','0.0.0.0','0.0.0.0',0,0,0,0,'UDP',1,'DROP',1,'INCOMING',0,0,'DEFAULT');
[...]
INSERT INTO "FirewallRulesStatic" VALUES(8,1,'IPv6','::0','::0',0,0,0,0,'ICMP6',3,'ICMPv6Filter',1,'INCOMING',0,0,'system entry');

Simply append a 10th rule (with the ID 9) like this:

INSERT INTO "FirewallRulesStatic" VALUES(9,1,'IPv4','0.0.0.0','0.0.0.0',0,0,22,0,'TCP',4,'ACCEPT',1,'INCOMING',0,0,'system entry');

If you are curious for the syntax, you can scroll up a bit where the table FirewallRulesStatic is created. Most options should be self-explanatory.

Secondly, we will enable the SSH daemon. Search for the line

INSERT INTO "SshConfiguration" VALUES(1,0,5,22,'',0);

and change it to

INSERT INTO "SshConfiguration" VALUES(1,1,5,22,'',0);

Finally, we enable the existing SSH account. Search for

INSERT INTO "SshUser" VALUES(1,0,'admin','admin',0);

and change it to

INSERT INTO "SshUser" VALUES(1,1,'admin','admin',1);

It is advisable to change the username and password as well.

After you have made all your changes, save the .sql file and repack everything back to a .tgz file. Next, compute both SHA-1 hashes and modify the header accordingly. After the config file is uploaded to the router, it will reboot and start a SSH daemon for you.

admin@sphairon.box's password:

BusyBox v1.21.1-sphairon7 (2014-07-18 13:17:33 CEST) built-in shell (ash)
Enter 'help' for a list of built-in commands.

# uname -a
Linux sphairon.box 2.6.32.61-stg-3.26 #2 Fri Jul 18 13:30:05 CEST 2014 mips GNU/Linux
# su
# 
This entry was posted in default and tagged , , . Bookmark the permalink.

Comments are closed.