Google security researcher Matthew Garrett discovered a zero-day vulnerability in TP-Link SR20 Smart Home routers. After the company failed to respond to the private disclosure, the researcher decided to make the flaw public.
TP-Link SR20 Vulnerability Technical Overview
The vulnerability is a zero-day arbitrary code execution bug. The TP-Link SR20 routers are dual-band 2.4 GHz / 5 GHz products suitable for controlling smart home and IoT devices. They also support devices that run the ZigBee and Z-Wave protocols.
Apparently, the researcher reported the security flaw to TP-Link privately more than 90 days ago but he received no response. Attempts to contact the company in other ways were also deemed unsuccessful:
I reported this to TP-Link in December via their security disclosure form, a process that was made difficult by the “Detailed description” field being limited to 500 characters. The page informed me that I’d hear back within three business days – a couple of weeks later, with no response, I tweeted at them asking for a contact and heard nothing back. Someone else’s attempt to report tddp vulnerabilities had a similar outcome, so here we are.
As for the vulnerability itself, the issue stems from a process that these routers run frequently. The process is known as “tddp”, or the TP-Link Device Debug Protocol. The process runs at root level and can initiate two types of commands. The first one doesn’t require authentication, and the second one does require it.
The vulnerability exposes some type one commands. One of them, command 0x1f, request 0x01, serves for configuration validation, as explained by Gareth.
Dumping tddp into Ghidra makes it pretty easy to find a function that calls recvfrom(), the call that copies information from a network socket. It looks at the first byte of the packet and uses this to determine which protocol is in use, and passes the packet on to a different dispatcher depending on the protocol version. For version 1, the dispatcher just looks at the second byte of the packet and calls a different function depending on its value. 0x31 is CMD_FTEST_CONFIG, and this is where things get super fun, the researcher wrote.
What happens next is that this function parses the packet for a payload that contains two strings separated by a semicolon. The first string is a filename, and the second one is a configfile. It then calls tddp_execCmd(“cd /tmp; tftp -gr %s %s &”,luaFile,remote_address) which executes the tftp command in the background.
This connects back to the machine that sent the command and attempts to download a file via tftp corresponding to the filename it sent. The main tddp process waits up to 4 seconds for the file to appear – once it does, it loads the file into a Lua interpreter it initialised earlier, and calls the function config_test() with the name of the config file and the remote address as arguments.
Since config_test() is administered by the file downloaded from the remote machine, arbitrary code execution in the interpreter is allowed, which includes the os.execute method running commands on the host. Since tddp is running as root, you get arbitrary command execution as root, Gareth concluded.
A proof-of-concept code is also available for the vulnerability in TP-Link SR20 smart home routers.