1day to 0day(CVE-2022-30024) on TP-Link TL-WR841N
Vulnerabilities on TP-Link TL-WR841N devices
Vulnerability | Description |
---|---|
CVE-2020-8423 | Data parsing |
CVE-2022-24355 | File extensions handling |
CVE-2022-30024 | Assignment data |
CVE-2020-8423
Description
The vulnerability on TP-LINK's router device with model number TL-WR841N V10 is assigned ID CVE-2020-8423. The vulnerability allows an authenticated attacker to remotely execute arbitrary code on the device by sending a GET request to the wifi network configuration.
Firmware
Firmware version: 3.16.9 Build 150310.
Vulnerability analysis
Before going into the hole I will analyze Dispatcher()
to understand how the program distributes functions to properly handle its function.
When a REQUEST is submitted, the httpGenListDataGet()
function will be called to return a LIST_ENTRY
pointer, which points to a list containing in turn the function pointers that handle the function for each previously assigned URL. Next, the program will call the function httpGenListFuncGet()
to return the function pointer in the list and find out if the URL assigned to the handler function is found in the submitted REQUEST or not. If there is a function that will be called, otherwise the check will continue with the next function pointers in the list.
The program will assign a handler function to each URL string using the httpRpmConfigAdd()
function.
Rambling a bit to get an overview, now I will focus on analyzing this vulnerability. This error occurs when handling escaped characters in a function named stringModify(char * dst, int size, char * src)
. The function will add the character \
when it encounters the characters \, /, <,> "
, or will add <br>
if the next characters are not \n
and \r
, The process will stop when full-size buffer.
The problem is that adding <br>
to dst buffet
, the data is added 4 bytes
, but the program only processes 1 byte
.
So, just find a place calling this function that uses the src buffer
as user input, this vulnerability is completely possible.
In reverse tracing, I get a writePageParamSet()function
that has the gen page function to return the values to the user, where a buffer dst[512]
is created and passed to stringModify()
to receive the values in the handle escape characters.
further, we get a callback function that handles the URL string containing /userRpm/popupSiteSurveyRpm.htm
at address 0x45FA94
.
This function will take the parameters of the GET request and call the function containing the vulnerability
and we can control this vulnerability based on the optional ssid
parameter entered.
Vulnerability verification
Use Payload = “/%0a” * 0x55 + “A” * 100
. Set breakpoint and observe.
So the vulnerability has been verified, the $ra register value has been changed, and 3 registers $s0, $s1, $s2
have been overwritten.
Exploit
Check and see that no protection mechanism is enabled, so we can pass shellcode to the stack to execute arbitrary code.
There is a problem with the MIPS architecture, we need to clear the Icache
cache before executing the shellcode, to solve this problem we will control the program to jump into the Sleep()
function. Looking at the program's library and I found the Ropchain that matches the library from an old exploit here, which will need some debugging and tweaking. suitable for my case.
Fix shellcode
I have a shellcode reference here but it doesn't work. Through debugging, I realized that when the shellcode is passed to the stringModify()
function, if it contains the bytes \x3c, \x3e, \x2f, \x22, \x5c
the program will add 1 byte \x5c
in front of \x5c\x3c
or \x5c\x3e
… and corrupt the shellcode. Checking this shellcode contains 2 bad bytes \x3c
and \x2f
. I will fix some commands to remove these bad bytes by replacing other commands.
Fix byte 0x3c
This byte is in the lui
instruction, the author's logic will save 4 bytes on the stack.
I will change the lui
instruction to the li
instruction to save 2 bytes on the stack instead of 4 bytes.
Fix byte 0x2f
In this command string shellcode contains 2 bad bytes, 0x3c
and 0x2f
when the author wants to put the string //bin/sh
on the stack.
I would use the li instruction to remove 0x3c
, and the xori
instruction with an intermediate value
to fix the 0x2f
byte.
This way when we modify the shellcode, we get control of the router.
My next task was to evaluate the entire firmware of this device and here I discovered more 1day and 0day exist.
CVE-2022-24355
Vulnerability information
The first vulnerability I discovered (1day) is a critical vulnerability CVE-2022-24355 that allows network attackers to execute arbitrary code without based authentication about buffer overflow. A teammate of mine analyzed this vulnerability here so I won't mention it further.
CVE-2022-30024
Description
This is a Stack-based buffer overflow vulnerability that exists in the ipAddrDispose
function of a Web service running on binary httpd. The vulnerability occurs in the process of assigning the parameter value of the GET request to a stack variable, allowing the user to enter large amounts of data into the stack memory and the attacker can take control.
Finding errors
First, enter the function that I feel is easy to understand for me, which is ping
.
Start checking to see if the program allows overflow to cause any errors by sending a string aaaaaaaaa....aaa
and as a result, only 50 characters can be entered on the UI and get the message ping request could not find host ….. Please check the name and try again.
Nothing seems to happen, we keep looking for the handler and reverse. As a result, we open the burp suite and get the Request containing /userRpm/PingIframeRpm.htm
Open IDA to look for this URL string and found the function that handles this URL at 0x44A530
Here the httpGetEnv
functions are called to get the values ping_addr, doType, isNew
… which are passed through GET REQUEST parameter.
Through a process, the ipAddrDispose
function is called with the ping _addr
argument passed. vulnerability will occur here.
A stack variable buf_ip
with size 52 bytes are initialized and receives each character value from ping_addr
until the end of the string. The problem is that the length of ping_addr
is not handled with validation in the code but is limited to the web UI, and this can be easily bypass using Burp Suite
.
Test with Burp Suite
, enter a length of ping_addr
around 200 bytes a
for fun, and as a result. The program crashed. The return address register $ra
was overwritten, so the vulnerability was confirmed.
I wrote a quick python script to enable the vulnerability. The result was as we expected.
Exploit
The next goal is that RCE is device, because the device is not enabled with any protection mechanism, ASLR is also turned off, so we can control the $ra
register to jump into the shellcode to execute the code and take control.
Looking at the assembly statement at the beginning of the program and the end of the program, the position of the stack variable buf_ip
, we can calculate the offset to overwrite to $ra: (0xD4 + 8) - (0xD4 – 0xA0) = 168 bytes
and at the same time can control two more registers $s0
and $s1
In order to have a mental model and build an exploit, I start making a diagram of the memory.
In MIPS architecture, we cannot jump directly into shellcode to execute the code, we have to clear the Icache (Instruction cache)
memory first by jumping into sleep()
function. Since it's on the same firmware, I will use ROP again in the above exploit.
Building the complete ROP chain, we will have the stack model as below.
As a result, we have successfully exploited the device with the Stack Overflow vulnerability, because we are performing a firmware simulation, so the reverse shell will print log, on the real device, this case will not appear.
I discovered this vulnerability exists on versions from TL-WR841N V12 and below and the ID CVE-2022-30024
is assigned to this vulnerability. Users should download the latest firmware from the official website from TP-Link to update the patch.
https://www.tp-link.com/en/support/download/tl-wr841n/v12/#Firmware
Time line
- 14/04/2022: I sent them a report with the vulnerability
- 27/04/2022: TP-Link security teams sent me a fixed firmware to check
- 04/08/2022: TP-Link released the new firmware