| name | testing-for-sensitive-data-exposure |
| description | 在安全评估中识别敏感数据暴露漏洞,包括 API 密钥泄露、响应中的 PII、不安全存储以及未受保护的数据传输。 |
| domain | cybersecurity |
| subdomain | web-application-security |
| tags | ["penetration-testing","data-exposure","pii","owasp","web-security","api-keys","secrets"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
测试敏感数据暴露(Testing for Sensitive Data Exposure)
适用场景
- 在授权渗透测试中评估数据保护控制措施
- 评估应用程序的 GDPR、PCI DSS、HIPAA 或其他数据保护合规性
- 识别应用程序响应中泄露的 API 密钥、凭据、Token 和密钥
- 测试敏感数据在传输和静止时是否已正确加密
- 对处理 PII、金融数据或健康记录的 API 进行安全评估
前置条件
- 授权:书面渗透测试协议(含数据处理范围)
- Burp Suite Professional:用于拦截和分析响应中的敏感数据
- trufflehog:密钥扫描工具(
pip install trufflehog)
- gitleaks:Git 仓库密钥扫描器(
go install github.com/gitleaks/gitleaks/v8@latest)
- curl/httpie:用于手动端点测试
- 浏览器 DevTools:用于检查本地存储、会话存储和缓存数据
- testssl.sh:TLS 配置测试工具
工作流程
步骤 1:扫描客户端代码中的密钥
在 JavaScript 文件、HTML 源码及其他客户端资源中搜索暴露的密钥。
curl -s "https://target.example.com/" | \
grep -oP 'src="[^"]*\.js[^"]*"' | \
grep -oP '"[^"]*"' | tr -d '"' | while read js; do
echo "=== 扫描:$js ==="
if [[ "$js" == /* ]]; then
curl -s "https://target.example.com$js"
else
curl -s "$js"
fi | grep -inE \
"(api[_-]?key|apikey|api[_-]?secret|aws[_-]?access|aws[_-]?secret|private[_-]?key|password|secret|token|auth|credential|AKIA[0-9A-Z]{16})" \
| head -20
done
curl -s "https://target.example.com/static/app.js" | grep -nP \
"(AIza[0-9A-Za-z-_]{35}|AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{48}|ghp_[a-zA-Z0-9]{36}|xox[bpsa]-[0-9a-zA-Z-]{10,})"
curl -s "https://target.example.com/static/app.js.map" | head -c 500
curl -s "https://target.example.com/" | grep -inE \
"(api_key|secret|password|token|private_key|database_url|smtp_password)" | head -20
for file in .env .env.local .env.production config.json settings.json \
.aws/credentials .docker/config.json; do
status=$(curl -s -o /dev/null -w "%{http_code}" \
)
[ == ];
步骤 2:分析 API 响应是否存在数据过度暴露
检查 API 端点是否返回了超出必要范围的数据。
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users/me" | jq .
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users" | jq '.[0] | keys'
echo "=== 公开 ==="
curl -s "https://target.example.com/api/users/1" | jq 'keys'
echo "=== 已认证 ==="
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users/1" | jq 'keys'
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"invalid": "data"}' \
"https://target.example.com/api/users" | jq .
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/search?q=john" | jq .
步骤 3:测试数据传输安全性
验证敏感数据在传输过程中是否已加密。
./testssl.sh "https://target.example.com"
curl -s -v "https://target.example.com/" 2>&1 | grep -E "(SSL|TLS|cipher|subject)"
curl -s -I "http://target.example.com/" | head -5
curl -s "https://target.example.com/" | grep -oP "http://[^\"'> ]+" | head -20
curl -s "https://target.example.com/login" | grep -oP 'action="[^"]*"'
curl -s "https://target.example.com/" | grep -oP "(ws|wss)://[^\"'> ]+"
步骤 4:检查浏览器存储中的敏感数据
检查本地存储、会话存储、Cookie 和缓存响应。
curl -s -I "https://target.example.com/login" | grep -i "set-cookie"
curl -s "https://target.example.com/login" | \
grep -oP '<input[^>]*(password|credit|ssn|card)[^>]*>' | \
grep -v 'autocomplete="off"'
for page in /account/profile /api/users/me /transactions /billing; do
echo -n "$page: "
curl -s -I "https://target.example.com$page" \
-H "Authorization: Bearer $TOKEN" | \
grep -i "cache-control" | tr -d '\r'
echo
done
步骤 5:扫描 Git 仓库和源代码中的密钥
搜索版本控制中意外提交的密钥。
curl -s "https://target.example.com/.git/config"
curl -s "https://target.example.com/.git/HEAD"
git-dumper https://target.example.com/.git /tmp/target-repo
trufflehog filesystem /tmp/target-repo
gitleaks detect --source /tmp/target-repo -v
trufflehog github --org target-organization --token $GITHUB_TOKEN
gitleaks detect --source https://github.com/org/repo -v
步骤 6:测试数据脱敏和屏蔽
验证应用程序中的敏感数据是否已正确脱敏。
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/payment-methods" | jq .
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users/me" | jq '.ssn'
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users" | jq '.[].password // empty'
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/users/export?format=csv" | head -5
curl -s -H "Authorization: Bearer $TOKEN" \
"https://target.example.com/api/admin/logs" | \
grep -iE "(password|token|secret|credit_card|ssn)" | head -10
curl -s -X POST \
-H "Content-Type: application/json" \
-d '{"email":"duplicate@test.com"}' \
"https://target.example.com/api/register"
核心概念
| 概念 | 定义 |
|---|
| 敏感数据暴露(Sensitive Data Exposure) | 意外泄露 PII、凭据、金融数据或健康记录 |
| 数据过度暴露(Data Over-Exposure) | API 返回了超出客户端需求的数据字段 |
| 密钥泄露(Secret Leakage) | API 密钥、Token 或凭据暴露在客户端代码或日志中 |
| 静止数据(Data at Rest) | 存储在数据库、文件或备份中的敏感数据,未经加密 |
| 传输中数据(Data in Transit) | 通过网络传输的敏感数据,未经 TLS 加密 |
| 数据脱敏(Data Masking) | 用屏蔽值替换敏感数据(如仅显示信用卡后 4 位) |
| PII | 个人身份信息——可识别个人身份的数据 |
| 信息泄露(Information Leakage) | 响应中包含过多错误消息、堆栈跟踪或调试信息 |
工具与系统
| 工具 | 用途 |
|---|
| Burp Suite Professional | 响应分析和基于正则表达式的敏感数据扫描 |
| trufflehog | 跨 Git 仓库、文件系统和云存储的密钥检测 |
| gitleaks | 扫描 Git 仓库中的硬编码密钥 |
| testssl.sh | TLS/SSL 配置评估 |
| git-dumper | 从 Web 服务器下载暴露的 .git 目录 |
| SecretFinder | 分析 JavaScript 文件中暴露的 API 密钥和 Token |
| Retire.js | 检测存在已知漏洞的 JavaScript 库 |
常见场景
场景 1:JavaScript 包中的 API 密钥
应用程序的 JavaScript 包中包含硬编码的 Google Maps API 密钥和 Stripe 可公开密钥。Stripe 密钥权限过于宽泛,允许攻击者创建扣款。
场景 2:用户 API 返回密码哈希
/api/users 端点返回了包含 bcrypt 密码哈希的完整用户对象。攻击者可提取哈希并尝试离线破解。
场景 3:缓存 API 响应中的 PII
用户资料 API 端点返回了未脱敏的完整 SSN 和信用卡号。该端点未设置 Cache-Control: no-store,导致响应被缓存在浏览器和代理缓存中。
场景 4:含有数据库凭据的 Git 仓库
生产服务器上的 .git 目录可公开访问。攻击者使用 git-dumper 下载仓库历史,发现了在早期提交中提交、后来被"删除"但仍存在于 git 历史中的数据库凭据。
输出格式
## 敏感数据暴露评估报告
**目标**:target.example.com
**评估日期**:2024-01-15
**OWASP 类别**:A02:2021 - 加密失败
### 发现汇总
| 发现 | 严重性 | 数据类型 |
|---------|----------|-----------|
| JavaScript 源码中的 API 密钥 | High | 凭据 |
| API 响应中的密码哈希 | Critical | 认证信息 |
| 用户资料中未脱敏的 SSN | Critical | PII |
| 导出文件中的信用卡号 | High | 金融数据 |
| .git 目录暴露 | Critical | 源码 + 密钥 |
| API 端点缺少 TLS | High | 所有传输中数据 |
| 错误消息中的敏感数据 | Medium | 技术信息 |
### 严重:暴露的密钥
| 密钥类型 | 位置 | 风险 |
|-------------|----------|------|
| AWS 访问密钥(AKIA...) | /static/app.js 第 342 行 | AWS 资源访问 |
| Stripe 密钥(sk_live_...) | .env(通过 .git 暴露) | 支付处理 |
| 含凭据的数据库 URL | .git 历史提交 abc123 | 数据库访问 |
| JWT 签名密钥 | config.json(通过 .git) | Token 伪造 |
### API 数据过度暴露
| 端点 | 不必要返回的字段 |
|----------|-----------------------------|
| GET /api/users | password_hash, internal_id, created_ip |
| GET /api/users/{id} | ssn, credit_card_full, date_of_birth |
| GET /api/orders | customer_phone, customer_address |
### 建议
1. 从客户端代码中移除所有硬编码密钥;使用后端代理
2. 立即轮换所有已暴露的凭据
3. 从生产 Web 根目录中移除 .git 目录
4. 实施响应字段过滤;仅返回必要字段
5. 在所有 API 响应中脱敏敏感数据(SSN、信用卡)
6. 为所有敏感端点添加 Cache-Control: no-store
7. 在所有端点启用 TLS 1.2+;将 HTTP 重定向到 HTTPS
8. 在 CI/CD 流水线中实施密钥扫描(trufflehog/gitleaks)