TPLink TLWR740n Router Remote Code Execution

Introduction

In October of 2017 we disclosed multiple vulnerabilities in TP-Link’s WR940n router that occurred due to multiple code paths calling strcpy on user controllable unsanitised input (CVE-2017-13772) The httpd binary responsible for these vulnerabilities contained patterns of code that looked similar to the following:

At the time of disclosure, there were around 7000 of these devices accessible from the Internet.

N.B – The decision to go public on this one was tricky as we’d already released a Proof-of-Concept in our previous blog post which works for this model too, unknowingly to us at the time. Due to the sheer number of affected devices around the globe we expected TP-Link to issue a fix very quickly, especially as they had already fixed the EXACT same issue in a previous device. Sadly this wasn’t the case. We can’t be sure if this is currently being exploited in the wild, however it is likely.

Until a fix has eventually been released by TP-Link (No idea when this will be..) ensure your router is using a strong password and you’ve changed default credentials!

Code Reuse is Vulnerability Reuse

Code reuse is a huge problem within the IoT industry. In most cases, what we generally see is a company who sells devices with poor security to vendors who then brand them and sell them on. Tracking the original manufacturer can be quite difficult and, in our experience, getting such vulnerabilities patched is even harder. A good example of this kind of code reuse was discovered in 2017 by Pierre Kim, who found roughly 185,000 devices which all shared the same vulnerabilities.

When we originally found the vulnerabilities in TP-Link’s WR940n router, our first thought was “how has no one else discovered this yet”, it’s hardly a difficult bug to spot. Our second thought was possibly more naïve, “there’s no way we’ll find something like this again”.

Whilst making various Shodan searches for new targets to do some research on, we came across TP-Link’s WR740n router, which is a much older model and hasn’t had a firmware update for a few years for some versions.

We decided to grab the current firmware for hardware version 5 UK (https://static.tp-link.com/res/down/soft/TL-WR740N(UN)_V5_160715.zip) and have a look around for some low hanging fruit. The extraction of the filesystem is trivial, and is documented in our previous blog post, so we will skip right into reversing the httpd binary.

Straight away we saw some functions that looked familiar (if not identical), so went for a complete chance and just looked for a known vulnerable GET parameter “dnsserver2”. Instantly we get a pretty obvious buffer overflow:

This block of code is exactly the same as noted in CVE-2017-13772, in-fact it is the second vulnerable location we decided to generate an exploit for (which you can find in that post).

Finding all Vulnerable Locations

Tracking down every single vulnerable location and checking if they are the same as the WR940n router would be quite tedious, so we decided that it might be fun to use some IDA python scripting instead. Our goal being to identify all vulnerable locations as well as the GET parameters that can be used to trigger them. This is a relatively easy task due to the fact that the vulnerable pattern is so simple – strcpy(httpGetEnv(“some_param”)).

Let’s look at what this code is doing, the following diagram shows the sequence of each of the loops on a target code block known to be vulnerable:

Notice how between $t9 being loaded with httpGetEnv and $t9 being called, $a1 has 2 different values copied into it, the value 0x56 is redundant, the actual argument is a pointer to the string “dnsserver1”.

The only other thing to consider with this code is how far we jump back initially, you could of course go back 80 or 100 instructions, however you end up with false positives. We found the optimal value to be 20 instructions.

Running this code within IDA for the WR740n httpd binary gives the following output:

In fact the only differences we have are the addresses of the vulnerable locations. It should be noted that this does not necessarily mean that each one of these locations is 100% exploitable, but it does give us a good way of focusing our attention.

The main issue here is that we disclosed the vulnerabilities for the WR940n router over 5 months ago and we would assume that someone would have noticed that the 2 devices use extremely similar if not identical software.

Timeline

25/1/18 – Initial contact with description of issue, contact with [email protected]
26/1/18 – Reply from TP-Link asking for more details, sent them the details for CVE-2017-13772 (wr940n model).
1/2/18 – TP_Link inform us they are looking into the issue.
15/2/18 – Request from us for an update.
30/2/18 – Request from us for an update.
26/3/18 – Another request for an update, warning of public disclosure sent.
28/3/18 – Reply from [email protected], inform us they are releasing a patch in the “recent days”.
29/3/18 – [email protected] send us beta firmware to fix the issue.
29/3/18 – Sent a reply to [email protected] to confirm the issue fixed.
9/4/18 – Request for an estimate for when the firmware goes live.
18/4/18 – Another request, another warning of public disclosure sent.
26/4/18 – No reply received, public disclosure of vulnerability.