DIR-645—ssdp.cgi命令执行复现
字数 3006
更新时间 2026-02-27 03:23:25

D-Link DIR-645 A1 远程任意命令执行漏洞分析与教学

一、 漏洞概览

本教学文档基于 D-Link DIR-645 A1 型号无线路由器固件。漏洞存在于其 ssdpcgi(Simple Service Discovery Protocol CGI)组件中,成功利用可导致远程攻击者执行任意系统命令,进而完全控制设备。

关键漏洞信息:

  • 漏洞组件ssdpcgi (Simple Service Discovery Protocol CGI 接口)
  • 危险函数lxmldbc_system
  • 漏洞类型:远程命令执行 (Remote Code Execution, RCE)
  • 影响版本:D-Link DIR-645 A1 特定固件版本(需进一步确认)
  • CVSS评分:预估为高危 (Critical)
  • 漏洞状态:根据分析,该漏洞可能已被提交至官方。

二、 漏洞原理深度分析

1. 漏洞触发入口与思路溯源

漏洞挖掘思路借鉴了同系列路由器(DIR-615/645/815)中已知的 service.cgi 远程命令执行漏洞。核心方法论是定位程序中直接调用 system() 或类似功能(如 lxmldbc_system)的危险函数,并逆向追踪其输入参数是否可控。

2. 漏洞点定位 (ssdpcgi_main)

首先在目标固件的 ssdpcgi 二进制文件中定位到关键入口函数 ssdpcgi_main。分析发现,该函数最终会调用 lxmldbc_system 函数。lxmldbc_system 函数内部封装了对标准 system() 函数的调用,这意味着只要能控制传入 lxmldbc_system 的参数,就能实现任意命令执行。

3. 参数控制路径分析

逆向工程的关键在于追溯 lxmldbc_system 函数参数的来源。

  1. 参数数量检测:代码首先检测传入的命令参数数量,要求 ==2。此检测仅为数量校验,无内容过滤。
  2. 参数解析:程序直接解析 HTTP 请求或环境变量中的参数内容,未对参数内容进行任何安全检测或过滤
  3. 格式化字符串构造:解析后的参数内容被直接赋值给一个格式化字符串变量,其格式类似于 %s_ssdpall %s:%s %s_&。攻击者可以完全控制这些 %s 所对应的字符串内容。
  4. 命令拼接与执行:程序中有多个执行分支,最终都会进入调用 system() 的逻辑。攻击者可以通过在可控参数中插入命令分隔符(如分号 ;)来拼接并执行额外命令。典型的利用方式是在参数末尾添加 ;{command},其中 {command} 为攻击者意图执行的任意系统命令。

总结漏洞链条:缺乏输入验证 -> 可控参数直接拼接 -> 格式化字符串构造系统命令 -> 调用 system() 执行。

三、 漏洞验证(POC 概念验证)

可以使用 qemu-user 等用户态模拟环境来运行路由器的 ssdpcgi 二进制文件,以验证漏洞。

验证步骤简述:

  1. 搭建 qemu 用户态模拟环境,并配置相应的动态链接库。
  2. 构造一个特殊的 HTTP 请求(或直接设置环境变量),向 ssdpcgi 进程传递恶意参数。参数中包含用于命令注入的分隔符(如 ;)和待执行的命令(例如 cat /etc/passwd)。
  3. 启动模拟的 ssdpcgi 进程,并发送构造的恶意请求。
  4. 观察进程输出,若能成功读取到 /etc/passwd 文件内容或其他命令的执行结果,则证明漏洞存在且可利用。

四、 补丁对比分析(以 DIR-850L 为例)

为了解厂商修复方案,分析了另一型号 D-Link DIR-850Lssdpcgi 组件。

1. 危险函数依然存在

在 DIR-850L 的固件中,lxmldbc_system 函数依然存在,因此初步判断存在类似的命令执行风险。

2. 参数控制被严格限制

然而,深入分析 lxmldbc_system 的参数来源后发现,DIR-850L 引入了多层严格的校验和白名单机制,彻底阻断了参数控制路径:

  • 参数来源 (getenv):参数通过 getenv 函数从环境变量获取。
  • 长度限制:对关键参数 v2, v3 进行处理,其中 nptr 的长度被要求 < 6,否则后续逻辑判断无法通过。
  • 白名单函数 (sub_40FE70):该函数为核心修复点。它将参数赋值给栈变量 hackstack_0,但随后对 hackstack_0 的内容进行了严格处理。
    • 参数内容必须符合 "uuid:%08llX-%04llX-%04llX-%04llX-%012llX" 的特定格式(即 UUID 格式)。
    • 攻击者输入的字符串会被强制转换为此格式的数字,因此无法在其中注入命令。
  • IP 地址格式校验 (sub_41011C):另一参数会被此函数检测,必须是有效的 IPv4 或 IPv6 地址格式,否则直接报错,无法控制。
  • 其他参数 (s0, s1)
    • s0 为数字类型,无法用于字符串拼接。
    • s1 也加入了白名单检测,内容被严格限制。

修复结论:DIR-850L 版本的漏洞已被修复。通过 严格的输入格式校验(UUID、IP地址)长度限制白名单机制,确保了传递给 lxmldbc_system 的参数是预定格式的、不可控的安全数据,从而封堵了命令注入的可能性。

五、 教学总结与安全启示

  1. 漏洞根源未经校验的用户输入直接拼接进入系统命令是导致此类远程命令执行漏洞的根本原因。
  2. 挖掘方法论:对于嵌入式设备或 Web 服务的漏洞挖掘,一个有效的方法是:
    • 定位危险函数:在二进制文件中搜索 system, popen, exec 家族函数,以及设备自定义的封装函数(如 lxmldbc_system)。
    • 回溯数据流:逆向追踪这些危险函数参数的来源,检查其是否直接或间接来源于用户可控的输入(如 HTTP 请求参数、cookie、环境变量)。
    • 检查过滤机制:分析数据传递路径上是否存在有效的过滤、校验、编码或白名单机制。
  3. 安全开发建议
    • 最小化命令执行:尽量避免在 CGI 或服务中直接调用系统命令。
    • 使用安全 API:如需执行命令,应使用 execve 等指定完整路径和参数的函数,避免使用 system
    • 实施严格输入验证:对所有外部输入进行“白名单”验证,只允许已知安全的字符和格式。
    • 进行安全编码:避免使用未经处理的用户输入来拼接命令字符串或 SQL 语句。
    • 深度防御:在无法完全避免命令拼接的场景下,应对用户输入进行严格的转义和过滤。
  4. 固件安全分析流程
    • 获取目标设备固件。
    • 解包/解密固件(如 DIR-850L 使用了加密固件,需先解密)。
    • 使用 IDA Pro、Ghidra 等工具进行静态反编译分析。
    • 定位关键服务与 CGI 程序。
    • 结合动态分析(如 qemu 模拟、硬件调试)验证漏洞。

通过本案例的学习,可以掌握从思路借鉴、静态逆向分析、动态验证到补丁对比的完整 IoT 漏洞分析链条。

 全屏