4、凭据扫描工具实战:使用 TruffleHog、GitLeaks 扫描 Git 仓库中的泄露凭据
凭据泄露,说白了就是你的密码、Token、密钥被不小心写进了代码里。我见过太多工厂因为一个硬编码的数据库密码,导致整个生产网络被渗透。今天我们就来聊聊怎么用 TruffleHog 和 GitLeaks 这两个工具,把藏在 Git 历史里的“定时炸弹”挖出来。
4.1 为什么 Git 仓库是凭据泄露的重灾区?
你想想看,一个工厂的 IT/OT 融合项目,代码仓库里可能有什么?PLC 的通信密钥、SCADA 系统的数据库连接串、MES 系统的 API Token……这些东西一旦被提交到 Git,哪怕后来删掉了,历史记录里还留着。攻击者只要拿到仓库的访问权限,就能翻出这些凭据。
我在一家汽车零部件工厂做审计时,就遇到过这种情况。工程师为了方便,把 OPC UA 服务器的用户名密码直接写在了配置文件的注释里,还提交到了 GitLab。幸好我们及时发现,否则后果不堪设想。
- Git 历史记录不可篡改(除非强制 rebase 或 filter-branch)
- 凭据可能存在于多个分支、标签、提交中
- 即使删除了文件,二进制对象仍保留在 .git 目录中
4.2 TruffleHog:深度扫描 Git 历史的“猎犬”
TruffleHog 是我个人最常用的工具之一。它的原理很简单——扫描 Git 仓库的每一次提交,检查是否有高熵值字符串(比如 Base64 编码的密钥)或者已知模式的凭据(比如 AWS Key、GitHub Token)。
4.2.1 安装与基础使用
# 使用 pip 安装
pip install trufflehog
# 扫描本地仓库
trufflehog git file:///path/to/your/repo --json
# 扫描远程仓库
trufflehog git https://github.com/your/repo.git --only-verified
这里有个关键参数 --only-verified。我建议你在生产环境中一定要加上它。为什么?因为 TruffleHog 会调用对应的 API 去验证扫描到的凭据是否真的有效,能大幅降低误报率。
4.2.2 实战案例:扫描工厂 MES 系统仓库
假设我们有一个工厂 MES 系统的 Git 仓库,里面可能包含数据库连接信息。我们这样操作:
trufflehog git https://gitlab.plant.local/mes/production.git \
--only-verified \
--json \
--since-commit HEAD~100 \
> trufflehog_report.json
扫描完成后,用 jq 提取关键信息:
cat trufflehog_report.json | jq 'select(.severity == "high") | {source, detector, raw}'
我曾经用这个命令,在一个工厂的仓库里找到了 3 个有效的 AWS Secret Key。那个工程师把密钥写在了 Dockerfile 的环境变量里,还提交了 20 多个版本。要不是 TruffleHog 扫出来,这些密钥可能到现在还在泄露。
4.3 GitLeaks:轻量级、规则驱动的扫描器
GitLeaks 和 TruffleHog 的思路不太一样。它更像一个规则引擎,通过预定义的正则表达式和路径模式来匹配凭据。优点是速度快、规则可定制,适合集成到 CI/CD 流水线中。
4.3.1 安装与基础使用
# macOS
brew install gitleaks
# Linux
wget https://github.com/gitleaks/gitleaks/releases/latest/download/gitleaks-linux-amd64
chmod +x gitleaks-linux-amd64
sudo mv gitleaks-linux-amd64 /usr/local/bin/gitleaks
# 扫描本地仓库
gitleaks detect --source /path/to/repo -v
# 扫描远程仓库
gitleaks detect --source https://github.com/your/repo.git --no-git
4.3.2 自定义规则:适配工厂场景
GitLeaks 默认的规则集主要针对互联网常见的凭据类型。但工厂环境有很多特有的凭据格式,比如西门子 PLC 的通信密钥、罗克韦尔的 Tag 密码等。这时候就需要自定义规则了。
创建一个 .gitleaks.toml 文件:
title = "工厂凭据扫描规则"
[[rules]]
id = "siemens-plc-key"
description = "西门子 PLC 通信密钥"
regex = '''(S7-1200|S7-1500)_KEY_[A-Za-z0-9]{32}'''
tags = ["plc", "siemens"]
[[rules]]
id = "opc-ua-password"
description = "OPC UA 连接密码"
regex = '''(Password|Pwd)\s*[:=]\s*['"][A-Za-z0-9!@#$%^&*]{8,}['"]'''
tags = ["opcua", "scada"]
[allowlist]
paths = [
'''(vendor|third_party|node_modules)''',
'''\.git'''
]
然后运行:
gitleaks detect --source /path/to/repo --config .gitleaks.toml
4.4 两种工具的对比与选型建议
| 特性 | TruffleHog | GitLeaks |
|---|---|---|
| 扫描方式 | 基于熵值 + 模式匹配 | 基于正则规则 |
| 验证能力 | 支持(--only-verified) | 不支持(需配合其他工具) |
| 速度 | 较慢(深度扫描历史) | 较快(规则匹配) |
| 自定义规则 | 较复杂 | 简单(TOML 配置) |
| CI/CD 集成 | 支持 | 原生支持(pre-commit hook) |
| 误报率 | 中等(验证后降低) | 低(规则精准) |
我个人建议:日常开发用 GitLeaks 做 pre-commit 检查,定期用 TruffleHog 做全量历史扫描。两者互补,效果最好。
4.5 扫描结果处理与修复流程
扫描出凭据只是第一步,怎么处理才是关键。我曾经见过一个团队,扫出凭据后直接删文件重新提交,结果历史记录里还留着。正确的做法是:
- 立即撤销/轮换凭据:通知相关系统管理员,生成新凭据并更新配置。
- 从 Git 历史中彻底清除:使用
git filter-branch或BFG Repo-Cleaner重写历史。 - 强制推送并通知所有协作者:rebase 或重新 clone 仓库。
- 更新 CI/CD 流水线:加入凭据扫描步骤,防止再次发生。
4.6 知识体系:凭据扫描的核心逻辑
下面这张图展示了凭据扫描的整体流程和工具定位,你可以对照着理解:
4.7 避坑指南:我踩过的几个坑
- 不要只扫当前分支:凭据可能藏在旧分支或标签里。记得加
--all参数。 - 别忽略二进制文件:有些凭据藏在图片、PDF 或压缩包里。TruffleHog 默认会扫描二进制文件,但 GitLeaks 需要额外配置。
- 扫描结果要人工复核:自动工具难免有误报。我见过把随机生成的 UUID 当成 AWS Key 的情况。
- 定期扫描 vs 实时扫描:两者都要做。实时扫描靠 pre-commit hook,定期扫描靠定时任务。