
Proof-of-concept exploit for CVE-2020-12124 targeting Wavlink AC1200 router, demonstrating unauthenticated command injection and stack buffer overflow in CGI interfaces.
originally at https://www.klogixsecurity.com/scorpion-labs-blog/anatomy-of-an-iot-exploit-from-hands-on-to-rce
by David E. Baker, published on June 1, 2023
This study concerns the firmware of the Wavlink Wireless-AC1200 Gigabit router as of June 2020. The vulnerabilities discussed here may or may not have been patched by the vendor, but this is a case of vulnerability research that will show the journey as the reward rather than its conclusion. The author conducted this research before the public disclosure of the vulnerabilities but after they had been independently discovered by other researchers and reported to the vendor.
The vendor makes firmware for their products available in the support section of their website; this is a common way to obtain IoT firmware and a helpful alternative from extracting it from the device memory. The firmware is unencrypted, so it can be easily extracted with binwalk. Dynamic analysis was done with access to a physical exemplar of the device, and static analysis was done through Ghidra.
The web interface of the Wavlink Wireless-AC1200 Gigabit router has several vulnerable endpoints that allow for the unrestricted copy of user-provided data onto the application stack or even directly to the command line to achieve arbitrary command execution.
Initial scans of the device suggest that the only exposed resource was the administrative web console, accessible to authenticated users on the LAN interface over HTTP on TCP port 80. The device can offer more services, but these are not enabled out-of-the-box and by default. As such, this investigation focuses on the web interface alone.
An nmap scan of the exemplar device, showing only the web
interface listening.
The usual tests — such as the typical command injections found on device
diagnostic panels that allow a command injection in the parameters to a
ping or traceroute command — did not yield any immediately interesting
results, which was disappointing.
Management options available after authenticating to the
administrative web panel. “USB Storage” can be seen as the second option.
The first (ultimately exploitable) interface that was examined here was found on the “USB storage” panel, which can be seen as the second option in the screenshot above. The device has a USB port adjacent to its 802.2 Ethernet plugs, suggesting that it could offer network-attached storage (NAS) functionality.
A photograph of the back of the actual exemplar, showing USB
availability.
A simple principle in vulnerability research is that the more components a piece of code interacts with and the more moving parts it has, the more likely there will be exploitable code lurking nearby. The presence of NAS capabilities is promising because it indicates the presence of code that simultaneously interacts with the device’s software layer, hardware layer, and plugged-in periphery (the USB storage itself).
The management interface for the USB Storage console is shown in below.
The presence of the “Workgroup” field alone is promising, as this would
suggest that this WiFi router may even attempt to interact over Server
Message Block (SMB) — a big lift for an IoT router. I can’t count the number
of times I’ve seen user-supplied input sent directly to the command line
as an argument to the Unix smbpasswd function.
USB storage options available to authenticated users.
Initial attempts to manipulate these settings failed due to the device not detecting a USB drive, as seen below.
Configuration changes to USB Storage options will not be
saved unless an adequately formatted drive is manually plugged into the
device’s USB port.
However, once a correctly formatted drive is plugged in, the device allowed an FTP username and password to be set. As suspected, it placed this user-provided input on the command line:
A command injection in the ‘password’ field nets the first
shell access directly to the device’s operating system.
Though interesting, this vulnerability is challenging to get overwhelmingly excited about: it requires not only credentialed access to the administrative interface of the device but physical access to the device to manipulate its USB drive. The above exploit allows a researcher to interact with the individual operating system components (and exfiltrate them for reverse engineering purposes).
The device was a busy box-centric Linux system with a web interface
powered by Lighttpd. The Common Gateway Interface (CGI) functionality
was provided by individual binaries in /etc\_ro/lighttpd/www/cgi-bin/,
with web requests to CGI URIs launching these binaries directly. A quick
look at nas.cgi in Ghidra shows the command injection on line 38 below,
which sends a user-supplied password directly to the do\_system function
(itself simply a wrapper around the standard libc system call).
User input is placed on the command line as an argument to
the chpasswd.sh script on Line 38, resulting in a command injection
and shell access directly to the device’s operating system.
Looking through the /cgi-bin/ directory reduces the task of finding a
more interesting exploit to enumerating the CGI interfaces available to the
user, shown below:.
An exhaustive list of the CGI binaries made available on the
device, taken live from the shell established by the exploit described in
this section.User input is placed on the command line as an argument to
the chpasswd.sh script on Line 38, resulting in a command injection
and shell access directly to the device’s operating system.
Several things stand out on the initial examination. The first important
thing to note is that the CGI binaries often call the check_valid_user
function. This method looks to see if the IP address making the request is
stored in a particular temporary file on the file system. Minimal testing
shows that a client’s authentication status is not verified until a call to
this method has been made, so the entirety of the code surface in each CGI
binary before the invocation of this function is accessible unauthenticated.