凭据收集技术:Git历史记录泄露、配置文件扫描、环境变量提取、云服务元数据泄露
凭据收集,说白了就是找钥匙。你想想看,一个工厂里最值钱的东西是什么?不是机器,是那几把能打开金库的钥匙。在DevSecOps的世界里,这些钥匙就是各种凭据——API密钥、数据库密码、SSH私钥、云服务访问令牌。
我做了这么多年安全,见过太多团队把凭据当儿戏。有人把密码写在代码里,有人把密钥传到GitHub上,还有人把云服务凭证直接写在环境变量里。嗯,今天我们就来聊聊,攻击者是怎么找到这些钥匙的。
核心观点:凭据泄露不是偶然,是习惯问题。你越依赖硬编码,风险就越大。
Git历史记录泄露:最容易被忽视的宝藏
Git历史记录泄露,是我见过最频繁的凭据泄露方式。很多人以为删掉文件就没事了,但Git会记住一切。你提交过的东西,哪怕后来删了,历史里还留着。
我记得有一次做渗透测试,目标是一个电商平台。我什么都没干,就拉了一下他们的公开仓库,然后跑了个git log --all --oneline,发现一条提交信息写着"fix: remove hardcoded db password"。我直接git show那个commit,数据库密码就躺在那里。嗯,就是这么简单。
实战技巧:使用 git log --all -p --diff-filter=D 可以快速找到被删除的文件内容。攻击者最喜欢这个命令。
常见的Git泄露场景有哪些?我列一下:
- 硬编码凭据提交:开发人员图省事,直接把密码写在代码里
- 配置文件误提交:.env、config.json、database.yml 被不小心push上去
- 密钥文件泄露:.pem、.key、.p12 文件被提交到仓库
- 历史记录未清理:删除了文件但没清理Git历史
- 分支泄露:feature分支里包含敏感信息,合并到master后没清理
怎么查?我习惯用这几个命令:
# 查看所有提交记录
git log --all --oneline
# 搜索历史中的密码模式
git log --all -p | grep -i "password\|secret\|token\|api_key"
# 查找被删除的文件
git log --all --diff-filter=D --name-only
# 查看某个特定文件的变更历史
git log -p -- filename
注意:不要以为私有仓库就安全。内部人员、第三方合作方、甚至被攻破的CI/CD系统都可能访问到这些历史记录。
配置文件扫描:自动化找钥匙
配置文件扫描,说白了就是自动化地翻箱倒柜。攻击者不会手动一个个文件看,他们会写脚本,扫描常见的配置文件名和路径。
我见过一个案例,攻击者扫描了目标服务器的/var/www/html目录,发现了一个.env.bak文件。这个备份文件里包含了数据库连接信息、Redis密码、甚至AWS的Access Key。你想想看,一个备份文件,毁了一个公司。
常见的配置文件扫描目标:
| 文件类型 | 常见文件名 | 可能泄露的凭据 |
|---|---|---|
| 环境变量文件 | .env, .env.production, .env.local | 数据库密码、API密钥、JWT密钥 |
| 应用配置文件 | config.json, application.yml, settings.py | 第三方服务凭据、OAuth令牌 |
| 云服务配置文件 | .aws/credentials, .azure/credentials, gcloud.json | 云服务Access Key、Secret Key |
| 数据库配置文件 | database.yml, dbconfig.php, connectionstrings.xml | 数据库用户名密码、连接字符串 |
| 备份文件 | .bak, .old, ~, .swp | 原始配置内容,可能包含所有凭据 |
攻击者常用的扫描工具和命令:
# 使用find命令扫描常见配置文件
find / -name ".env" -o -name "*.pem" -o -name "credentials" 2>/dev/null
# 使用grep搜索敏感关键词
grep -r "password" --include="*.php" --include="*.py" --include="*.js" /var/www
# 使用curl检查云元数据
curl http://169.254.169.254/latest/meta-data/
我的建议:在CI/CD流程中加入配置文件扫描步骤。用truffleHog、git-secrets这类工具,在代码合并前就拦截住敏感信息。
环境变量提取:藏在进程里的秘密
环境变量,是很多团队存放凭据的"安全区"。他们觉得环境变量比硬编码安全,但真的安全吗?
我做过一个实验。在一台生产服务器上,我执行了ps aux,发现一个Java进程的启动参数里直接写了数据库密码。嗯,你没看错,启动参数。然后我又看了/proc/1/environ,里面躺着AWS的Secret Key。
环境变量泄露的常见途径:
- 进程信息泄露:通过
/proc/[pid]/environ读取进程的环境变量 - 错误日志泄露:应用报错时把环境变量打印到日志里
- 调试接口泄露:/actuator/env、/debug等端点暴露环境变量
- 容器逃逸:从容器内部读取宿主机的环境变量
- Dump文件泄露:核心转储文件包含进程环境变量
攻击者怎么提取?看这里:
# 读取当前环境变量
env
# 读取特定进程的环境变量
cat /proc/1/environ | tr '\0' '\n'
# 通过调试接口获取
curl http://target.com/actuator/env
# 从Docker容器中读取
docker exec container_id env
我曾经踩过的坑:有一次我把AWS密钥放在环境变量里,然后在代码里打印了所有环境变量用于调试。上线前忘了删调试代码,结果日志里全是凭据。从那以后,我坚持用专门的密钥管理服务,比如Vault、AWS Secrets Manager。
云服务元数据泄露:云上的定时炸弹
云服务元数据泄露,是近几年最火的攻击面。为什么?因为云厂商为了方便,把凭据直接放在元数据服务里。你只要访问一个IP地址,就能拿到临时凭据。
我记得有一次做红队演练,我们拿到了一台EC2的WebShell。我什么都没干,先访问了http://169.254.169.254/latest/meta-data/iam/security-credentials/,然后拿到了一个IAM角色的临时凭据。这个角色有S3的读写权限,我们直接把目标的所有数据拖走了。
各大云厂商的元数据地址:
| 云厂商 | 元数据服务地址 | 获取凭据路径 |
|---|---|---|
| AWS | http://169.254.169.254 | /latest/meta-data/iam/security-credentials/ |
| Azure | http://169.254.169.254 | /metadata/identity/oauth2/token?api-version=2018-02-01 |
| GCP | http://metadata.google.internal | /computeMetadata/v1/instance/service-accounts/default/token |
| 阿里云 | http://100.100.100.200 | /latest/meta-data/ram/security-credentials/ |
攻击者常用的元数据攻击手法:
# AWS元数据获取
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME
# Azure元数据获取
curl 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/' -H 'Metadata: true'
# GCP元数据获取
curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# 通过SSRF漏洞利用
curl http://target.com/proxy?url=http://169.254.169.254/latest/meta-data/
关键点:元数据泄露通常和SSRF(服务端请求伪造)漏洞配合使用。攻击者先找到SSRF漏洞,然后通过元数据服务获取云凭据,最后用这些凭据访问云资源。
怎么防御?我总结了几条:
- 限制元数据服务访问:使用iptables或安全组限制对169.254.169.254的访问
- 使用IMDSv2:AWS的IMDSv2需要PUT请求和令牌,比v1安全得多
- 最小权限原则:给IAM角色分配最小必要权限,即使凭据泄露也能控制损失
- 网络隔离:敏感服务不要放在公网,使用VPC和私有子网
- 监控异常访问:监控对元数据服务的访问,发现异常立即告警
实战建议:在代码中不要直接访问元数据服务。使用SDK自动获取凭据,SDK会处理令牌刷新和缓存。手动访问元数据服务容易留下痕迹,也容易被安全工具检测到。