In the previous part, we gathered the firmware and caught the password for Root user. Note that the password is for the web Interface.
First, I want to log in to the web interface to see if the Root user has extra control than usual admin user. Also it is easier to try than reversing the firmware. I had no problem with logging in and, indeed, the Root user is more privileged than admin user.
The first thing I did is to change Root’s password. Then I started discovering the interface. Have you seen CWMP menu option on the left? CWMP stands for CPE WAN Management Protocol and that menu is where we can set our ACS URL, inform period, etc.
So, I think if we set up our ACS and set its URL from the web interface, we can access and change more of settings. I decided to install genieacs which is an open-source ACS software. The installation process was easy and clean with the instructions in genieacs docs. Geniacs has three binaries:
genieacs-cwmp: It is the main ACS binary. By default in runs on port 7547.
genieacs-nbi: This is the server we’ll send our queries to. Basically, it is an administrator interface to communicate with genieacs-cwmp.
geniacs-fs: This is the fileserver to serve firmware, config files, etc.
Since I don’t want to serve anything for now, I only started geniacs-cwmp and genieacs-nbi. From the web interface, I set http://psaux.io:7547 as ACS URL without a username or password. I also updated the inform period to 5 seconds, so that I don’t have to wait 86400 seconds (24 hours) to get a connection. With the help of this API reference, I started to poll for new connections but no luck.
1 2 3 4
$ curl localhost:7557/devices [
]
There may be a limitation on the router. Maybe it only connects to acs.superonline.net. Once again, I took my laptop and two ethernet converters, sat beside my router, started sniffing communication hoping that I see something related. And yes, I could see that the router was sending DNS queries for psaux.io but never connected to it.
So it’s an ip restriction. With high hopes I installed genieacs on my laptop which is connected to LAN, changed CWMP settings accordingly but received no connection again. It’s life. You don’t get lucky all the time. So now it’s time to take the harder path: reversing the firmware. Let’s run binwalk on the firmware:
1 2 3 4 5
$ binwalk HG253sV100R001C01B039_upgrade_main.bin
DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 131200 0x20080 JFFS2 filesystem, big endian
It seems like there is a JFFS2 filesystem embedded in the binary. Let’s extract the image with:
DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 131200 0x20080 JFFS2 filesystem, big endian
$ ls 20080.jffs2 HG253sV100R001C01B039_upgrade_main.bin
I’ll use jffs2dump script written by project-magpie to dump the image. First convert the endianness:
1 2 3 4 5 6
$ jffs2dump -v -b -r -edum.bin 20080.jffs2 Wrong bitmask at 0x00c00000, 0xbd61 Wrong bitmask at 0x00c00004, 0x0000 Wrong bitmask at 0x00c00008, 0x0000 Wrong bitmask at 0x00c0000c, 0x0000 Wrong bitmask at 0x00c00010, 0x0000
Note that jffs2dump here isn’t the python script, it’s a tool that belongs to mtd-utils. We got “Wrong bitmask” warnings, so let’s fix them with sumtool:
1
$ sumtool -l -i dum.bin -o dum.sum -v
Now we can run the python script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$ python jffs2-dump.py dum.sum . . . root/etc/passwd root/etc/printers.ini root/etc/profile root/etc/radius.conf root/etc/resolv.conf root/etc/root.crt Traceback (most recent call last): File "jffs2-dump.py", line 285, in <module> unpack_main(sys.argv[1], 'root') File "jffs2-dump.py", line 277, in unpack_main for din in inodes[n.ino]: KeyError: 157
Damn, it exited with an error and left a lot of missing files. After spending some time, I added try/except block around the line we got the error to ignore KeyErrors.
1 2 3 4 5 6 7
try: for din in inodes[n.ino]: if din.dsize > 0: cur_file.seek(din.offset) cur_file.write(din.get_data()) except: pass
No errors. The image extracted to a folder named root.
1 2 3 4
$ cd root/ $ ls bin config etc lib mnt sbin tmp var voip cferam.000 dev html linuxrc proc status usr vmlinux.lz
It looks like a usual linux system. After looking into folders, I found some interesting files. I won’t go through them here but I want to mention just one of them:
Maybe an engineer from Huawei (I assume z00163152@HUAWEI-627FB9A3) who owns a specific DSS key, can connect all HG253s routers without needing a password, who knows?
Alright, enough of corporation backdoors, I want to look at ATP Cli from the first part because I think it’s very promising. It must be accepting some commands which may provide us a wider perspective. To find which binary handles ATP Cli, I simply ran:
1 2
$ grep -nr "Welcome to ATP Cli" Binary file bin/cli matches
The string “Welcome to ATP Cli” is hardcoded in bin/cli. Let’s inspect bin/cli with strings command and find out what other strings are hardcoded:
$ strings bin/cli . . . console Login: HG253s56jiioHJ5867nihNJI255KOIg7 The console is prohibited! Login incorrect! Password: /var/telnetIpaddr open telnetIpaddr fail get telnetIpaddr fail rm -rf /var/telnetIpaddr telnet unlocked and login from %s successfully. telnet login from %s successfully. console unlocked and login successfully. console login successfully. telnet login failed %d times: locked. console login failed %d times: locked. Authorization failed after trying %d times.Please wait one minute. telnet login failed:Authorization failed. console login failed:Authorization failed. Login incorrect. Try again. CLI login return %x console logout:timeout. telnet logout:timeout. ATP> exit logout quit console logout by command. telnet logout by command. ssh logout by command. shell debug display cwmp debug display sysuptime debug display atpversion save help cpuinfo meminfo arptable ifconfig iptables nattable ping traceroute netstat Command failed. Byebye! Have a nice day! . . . ing %s > %s 2>/dev/null /var/PingInfo ping [ip|domain] ping result:%s %s > %s cat proc/loadavg /var/CPUInfo cat proc/meminfo /var/MemInfo cat proc/net/nf_conntrack /var/NatTableCurSize nattable currentsize cat proc/sys/net/nf_conntrack_max /var/NatTableTotalSize nattable totalsize /var/NatTableInfo nattable info ifconfig %s > %s 2>&1 /var/IfconfigInfo ifconfig > %s 2>&1 iptables %s > %s 2>&1 /var/IptablesInfo iptables > %s 2>&1 . . .
It seems like it’s indeed accepting some commands. To confirm I connected to ATP Cli and ran:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
------------------------------- -----Welcome to ATP Cli------ ------------------------------- ATP>ping psaux.io ping psaux.io ping result: PING psaux.io (104.248.35.218): 56 data bytes 64 bytes from 104.248.35.218: seq=0 ttl=53 time=50.722 ms 64 bytes from 104.248.35.218: seq=1 ttl=53 time=47.797 ms 64 bytes from 104.248.35.218: seq=2 ttl=53 time=47.537 ms
--- psaux.io ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max = 47.537/48.685/50.722 ms
That’s quite a response! Since we’ve found out that there is an IP restriction on ACS URL before, iptables command took my attention:
Chain OUT_SERVICE (1 references) target prot opt source destination ACCEPT tcp -- anywhere anywhere destination IP range 85.29.0.1-85.29.63.254 tcp dpt:7547
at lines 20-23 and 84-86 respectively. We can see that our ACS port 7547 is added as a rule in iptables but it only accepts connections to the IPs in range 85.29.0.1-85.29.63.254. To remove the restriction let’s flush OUTPUT chain:
1 2
ATP>iptables -F OUTPUT iptables -F OUTPUT
Now we can check our ACS to see if there is a connection:
After a few seconds, the router informed about its 1352 parameters. Here is the full list for the ones interested. In all these parameters, these took my attention:
Not that “ServiceManage” is not a typo I made. Also I searched for ssh credential parameters but there was none. I retrieved the values of above parameters with:
$ telnet 192.168.1.1 2323 Trying 192.168.1.1... Connected to 192.168.1.1. Escape character is '^]'. ------------------------------- -----Welcome to ATP Cli------ -------------------------------
Login: Root Password: ATP>
Our old friend ATP Cli again… Wait, if I could log in to ATP Cli with the new password, maybe that password will also work for ssh. I tried afterwards and yes it’s also changed.
So we managed to change passwords for both ssh and telnet, gain access to Root user for the web interface, changed that password too. We changed ACS URL to ours and remove the IP restrictions. To put it simply, we cleaned up our router from our ISP. Good for our privacy.
Still there is an authorized ssh key left in the firmware but for now it’s enough that we’re keeping the ISP out. Maybe in the future, we can repack the firmware with our configuration and keys and install it on the router. For now, take care!
Note: The main discussion about these post series is here.