4、固件漏洞扫描:静态分析工具、动态分析技术与漏洞库匹配
拿到固件清单之后,下一步就是找漏洞。说白了,就是要把固件拆开、翻个底朝天,看看里面藏着哪些安全隐患。我做了这么多年固件安全,发现很多人拿到固件就急着跑扫描工具,结果跑出一堆误报,反而把真正的问题漏掉了。
这一章,我带你走一遍固件漏洞扫描的完整流程。从静态分析到动态分析,再到漏洞库匹配,每一步都有讲究。
4.1 静态分析:不运行代码也能挖洞
静态分析,就是不运行固件,直接分析它的二进制文件。你想想看,很多嵌入式设备根本没法在调试环境下跑起来,这时候静态分析就是唯一的选择。
4.1.1 Binwalk:固件拆解第一刀
Binwalk 是我最常用的固件分析工具,没有之一。它的核心能力就两个:文件签名扫描和文件系统提取。
先看一个典型用法:
# 扫描固件中的文件签名
binwalk firmware.bin
# 提取所有识别到的文件
binwalk -e firmware.bin
# 只提取特定类型的文件(比如 SquashFS)
binwalk -D 'squashfs:squashfs-root' firmware.bin
# 递归提取(遇到嵌套固件也能处理)
binwalk -Me firmware.bin
我个人习惯先用 binwalk firmware.bin 看一眼扫描结果。输出会告诉你:这个固件用了什么引导加载程序、文件系统是什么格式、有没有嵌入其他固件。
关键输出解读:
- DECIMAL 列:偏移地址,告诉你每个文件在固件中的起始位置
- HEXADECIMAL 列:十六进制偏移,调试时更常用
- DESCRIPTION 列:文件类型描述,比如 SquashFS filesystem、gzip compressed data
我在项目中遇到过一台路由器,固件只有 8MB,但 Binwalk 扫出来里面嵌了三个不同版本的 OpenWrt 文件系统。后来发现是厂商把开发版和正式版打包到一起了——这种低级错误,用 Binwalk 一眼就能看出来。
4.1.2 Firmwalker:自动化敏感信息扫描
Binwalk 把固件拆开之后,Firmwalker 就该上场了。它是个脚本工具,专门在提取出的文件系统里找敏感信息。
# 基本用法
./firmwalker.sh /path/to/extracted-filesystem/
# 输出结果会包含:
# - 硬编码密码
# - SSL/TLS 证书
# - 私钥文件
# - 配置文件中的敏感字段
# - 可执行文件列表
Firmwalker 的扫描逻辑其实不复杂,就是正则匹配加文件路径检查。但它的价值在于自动化——你手动翻目录可能要翻半天,它几秒钟就搞定了。
我的使用技巧:
Firmwalker 默认的规则比较保守,容易漏掉一些自定义的敏感信息。我建议你在运行之前,先看看 firmwalker.sh 里面的正则规则,根据目标固件的特点补充几条。比如 IoT 设备经常用 MQTT,那就加上 MQTT 密码的正则匹配。
4.2 动态分析:让固件跑起来看
静态分析能发现很多问题,但有些漏洞只有在运行时才会暴露。比如内存破坏、竞争条件、逻辑漏洞——这些靠静态分析很难抓到。
动态分析的核心思路:让固件在受控环境中运行,然后观察它的行为。
4.2.1 模拟执行:QEMU 全系统模拟
嵌入式设备千奇百怪,ARM、MIPS、RISC-V 什么架构都有。QEMU 可以模拟这些架构,让你在 PC 上直接运行固件。
# 以 ARM 架构为例,启动一个 Debian 文件系统
qemu-system-arm \
-M virt \
-kernel vmlinuz \
-initrd initrd.img \
-drive file=debian-armhf.img,format=raw \
-append "root=/dev/vda1 console=ttyAMA0" \
-netdev user,id=net0 \
-device virtio-net-device,netdev=net0 \
-nographic
嗯,这里要注意:QEMU 全系统模拟对硬件外设的支持有限。如果你的固件依赖特定的 GPIO、I2C、SPI 外设,模拟环境可能跑不起来。
避坑指南:
我曾经花了两天时间调试一个 QEMU 模拟环境,结果发现固件里有个看门狗定时器,每 30 秒复位一次系统。后来我写了个脚本,在 QEMU 的 monitor 里定期喂狗,才把问题绕过去。所以,遇到模拟环境不稳定,先看看是不是有硬件定时器在捣乱。
4.2.2 用户态模拟:轻量级方案
如果不需要完整的操作系统环境,可以用 QEMU 的用户态模式。它只模拟 CPU 指令集,不模拟硬件外设,启动速度快得多。
# 运行 ARM 架构的 busybox
qemu-arm-static ./busybox
# 配合 chroot 运行完整的文件系统
sudo chroot . ./qemu-arm-static /bin/sh
用户态模拟特别适合测试单个二进制文件。比如你从固件里提取出一个 Web 服务器,想看看它有没有命令注入漏洞,用用户态模拟就能快速验证。
4.3 漏洞库匹配:把已知漏洞揪出来
静态分析和动态分析找到的组件版本,需要跟漏洞库做匹配。这一步看起来简单,但坑很多。
4.3.1 常见漏洞库
| 漏洞库 | 特点 | 适用场景 |
|---|---|---|
| NVD (National Vulnerability Database) | 最权威,更新及时 | 通用漏洞查询 |
| Exploit-DB | 包含 PoC 代码 | 验证漏洞可利用性 |
| VulnDB | 商业库,覆盖更广 | 企业级安全评估 |
| 固件厂商私有库 | 包含未公开漏洞 | 厂商内部安全审计 |
4.3.2 版本匹配的陷阱
漏洞库匹配最大的坑是版本号解析。厂商的版本号格式五花八门:
v2.1.3和2.1.3是同一个版本吗?1.0.0-beta和1.0.0哪个更新?OpenSSL 1.1.1d和OpenSSL 1.1.1的漏洞范围一样吗?
我建议用 cpe-guesser 这类工具做模糊匹配,或者自己写个版本号归一化脚本。别指望手动比对——固件里动辄几十个组件,手动比对会疯掉的。
自动化匹配方案:
我常用的流程是:先用 Binwalk 提取文件系统,然后用 strings 和 find 抓取所有版本信息,最后用 Python 脚本调用 NVD API 做批量匹配。整个过程可以写成 CI/CD 流水线,每次固件更新自动跑一遍。
4.4 知识体系总览
下面这张图把本章的核心逻辑串起来了。静态分析、动态分析、漏洞库匹配三者不是孤立的,而是层层递进的关系。
4.5 实战建议
说了这么多,最后给你几条实战建议:
- 先静态后动态:静态分析能解决的问题,不要上动态分析。省时间,也省精力。
- 自动化要适度:全自动扫描会漏掉很多逻辑漏洞。我习惯用工具做初筛,然后手动验证关键发现。
- 版本号归一化:写个脚本把各种奇葩版本号转成标准格式,再去做漏洞库匹配。这一步能省掉 80% 的误报。
- 关注供应链:很多固件漏洞其实是第三方库的漏洞。比如 OpenSSL、BusyBox、Dropbear 这些常见组件,一旦爆出漏洞,影响面特别广。
最后提醒一句:
漏洞扫描只是第一步。找到漏洞之后,还要评估它的实际可利用性。有些漏洞在特定硬件配置下根本没法触发,别浪费时间去修那些修不了的漏洞。