3. 固件文件系统遍历与敏感信息搜索
任务目标
对给定的嵌入式设备固件进行解包,遍历其文件系统,定位并提取硬编码密码、私钥、API令牌等敏感信息,形成可复现的审计流程。
环境准备
本案例使用 binwalk 进行固件解包,grep 与 find 完成文件系统遍历与敏感信息搜索。所需工具安装命令如下(Ubuntu/Debian):
sudo apt-get update && sudo apt-get install -y binwalk
固件获取与解包
以某开源路由器固件为例(router_fw.bin),执行以下命令解包:
binwalk -e router_fw.bin
ls _router_fw.bin.extracted/
若固件包含多层压缩(如先LZMA再SquashFS),需对解包产物递归执行 binwalk -e,直至获得完整的根文件系统目录(通常包含 /bin、/etc、/usr 等标准目录)。
敏感信息搜索脚本
以下脚本对解包后的根目录执行递归搜索,覆盖密码、私钥、证书、及连接字符串等常见敏感信息:
#!/bin/bash
# scan_firmware.sh - 固件敏感信息扫描器
# 用法: ./scan_firmware.sh <固件根目录>
ROOT_DIR="$1"
if [ -z "$ROOT_DIR" ]; then
echo "用法: $0 <固件根目录>"
exit 1
fi
echo "[*] 开始扫描: $ROOT_DIR"
echo "[*] 搜索硬编码密码..."
grep -rniE "(password|passwd|pwd)\s*[=:]\s*[^\"'<>]{4,}" \
--include="*.conf" --include="*.cfg" --include="*.ini" \
--include="*.sh" --include="*.php" --include="*.cgi" \
--include="*.html" --include="*.js" "$ROOT_DIR" 2>/dev/null \
| grep -viE "(password\s*[=:]\s*$|passwd\s*[=:]\s*$)" \
| head -50
echo "[*] 搜索私钥与证书..."
find "$ROOT_DIR" -type f \( -name "*.pem" -o -name "*.key" -o -name "*.crt" \
-o -name "id_rsa" -o -name "*.p12" \) 2>/dev/null | head -30
echo "[*] 搜索与令牌..."
grep -rniE "(api[_-]?key|secret||auth)\s*[=:]\s*[a-z0-9]{16,}" \
"$ROOT_DIR" 2>/dev/null | head -30
echo "[*] 搜索数据库连接字符串..."
grep -rniE "(mysql|postgres|mongodb|redis)://[^\"'<> ]+" \
"$ROOT_DIR" 2>/dev/null | head -20
echo "[*] 扫描完成"
赋予执行权限并运行:
chmod +x scan_firmware.sh
./scan_firmware.sh _router_fw.bin.extracted/_router_fw.bin.extracted/
验证方法与判定标准
验证分为两个层面:
- 脚本有效性验证:在扫描结果中应能看到至少一条包含明文口令(如
password="admin123")或私钥文件路径的输出。若输出为空,可先在一个已知包含测试字符串的目录上运行脚本,确认grep语法与路径正确。 - 结果真实性验证:对脚本输出的每个敏感文件,手动执行
cat或strings确认内容确实包含可读的凭据信息。例如:cat _router_fw.bin.extracted/etc/shadow若能看到非*或!的哈希值,即为有效发现。
通过条件:脚本成功遍历固件文件系统,输出至少3类不同的敏感信息命中(如密码、私钥、),且人工复核确认命中项真实存在、非误报。
常见问题
- 解包不完整:部分固件使用UbiFS或JFFS2格式,binwalk可能无法直接处理。此时需使用
jefferson(JFFS2)或ubi_reader(UBI)工具补充解包。 - 误报过滤:默认grep会匹配大量注释或示例代码。可通过增加
--exclude-dir=doc、--exclude-dir=example或提高匹配字符串长度阈值来降低噪声。 - 二进制文件中的敏感信息:若敏感信息嵌入在编译后的二进制中,需额外使用
strings命令配合grep:find "$ROOT_DIR" -type f -exec strings {} \; 2>/dev/null | grep -iE "password="。