A vulnerability published for the TP-Link WL-WA850RE WiFi Range Extender recently caught our attention and warranted further investigation. It’s a command injection bug, typical for many low-cost consumer embedded systems. It's a valid bug, allowing a remote attacker complete access to the device, but it requires administrative credentials to exercise the vulnerable code. Using the Centrifuge Platform, we found that there is a much more serious bug that allows a remote attacker to completely control the device even without prior knowledge of the administrative credentials.
What is particularly worrisome is that these vulnerabilities aren’t limited to attackers with LAN or WLAN access. This vulnerability affects multiple TP-Link products, including many devices that are connected to the Internet and therefore susceptible to remote attack! More on this later.
THE COMMAND INJECTION BUG
First, let’s examine the original command injection bug. Based on the published exploit code, the command injection exists in the
wps_setup_pin input parameter passed to the
/data/wps.setup.json page in the device’s web server:
The first thing we do with firmware images these days is throw it into the Centrifuge Platform, which performs automated firmware extraction and vulnerability analysis. Sure enough, it ranks the
httpd daemon as the highest risk executable on the system:
There are some other interesting high-risk services listed here (
tmpServer seems interesting maybe another blog post on that later on), but let’s stick to the task at hand. Examining the detailed vulnerability analysis results for the
httpd binary in Centrifuge, there are a ton of calls to
strcpy with stack addresses as the destination…and this is just the first page of results:
Once we identify suspicious binaries in the firmware we can download the file directly from Centrifuge and throw it into our disassembler of choice. In this article we use IDA Pro, but there are several less expensive alternatives available recently. Once we have the
httpd binary loaded into IDA we quickly realize that one of the first
strcpy issues listed in the Centrifuge Platform report leads us directly to the originally published vulnerability. This vulnerability is a WPS command injection bug inside the
Looking at the code in this function, it handles the user-supplied data in the least secure manner possible. The
wps_setup_pin value can be used to exploit both a stack-based buffer overflow and a command injection bug here, but the command injection bug is easier to exploit, and is more portable across different firmware versions and different affected devices, so it makes sense for an attacker to target the command injection instead of the buffer overflow.
However, before we can get to this vulnerable code, an authentication check is made by calling the
As noted in the published exploit, if this authentication check fails then the attacker will never reach the vulnerable code.
FINDING UNAUTHENTICATED ATTACK VECTORS
The obvious first question is: are there any HTTP requests that we can make to the web server that don’t require authentication? To answer that, we first need to figure out what web pages can be requested from the web server, and which pieces of code are responsible for handling requests for a particular page.
For this particular web server, it registers a function handler with an associated URL via the
Here we can see that the URL is passed as the second argument to
httpRpmConfAddAndRegisterFile, and the function responsible for handling all requests for that URL is passed as the third argument.
Using Centrifuge Platform’s internal static analysis engine (whose API will soon be available to customers) we were able to parse all of these function calls and their arguments, allowing us to resolve each URL to its associated function handler and obtain a list of function handlers that do not call the the
wmAuthIsClientAuthencated authentication function:
Most of these unauthenticated URLs are just serving up static HTML pages, but one notable exception is
/fs/data/config.bin. This sounds like a backup configuration file, which should hopefully contain the administrative password! What happens if we request this file from the target device?
Well it seems the device just gives it to you without having to login (cue facepalm). The entire backup configuration file is perhaps the single most sensitive piece of information that can be requested through the web server; how it was left unprotected is beyond me, and clearly shows a complete lack of sufficient security analysis prior to product release.
config.bin file appears to be encrypted or obfuscated somehow; there are no readable strings (except some file header data) or common compression formats inside it, and the data appears to have relatively high entropy.
In fact, the ability to retrieve the
config.bin file without authentication was already discovered in a separate vulnerability report published earlier this year. That vulnerability report notes that while the configuration file can be retrieved, it is encrypted, and offers no suggestions or solutions to decrypting it.
DECRYPTING THE CONFIG FILE
Embedded systems aren’t typically known for using strong crypto, so let’s see if we can crack this nut. There wasn’t anything in the
httpd binary that I could find which appeared to be crypto-related, but searching the firmware’s file system revealed another binary which also references the
uclited binary there is a function named
usrconf_load_factory_setting, which calls the function
do_des_min, and immediately afterwards calls
This suggests that the
config.bin file that we have has first been compressed, then DES encrypted. Examining the arguments passed to the
des_min_do function, the fifth argument (pushed onto the stack) is the memory address
Hmmmm, could this
478DA50BF9E3D2CF value be a hard-coded encryption key? A quick Google search reveals that this key has been used by TP-Link for years to encrypt configuration files. One of the OpenWRT developers did quite a nice write-up on it, and even provided the exact openssl command needed to decrypt the configuration file using this key:
Binwalk'ing the resulting decrypted file shows a compressed data blob, which when decompressed contains an ASCII configuration file:
Hard coded encryption keys are a recurring theme in the world of embedded system “security”. Note to all product vendors: if you’re going to bother encrypting data, especially sensitive customer data, don’t use the same hard-coded encryption key across multiple products and firmware releases. Using hard-coded cryptographic keys is a classic example of security through obscurity. Instead of luring users into a false sense of security with your hard coded keys, focus your efforts to developing secure code to begin with.
Examining the decrypted, decompressed configuration data in more detail reveals that it is stored in JSON format, and while WiFi configuration settings (including the WiFi password) are stored in plain-text, the administrative password is stored as an MD5 hash:
We could of course run this hash through a password cracker, but that is unnecessary.
AUTHENTICATING WITH THE MD5 HASH
…The plain-text password is first MD5 hashed. This hash is then concatenated with a nonce (the browser’s cookie is used as the nonce), and the entire string is MD5 hashed again. This means that we don’t need to know the actual password, just the MD5 hash is sufficient. In fact, the original command injection exploit performs this same hashing sequence in order to authenticate prior to exploitation, so if you’ve examined that code at all, this should come as no surprise.
This is actually something we have seen in many embedded devices; they’ll hash the password before sending it across the wire, presumably to protect the clear-text credentials from being transmitted over the network, but anyone who captures the login request can simply replay the login request anyway. We would recommend requiring SSL for all traffic that transmits credentials, and using third party authentication frameworks that have been validated by the industry. If you roll your own crypto implementation, you are bound to do it poorly.
IDENTIFYING OTHER AFFECTED DEVICES
Thanks to vendor code reuse, bugs like these are rarely isolated to a single product (or even to a single OEM!). We wanted to learn what other TP-Link products might be affected, so we turned to Centrifuge Platform’s Guardian feature, which will scan current and past firmwares for known vulnerabilities as they are published.
This revealed that at the least the following TP-Link products are affected:
- RE305 v1.0
- RE450 v1.0
- TL-WA830RE v3.0
- TL-WA850RE v2.0
- TL-WA850RE v4.0
- TL-WA850RE v5.0
- TL-WA855RE v1.0
- TL-WA855RE v2.0
FINDING VULNERABLE DEVICES
My initial assumption was that because these devices are WiFi range extenders, they would typically be sitting behind a NAT/firewall and there would be precious few of them connected directly to the internet. But Shodan proved me wrong:
There are some false positive hits in the Shodan results, but all the results that have Opening… in the title appear to be vulnerable. These WiFi range extenders were probably intended to be installed behind a router/firewall, and I suspect the reason so many of them are internet accessible is user error. The users probably just connected the WAN cable from their ISP directly into the range extender’s ethernet port.
Perhaps this is why TP-Link didn’t take the security of this product very seriously, as they expected it to be connected to a trusted LAN, not the internet. However, as we have discovered, users are not always predictable or security conscious. Because of TP-Link's lack of attention towards device security they have inadvertently exposed many of their customers' homes and businesses to being exploited.
THE EXPLOIT SCRIPT
To demonstrate the severity of this issue and prove to the vendor that is in fact exploitable we developed a proof of concept exploit written in Python. This script grabs the configuration file, decrypts and decompresses it, authenticates to the target device, and exploits the command injection bug to start a telnet server on port 8080. It has been tested against the RE450 v1.0, TL-WA850RE v5.0, TL-WA855RE v1.0, and TL-WA855RE v2.0 products:
And... it works like a charm:
It should be noted that absolutely no reverse engineering was required to find the bugs discussed in this post. All of these bugs were already public knowledge, although as far as we are aware no one has tied all the pieces together before (at least not publicly), nor has TP-Link made any attempts to fix them.
Additionally, it appears that little, if any, work has been done by either researchers or the vendor to investigate what other devices were affected by these bugs. This is extremely common; attackers don’t know off hand which products may share a common code base, and vendors either don’t care or don’t have the time, resources, or expertise to examine all their potentially affected products. Likely this is due to the time consuming nature of manually undertaking such an endeavor, hence the advantage of using an automated system like the Centrifuge Platform.
The bottom line is: if you own one of these devices, especially if it is remotely accessible from the internet, assume that you’ve been compromised. Either put the device behind a NAT/Firewall or replace the device with one from a more reputable vendor.
Note these issues have already been disclosed to TP-Link who got a pre-release version of this blog post with all the technical details required to duplicate the bug. We are hopeful that TP-Link will issue patches for these serious vulnerabilities in a timely fashion.
Craig is a Principal Reverse Engineer with ReFirm Labs. He is the developer of the popular firmware extraction tool, binwalk. He has spoken at Blackhat, DEFCON, and other conferences on firmware security topics.