关于 analyzing-firmware-images
这是一项固件安全分析技能,用于检查更新镜像以及嵌入式设备的文件系统、服务和二进制文件,面向评估 IoT、路由器等嵌入式系统的安全研究人员。内容涵盖从提取分析到模拟运行和密码学审查。
主要功能
- 01识别镜像格式与熵值
- 02提取嵌入式文件系统
- 03搜索凭据和机密
- 04审查 Web 界面与服务
- 05分析跨架构二进制文件
- 06评估更新签名与密码学
适用场景
- 01根据固件镜像评估 IoT 设备
- 02搜索固件中的内嵌凭据或密钥
- 03评估设备更新验证机制
- 04检查嵌入式 Web 界面和网络服务
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trilwu/ secskills --skill analyzing-firmware-images安装后在 Claude Code 中输入/analyzing-firmware-images确认已加载。
详细介绍
分析固件镜像
固件是冻结的 Linux(或 RTOS)镜像,其安全性也随之冻结。硬编码凭据、CGI 脚本中的命令注入、未签名的更新包,以及仍启用的调试接口都不是个例——而是常态。工作内容包括提取、了解镜像结构,然后像分析任何系统一样提出相同的问题,同时要知道这个系统自发布以来就再也没有打过补丁。
适用场景
- 提取和分析固件更新文件(.bin、.img、.chk、.trx)
- 根据固件镜像审查 IoT 设备的安全状况
- 在设备固件中查找硬编码凭据、密钥或机密
- 评估嵌入式设备或路由器的攻击面
- 评估更新机制和签名验证
- 分析微控制器上的裸机或 RTOS 镜像
不适用场景
- 标准 x86/x64 二进制逆向工程——使用
analyzing-binaries - 恶意软件样本分析——使用
analyzing-malware - 有源代码可用——使用
auditing-code-for-vulnerabilities
固件获取
分析之前需要先获取固件。获取方式决定了你能得到什么。
| 方式 | 获取内容 | 备注 |
|---|---|---|
| 厂商下载 | 更新包,通常经过压缩或加密 | 查看支持门户、FTP 服务器和 FCC 文件 |
| OTA 抓包 | 传输中的更新载荷 | 在设备的更新通道上使用 mitmproxy 或 tcpdump;许多设备使用纯 HTTP |
| UART/串口控制台 | Shell 访问权限、引导加载程序交互 | 需要三根线(TX、RX、GND);使用万用表或逻辑分析仪识别 |
| JTAG/SWD | 完整内存读取、调试访问权限 | 需要识别引脚;使用 JTAGulator、OpenOCD |
| 芯片脱焊 | 原始闪存内容(NAND/NOR) | 拆下闪存芯片;使用编程器(CH341A、FlashcatUSB)读取;最后手段 |
| 引导加载程序提取 | 通过 U-Boot md 或 sf read 命令转储 | 如果可以通过 UART 访问引导加载程序 Shell |
要拦截 OTA 更新,请将设备配置为通过 mitmproxy 代理。许多设备会忽略代理设置——可能需要 ARP 欺骗或透明网桥。如果更新通过 HTTPS 传输,请检查设备是否会验证证书;有相当多的设备并不会验证。
初步分析
提取之前,先识别格式并分析熵。
file firmware.bin
binwalk firmware.bin # identify embedded filesystems and compression
binwalk -E firmware.bin # entropy analysis -- high entropy = compressed or encrypted
hexdump -C firmware.bin | head -64 # header bytes reveal container format
strings -n 10 firmware.bin | head -100 # quick orientation
熵图说明:
- 整个镜像的熵都很高且平坦(接近 1.0)——镜像整体经过加密或压缩。你需要先获取解密密钥或解压方法才能继续。
- 高熵区域之间由低熵头部隔开——压缩的文件系统分区之间包含元数据。这很正常;提取这些分区即可。
- 整体熵较低——未压缩的文件系统或原始闪存。应该可以直接提取。
常见容器格式:
| 头部魔数 | 格式 |
|---|---|
hsqs / sqsh | SquashFS |
UBI# | UBI/UBIFS |
0x1985 | JFFS2 |
0x28cd3d45 | cramfs |
HDR0 | TRX(Broadcom 路由器) |
\x27\x05\x19\x56 | uImage(U-Boot) |
提取
根据文件系统选择合适的工具。通用提取会遗漏元数据和权限。
# General recursive extraction -- good starting point
binwalk -Me firmware.bin
# SquashFS -- the most common embedded filesystem
unsquashfs -d rootfs squashfs-root.img
# Non-standard SquashFS (vendor-modified): use sasquatch
sasquatch -d rootfs squashfs-root.img
# JFFS2
jefferson firmware.jffs2 -d rootfs
# UBI/UBIFS
ubireader_extract_images firmware.ubi
ubireader_extract_files firmware.ubi
# cramfs
cramfsck -x rootfs cramfs.img
# Raw NAND dumps may need OOB data stripped first
nandextract firmware.nand
如果 binwalk 没有发现任何内容,且熵很高,那么镜像很可能经过加密。寻找包含解密例程的引导加载程序或较早版本的固件。有些厂商会将解密密钥放在引导加载程序或配套分区中。
文件系统分析
提取完成后,将根文件系统视为一个你首次审计的 Linux 系统。
凭据和机密
# Password files
cat rootfs/etc/passwd
cat rootfs/etc/shadow
# Hardcoded credentials -- these are endemic
rg -rn 'password|passwd|admin|root|default' rootfs/etc/ --include='*.conf'
rg -rn 'BEGIN (RSA|EC|OPENSSH|DSA) PRIVATE KEY' rootfs/
rg -rn 'api[_-]?key|secret[_-]?key|token' -i rootfs/
# Certificates and keys
find rootfs -name '*.pem' -o -name '*.key' -o -name '*.crt' -o -name '*.p12'
# WiFi and VPN credentials
find rootfs -name 'wpa_supplicant*' -o -name '*.ovpn' -o -name 'ipsec.*'
/etc/shadow 中的默认凭据是最常见的固件发现。检查 root 是否有密码哈希,以及该哈希是否能被破解——通常可以。哈希处理请参阅 cracking-passwords。
配置和服务
# Startup scripts reveal what runs and how
ls rootfs/etc/init.d/ rootfs/etc/rc.d/
cat rootfs/etc/inittab
# Systemd units if present
find rootfs -name '*.service' -path '*/systemd/*'
# Installed packages and versions
cat rootfs/etc/opkg/status 2>/dev/null # OpenWrt-based
ls rootfs/usr/lib/ipkg/info/ 2>/dev/null # older ipkg
# Network configuration
cat rootfs/etc/network/interfaces 2>/dev/null
rg -rn 'iptables|ip6tables|nftables' rootfs/etc/
Web 界面
可被利用的漏洞通常藏在 Web 界面中。嵌入式 Web 服务器通常是 BusyBox httpd、lighttpd、uhttpd 或 GoAhead,负责提供以 shell、Lua 或 C 编写的 CGI 脚本。
# Find the web root
find rootfs -name 'httpd*' -o -name 'lighttpd*' -o -name 'uhttpd*'
ls rootfs/www/ rootfs/usr/www/ rootfs/usr/share/www/ 2>/dev/null
# CGI scripts -- these are the attack surface
find rootfs -name '*.cgi' -o -name '*.sh' -path '*/cgi-bin/*'
find rootfs -name '*.lua' -path '*/luci/*' -o -name '*.lua' -path '*/www/*'
# Command injection patterns in CGI
rg -rn 'system\(|popen\(|exec\(|os\.execute|io\.popen|\`.*\$' rootfs/www/
rg -rn '\$QUERY_STRING|\$REQUEST_URI|\$HTTP_' rootfs/www/
通过 CGI 参数进行命令注入,在嵌入式 Web 界面中十分常见。 常见模式是 CGI 脚本从查询参数中获取用户输入,并在未进行净化的情况下将其传递给 shell 命令。检查每个 CGI 脚本是否存在这种模式——使用 system()、popen()、反引号执行、os.execute() 和 io.popen(),且输入受用户控制。
还要检查:
- 身份验证绕过(无需登录即可访问页面)
- 诊断页面中的跨站脚本攻击(ping、traceroute、DNS 查询)
- 文件处理程序中的路径遍历
- 硬编码的会话令牌或可预测的会话生成方式
二进制分析
固件二进制文件面向非 x86 架构。反汇编前先确定架构。
# Identify architecture from ELF headers
file rootfs/usr/sbin/*
readelf -h rootfs/usr/sbin/httpd # Machine field: ARM, MIPS, PowerPC
# Common architectures in firmware
# ARM (little-endian) -- modern IoT, cameras, some routers
# MIPS (big-endian) -- routers (Broadcom, Atheros, MediaTek)
# MIPS (little-endian) -- some Realtek-based devices
# PowerPC -- older enterprise networking gear
跨架构反汇编
Ghidra 原生支持所有常见的固件架构。加载二进制文件,选择正确的处理器和字节序,然后进行自动分析。
# Ghidra headless analysis
analyzeHeadless /proj FirmwareProj -import rootfs/usr/sbin/httpd \
-processor ARM:LE:32:v7 -postScript DecompileAll.java
# radare2 with architecture specification
r2 -a arm -b 32 rootfs/usr/sbin/httpd
# For MIPS big-endian:
r2 -a mips -b 32 -e cfg.bigendian=true rootfs/usr/bin/target
重点反汇编分析:
- Web 服务器和 CGI 处理程序二进制文件
- 自定义守护进程(任何非 BusyBox 或标准软件包提供的程序)
- 实现设备特定功能的共享库
- 以 root 身份运行且接受网络输入的二进制文件
使用 QEMU 进行仿真
# User-mode emulation for individual binaries
qemu-arm -L rootfs/ rootfs/usr/sbin/httpd
qemu-mipsel -L rootfs/ rootfs/usr/bin/target
# Use -strace to trace syscalls
qemu-arm -strace -L rootfs/ rootfs/usr/sbin/httpd
# If the binary needs specific /dev nodes or /proc, use chroot
sudo chroot rootfs/ /usr/sbin/httpd
# Or mount necessary filesystems
sudo mount -t proc proc rootfs/proc
sudo mount -t sysfs sysfs rootfs/sys
网络服务
通过读取 init 脚本和二进制配置文件,枚举设备在网络上提供的服务,而不要扫描在线设备。
# Services started at boot
rg -rn 'start\(\)|start_service' rootfs/etc/init.d/
# Listening ports from configuration
rg -rn 'listen|bind|port' rootfs/etc/ --include='*.conf'
# Common embedded services to look for
find rootfs -name 'telnetd' -o -name 'dropbear' -o -name 'sshd'
find rootfs -name 'upnpd' -o -name 'miniupnpd' -o -name 'minissdpd'
find rootfs -name 'mosquitto*' -o -name 'mqtt*'
find rootfs -name 'snmpd' -o -name 'snmp.conf'
常见发现:
- 启用了 Telnet,且使用默认凭据或没有凭据
- UPnP/SSDP 将内部服务描述暴露给 WAN
- MQTT 代理未启用身份验证
- SNMP 使用默认团体字符串(
public、private) - 非标准端口上的自定义管理协议未启用身份验证
- TR-069(CWMP)接口暴露在 ISP 管理 VLAN 之外
- 调试端口(GDB 服务、网络串口)在生产环境中仍处于启用状态
全系统仿真
当单个二进制文件仿真无法满足需求时,可仿真整个固件。
# FirmAE -- automated full-system emulation
sudo python3 firmae.py -r <brand> firmware.bin
# EMBA -- comprehensive firmware analysis framework
sudo ./emba -f firmware.bin -l ./logs
# firmwalker -- static analysis without emulation
./firmwalker.sh rootfs/
FirmAE 和 EMBA 会处理难点:推断正确的 QEMU 机器类型、设置网络,以及修补 /dev/ 节点。如果它们无法运行,手动进行 QEMU 系统仿真则需要为目标平台构建正确的设备树和内核。
整个系统运行后,就像测试任何联网服务一样进行测试:使用 nmap 扫描、测试 Web 界面、对自定义协议进行模糊测试。不同之处在于,你可以访问文件系统,并在测试时阅读代码。
密码学分析
固件映像中经常包含密码学材料,并实现自定义密码方案。
# Find encryption keys and certificates
find rootfs -name '*.pem' -o -name '*.der' -o -name '*.key' -o -name '*.pub'
rg -rn 'AES|DES|RSA|SHA256|MD5|encrypt|decrypt' rootfs/usr/lib/ --include='*.so'
# Check update signature verification
# Look for signature checks in the update handler
rg -rn 'verify|signature|sign|openssl|gpg' rootfs/usr/sbin/ rootfs/etc/init.d/
检查内容:
- 未签名的固件更新——如果更新机制不验证密码学签名,处于网络路径上的攻击者就能推送任意固件。这是严重问题。
- 仅使用对称密钥签名更新——如果固件中嵌入了共享密钥,那么任何拿到固件的人都能签名更新。提取密钥并进行验证。
- 硬编码的 TLS 证书和私钥——每台设备都使用相同的密钥对。提取密钥,并证明一台设备的密钥可以解密另一台设备的流量。
- 弱加密或自定义加密——对配置文件进行 XOR“加密”、使用硬编码密钥“加密”密码,以及实际上并非加密的自定义混淆例程。
- 熵源——嵌入式设备在启动时通常熵不足。检查
/dev/urandom是否正确播种、随机数生成器是否在生成密钥前初始化,以及设备是否配备了实际在使用的硬件随机数生成器。
有关详细的密码学审查方法,请参阅 reviewing-cryptography。
防御审查清单
完成分析后,请依据以下控制措施进行评估。缺少任何一项都属于发现的问题。
| 控制措施 | 检查项 | 常见问题 |
|---|---|---|
| 更新包签名 | 更新包是否使用非对称密钥进行了加密签名?刷写前是否验证签名? | 完全没有签名,或仅使用对称密钥 |
| 安全启动 | 引导加载程序是否验证内核和 rootfs 的完整性? | U-Boot 未进行签名验证 |
| 无默认凭据 | 设备是否强制用户首次使用时更改密码? | root:root、admin:admin 或空密码 |
| 服务精简 | 是否只启用了必要的服务? | 默认启用 Telnet、UPnP、SNMP |
| 调试接口 | 生产环境中是否禁用或锁定了 UART、JTAG 和 SSH? | UART Shell 可获取 root 权限,且无身份验证 |
| 存储加密 | 凭据和密钥是否以静态加密方式存储? | 配置文件中存储明文密码 |
| 全面使用 TLS | 所有网络服务是否都使用带有效证书的 TLS? | Web 管理界面使用纯 HTTP,MQTT 未加密 |
| 输入验证 | CGI 和 API 处理程序是否验证并清理输入? | 通过 Web 参数直接注入 Shell 命令 |
| 最小权限 | 服务是否尽可能以非 root 身份运行? | 所有程序都以 root 身份运行 |
| 日志记录与审计 | 是否记录了安全事件? | 没有日志,或日志仅存储在易失性内存中 |
应当驳斥的借口
- “它在隔离网络上。” 嵌入式设备仍会暴露在外——通过 UPnP、配置错误的防火墙,或会向外部发起连接的云管理门户。应假定设备可被访问。
- “固件已加密,所以我们无法分析。” 解密密钥位于引导加载程序中,或存在于先前的未加密版本中。没有安全启动的加密只是混淆,不是保护。
- “这只是消费级设备。” 消费级设备也会组成僵尸网络。这里同样适用这些漏洞类型。
- “我们无法修补,所以为什么还要报告?” 应记录问题,以便了解风险并采取补偿性控制措施。
- “供应商说它是安全的。” 供应商的声明不是证据。文件系统才是证据。
- “这是定制 RTOS,不是 Linux,所以标准工具无法使用。” 架构层面的工具(Ghidra、QEMU、binwalk 熵分析)适用于任何二进制文件。应调整方法,而不是跳过分析。
- “没人会费心攻击这台设备。” Mirai 曾扫描整个 IPv4 地址空间,寻找默认凭据。所谓“费心”的门槛,不过是运行一个脚本。
参考资料
analyzing-binaries-- 反汇编和逆向工程方法auditing-code-for-vulnerabilities-- 有源代码时进行源码级审查enumerating-network-services-- 服务发现与评估reviewing-cryptography-- 密码学实现审查