传统的污点分析技术虽然在漏洞检测中被广泛应用,但现代物联网设备日益复杂的架构带来了新的挑战——高阶污点漏洞(High-order Taint Vulnerabilities)。这类漏洞的触发需要多个请求的协同配合,涉及不同组件之间的污点传递和控制流转移,现有方法难以有效检测。
本文介绍的 Bridge 是首个针对物联网固件高阶污点漏洞的检测方法,通过构建 BDG(Binary Dependency Graph)和 ADG(Action Dependency Graph),实现了跨请求、跨进程的数据流和控制流追踪。
什么是高阶污点漏洞?
在深入理解高阶污点漏洞之前,我们先来看看物联网设备是如何处理用户请求的。以 D-Link DIR882 路由器为例,其工作流程可分为两个阶段:
- 阶段一:构造请求 用户通过Web前端与设备交互,配置设置或查询状态。前端生成相应的HTTP请求发送给设备,每个请求通过特定的动作关键字(如
SetNetwork、SetVLAN)标识其功能。 - 阶段二:处理请求 后端使用多个组件(可执行二进制文件、动态链接库、shell脚本等)处理请求。边界二进制文件(如
prog.cgi)首先接收请求,通过注册函数确定对应的动作入口处理器(AEH),然后可能通过进程间通信(IPC)将控制权传递给其他进程进一步处理。
高阶污点漏洞的定义
高阶污点漏洞是指需要多个请求协同配合、由用户可控输入传播引起的漏洞。其触发过程涉及:
- 污点数据的引入和初始存储:第一个请求引入用户可控输入,标记为污点数据,存储到持久化存储中
- 污点数据的传播:后续请求从存储中读取污点数据,可能继续存储或直接触发漏洞
Motivating Example
让我们通过 D-Link DIR882 路由器中的一个真实漏洞来理解高阶污点漏洞:

请求1:引入污点数据
- 动作关键字
SetNetwork触发AEH1处理请求 - 用户可控字段
DeviceName被解析,值为DIR882 - 该值通过
nvram_safe_set写入NVRAM,关键字为lan0_management_link
请求2:使用污点数据
- 调用
notify_rc发送IPC控制消息start_vlanall rc进程接收控制消息,进入vuln_func处理,并解析消息进入对应的处理逻辑(action handler)nvram_safe_get读取之前存储的DIR882
这个例子清晰地展示了高阶污点漏洞的特点:污点数据的写入和读取发生在不同的请求中,需要两个请求的协同才能触发漏洞,且触发过程涉及多个进程。
现有方法局限性
现有的污点分析方法在检测高阶漏洞时面临以下挑战:
隐藏的通信接口:针对Linux内核的方法(如SUTURE)关注系统调用的数据共享,但物联网固件中前后端交互普遍,许多接口隐藏在二进制文件中,无法直接暴露。
IPC数据和控制依赖:现有分析工具(如Karonte、SaTC)依赖静态关键字匹配建立IPC数据依赖,但无法分析动态生成的关键字。例如,通过str_merge函数拼接生成的关键字lan0_management_link就无法被识别。此外,这些方法忽略了进程间通信 (IPC) 控制依赖关系,导致无法提供漏洞警报的实际触发路径。
动态分析的输入空间爆炸:动态分析依赖测试用例执行,难以覆盖所有代码路径,特别涉及多个进程交互的场景。且高阶漏洞需要追踪多个请求的执行状态,显著增加了输入空间。
Bridge的设计

3.1 Entry Point Extraction
Bridge需要识别两类入口点:
- 动作入口处理器(AEH):处理外部请求的入口点(控制流入口)
- 输入解析函数(IPF):解析用户可控数据的污点源函数(数据流入口)
AEH识别采用模式匹配策略,识别三种常见模式:
- 嵌套条件模式:通过
strcmp、memcmp等函数进行字符串比较的多层if-else结构 - 注册函数模式:通过注册函数将动作关键字与处理函数绑定
- 函数指针表模式:在
.data段存储字符串指针和函数指针对
Nested Conditional Pattern// Linksys deviceif(!strcmp(a3, "setEthPortLed")) { setEthPortLed(a1, a2, v6);} elseif(!strcmp(a3, "langSwitch")) { v49 = (_BYTE *)sub_34970(v6, "lang"); // 处理逻辑 v50 = nvram_bufget(0, "Language");if (*v49 && strcmp(v49, v50)) { nvram_bufset(0, "Language", v49); }}Registration Function Pattern// D-Link deviceintModuleInitInternet(){ websFormDefine("GetWanSettings", sub_45D714); websFormDefine("SetWanSettings", sub_465E68);}// Netgear device.data:00120AB0 DCD aUpgradeCgi ; "upgrade.cgi".data:00120AB4 DCD sub_304C8.data:00120AB8 DCD aFwlogCgi ; "fwLog.cgi".data:00120ABC DCD sub_2E278
3.2 BDG Construction
BDG(Binary Dependency Graph)描述了污点数据在整个固件中的传播路径。多阶段污点分析在第一阶段:以IPF为污点源,IPC写函数为汇聚点。后续阶段:以IPC读函数为污点源,IPC写函数和危险函数为汇聚点。
IPC函数配对是BDG构建的核心。Bridge提出了按需过程间常量传播(OD-ICP)算法来恢复动态关键字:
过程内分析:在特定调用点,对包含IPC调用的函数基本块进行前序遍历,识别常量赋值与更新;通过Hook字符串处理和数值计算函数跟踪值变化。循环中若迭代次数已知则直接计算,否则基于初始值作保守估计。
过程间分析:若过程内分析无法确定常量,则分析涉及目标变量处理的自定义函数;在函数内进行过程内分析,并同步全局变量、栈指针和返回值的更新,再将结果回传至原调用点。
例如,对于nvram_safe_get(v2),通过回溯分析可以确定v2的值为lan0_management_link(由str_merge拼接生成)。
3.3 ADG Construction
Bridge 将控制流分析扩展至多进程场景,通过构建动作二进制依赖图(ADG, Action Binary Dependency Graph)刻画不同进程中 action handler 之间的关联,从而串联固件处理 Web 请求的完整执行流程。ADG 被建模为有向图 ,其中节点 表示二进制名称、通信方式、关键字及控制值,边 表示控制流从 到 的跨进程转移。
考虑到 libc 等标准库中的 IPC 函数常被第三方库封装,Bridge 首先为每个二进制构建跨动态链接库的调用图(CG),递归解析库函数调用直至标准库层。基于该 CG,一旦识别出 IPC 调用,即执行 IPC 控制分析以定位目标二进制中的 action handler。随后,以被识别的 handler 为起点,继续进行跨库调用分析与迭代剪枝,逐步扩展跨进程依赖关系,最终构建完整的 ADG。Bridge 将进程间控制流建模为三类:显式控制(如信号或直接进程调用)和隐式控制(由 IPC 控制消息驱动)。其中,显式控制system("sysctl -p 14")直接指明目标程序,而隐式控制通过 IPC 数据流推断:其典型特征是写端在多个路径中复用相同关键字,而读端根据值分发至不同 handler,从而影响后续控制流。
消息流类型推断. 基于信号机制和进程调用的控制流转移具有明确指向性,可通过识别特定函数调用(如 system 或 kill)直接确定控制流转移,无需额外类型推断。因此,本文重点关注基于 IPC 消息机制的类型推断,并引入以下两种启发式约束来识别控制消息:
首先,我们对每个 action handler 进行隔离分析,聚焦单一类型的 IPC 调用,并提取对应的跨库调用图子图。随后,沿调用路径分析消息的传播过程。对于 socket 和 nvram 等机制,控制消息通常在调用图的叶子节点产生(如 nvram_safe_set 或 sendto)。因此,我们从这些叶子节点出发,沿调用路径向上回溯,逐步聚合调用关系及其参数信息,最终恢复完整的消息传播路径。
- 消息生产-集中性约束: 控制消息通常表现出集中性,即多个 action handler 会写入相同的 IPC 接口(如
nvram 关键字或 socket 的 IP-端口对)。这种共享写入模式通常反映系统级控制行为,而非普通数据传输。 - 消息消费-控制流约束: 控制消息不仅具有集中性,还会影响后续控制流。我们通过对消息消费者进行污点分析,判断消息是否影响控制结构(如分支条件或比较函数)。若污点传播至控制依赖位置,则可判定该消息为控制消息。该约束同样适用于带参数的进程调用分析。
- 显式控制: 对于进程调用,我们定位函数调用点并提取其参数作为控制值,例如
system("sysctl -p 14")。此外,IoT 固件中广泛使用 shell 脚本进行跨进程控制传递,这类脚本通常包含复杂的条件逻辑与变量赋值,难以直接解析。为此,我们基于抽象语法树(AST)进行结构化分析。AST 能同时保留控制流与数据流信息,从而定位执行指令(如二进制调用)并跟踪相关变量的取值,即使控制值在多行中被定义或更新,仍可实现精确提取。对于信号机制,我们分析信号发送函数的调用点,并将其参数作为控制值。 - 隐式控制: 从 IPC 写入函数的调用路径根节点出发,我们采用欠约束的定向符号执行,在不同调用上下文中推导具体控制值。该方法适用于恢复运行时构造或解析的控制值,尤其是在涉及分支选择、参数组合或间接计算的场景中。作为对纯静态分析的补充,该策略显著提升了控制值识别的鲁棒性。例如,在 motivating example 中,可恢复
start_vlanall 和 restart_lan 等关键值。为提高效率,我们首先对 IPC 写入点执行反向数据依赖分析,识别通往根节点的可达基本块;随后仅对相关基本块进行选择性符号执行,从而避免不必要的路径探索。
控制值解析. 控制值解析旨在将 IPC 读写函数及其关联代码映射到对应的处理程序。根据解析方式的不同,处理程序可分为固定处理程序和灵活处理程序。
- 固定处理程序: 对于信号机制,我们根据 IPC 控制值直接匹配已注册的信号处理函数作为action handler(如通过
signal 或 sigaction)。 - 灵活处理程序: 对于隐式 IPC 控制值和进程调用值,需要进一步分析以定位对应处理程序。我们将命令行参数(如
main 函数的 argv)以及 IPC 接收函数(如 recvfrom)视为污染源,并通过污点传播提取受影响的基本块子图。在此基础上,采用欠约束符号执行,从污染源出发推导控制值在不同路径下的取值,并定位其影响的分支入口。分支入口之后的受影响基本块被视为与该控制值对应的处理程序。
此外,Bridge 还考虑了污点分析中的隐式流问题,并对静态分析过程进行了进一步优化。具体实现细节可参见附录。
实验评估
Bridge在44个真实固件样本上进行了评估(涵盖8个主流厂商),共发现了1168个真阳性漏洞,其中566个为高阶污点漏洞。已有90个0-day漏洞(包括45个高阶漏洞)获得厂商确认并分配CVE/PSV编号。效率方面,Bridge的平均分析时间为3.06小时,比Mango快2.9倍,比SaTC快20.7倍。

消融实验验证了污点分析各模块的贡献:
AEH、IPF识别:Bridge 对边界二进制、AEH 和 IPF 的识别精度分别为 95.56%、95.56% 和 95.56%,均优于 SaTC 的 71.11%、37.71% 和 22.23%。
BDG构建:Bridge 的 BDG 中节点和边的平均数量分别是 SaTC 的 BDG 的 45 倍和 44 倍,并评估了各模块对污点分析的贡献。
ADG构建:Bridge分别识别出509个、2346个和677个隐式IPC、进程调用和信号控制依赖关系,然而,Chkup只能识别出4个进程调用依赖关系。此外,通过消融实验分析了三类进程间控制依赖关系对高阶污点漏洞的贡献。
总结
Bridge是首个针对物联网固件高阶污点漏洞的检测方法,其主要贡献包括:
- 通过BDG和ADG实现跨二进制的数据流和控制流追踪
Bridge的代码和数据集已公开发布,为物联网固件安全研究提供了重要的工具支持,相关链接如下:
本文介绍的研究成果发表于IEEE S&P 2026,作者来自中国科学院信息工程研究所、蚂蚁集团和清华大学。
供稿:杨浩然
编辑:张艺馨
审核:DAMS编辑部