1day to 0day(CVE-2022-30024) on TP-Link TL-WR841N

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



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.                                                  

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.


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.


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.



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.


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.

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