1day to 0day(CVE-2022-30024) on TP-Link TL-WR841N
Vulnerabilities on TP-Link TL-WR841N devices
|CVE-2022-24355||File extensions handling|
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 version: 3.16.9 Build 150310.
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
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
\r, The process will stop when full-size buffer.
The problem is that adding
dst buffet, the data is added
4 bytes, but the program only processes
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 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
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.
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.
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.
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\x3e… and corrupt the shellcode. Checking this shellcode contains 2 bad bytes
\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,
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
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.
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.
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.
First, enter the function that I feel is easy to understand for me, which is
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
Open IDA to look for this URL string and found the function that handles this URL at
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, 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.
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
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.
- 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