0x9reedark/cloud-credential-incident-response-playbook
GitHub: 0x9reedark/cloud-credential-incident-response-playbook
这是一个逐步的事件响应手册,专门用于处理GitHub中暴露的AWS云凭据,以调查和恢复泄露风险。
Stars: 2 | Forks: 0
# 检测与响应手册:GitHub 中暴露的云凭据
## 执行摘要
本仓库包含一个逐步的事件响应手册,用于调查 GitHub 中暴露的云凭据。该场景适用于在经授权的组织自有环境中工作的渗透测试员、云安全工程师、SOC 分析师或事件响应人员。
该手册聚焦于一个现实的金融科技风险:一个 AWS 访问密钥被意外提交到 GitHub,并且可能已被未授权方复制或使用。响应目标是遏制凭据、证明是否被使用、确定云影响范围、安全恢复并改进预防性控制。
这是一份防御性指南。所有命令均假设您在自己的实验室、公司账户或明确授权的环境中工作。
## 为何在金融科技中至关重要
在金融科技环境中,泄露的云凭据可能演变为业务关键事件,因为云身份通常能访问敏感系统:
- 客户个人身份信息 (PII) 和 KYC 文件
- 银行账户元数据
- 支付令牌或支付处理商凭据
- 交易历史和结算记录
- 欺诈监控数据
- 数据仓库导出
- CI/CD 部署管道
- 包含敏感字段的生产日志
- Secrets Manager 或 SSM 参数存储值
- 生产工作负载使用的跨账户角色
即使没有数据被访问,此暴露也可能触发审计、合规、法律、隐私和客户影响审查。
## 场景
一位开发者意外将 AWS 访问密钥提交到了 GitHub 仓库。在提交被推送后不久,GitHub 密钥扫描生成了警报。
响应团队必须回答:
1. 具体暴露了什么?
2. 在哪里暴露的?
3. 该凭据是否活跃?
4. 谁或什么拥有该凭据?
5. 它拥有什么权限?
6. 暴露后是否被使用过?
7. 是否访问了任何敏感数据?
8. 哪些系统依赖于该凭据?
9. 我们如何安全地轮换?
10. 哪些控制措施失效,我们如何防止再次发生?
## 安全与范围
### 授权范围
仅将本手册用于:
- 您自己的 GitHub 组织或仓库
- 您自己的 AWS 账户或实验室账户
- 您拥有书面授权的客户环境
- 使用模拟凭据的受控培训实验室
### 超出范围
请勿将本手册用于:
- 测试来自您不拥有的公共仓库的泄露凭据
- 访问第三方 AWS 账户
- 不必要地拉取、复制或查看敏感数据
- 绕过身份验证或授权
- 建立持久性
- 除在批准的紧急响应下,禁用日志记录
- 发布真实的密钥、账户 ID、内部主机名或客户数据
## 响应原则
- 将暴露的凭据视为已泄露。
- 当风险较高时,先禁用再调查。
- 在可能的情况下,在进行广泛更改前保留证据。
- 不要将密钥粘贴到工单、聊天、截图或第三方工具中。
- 记录每个操作的时间戳、操作者、命令和结果。
- 优先使用短期凭据和 OIDC,而非静态访问密钥。
- 将技术发现与业务影响和控制改进关联起来。
## 所需工具
### 本地工作站
```
sudo apt update
sudo apt install -y git jq ripgrep python3 python3-pip
```
可选的密钥扫描器:
```
# gitleaks
curl -sSfL https://raw.githubusercontent.com/gitleaks/gitleaks/master/install.sh | sh -s -- -b /usr/local/bin
# trufflehog,如有可用则使用 pipx
sudo apt install -y pipx
pipx install trufflehog
```
### 命令行界面 (CLI)
```
# GitHub CLI
sudo apt install -y gh
# AWS CLI
sudo apt install -y awscli
```
登录 GitHub:
```
gh auth login
```
使用经批准的响应者角色登录 AWS。不要使用泄露的凭据。
```
aws sts get-caller-identity
```
预期结果:
```
{
"UserId": "AROAXAMPLE:responder",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/SecurityResponder/responder"
}
```
需捕获的证据:
```
mkdir -p evidence
aws sts get-caller-identity | tee evidence/aws-responder-identity.json
```
## 案例文件夹设置
在收集证据前创建一个案例文件夹。
```
CASE_ID="IR-2026-001"
mkdir -p "$CASE_ID"/{github,aws,evidence,timeline,notes,reports}
date -u +"%Y-%m-%dT%H:%M:%SZ" | tee "$CASE_ID/timeline/start-time.txt"
```
创建一个工作时间线文件。
```
cat > "$CASE_ID/timeline/timeline.md" <<'EOF'
# 事件时间线
| Time UTC | Event | Source | Analyst | Notes |
| --- | --- | --- | --- | --- |
EOF
```
添加您的第一条记录。
```
printf '| %s | Case opened | Analyst workstation | YOUR_NAME | Initial triage started |\n' \
"$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
>> "$CASE_ID/timeline/timeline.md"
```
## 阶段 1:确认警报
### 目标
确认警报是否真实,识别仓库位置,并避免进一步传播密钥。
### 步骤 1.1:捕获仓库元数据
```
ORG="example-org"
REPO="example-repo"
CASE_ID="IR-2026-001"
gh repo view "$ORG/$REPO" \
--json nameWithOwner,visibility,isFork,parent,pushedAt,defaultBranchRef,url \
| tee "$CASE_ID/github/repo-metadata.json"
```
预期结果:
- 仓库名称
- 可见性:公共、私有或内部
- 默认分支
- 分叉状态
- 如果已分叉,父仓库
- 仓库 URL
证据价值:
- 公共仓库增加暴露风险。
- 分叉增加清理难度。
- 最近的推送时间有助于界定暴露窗口。
### 步骤 1.2:捕获警报元数据
如果可通过 GitHub 界面访问 GitHub 密钥扫描,记录:
- 警报 ID
- 密钥类型
- 仓库
- 文件路径
- 提交 SHA
- 分支
- 警报创建时间
- 警报状态
- 是否绕过了推送保护
如果使用 GitHub API,列出密钥扫描警报:
```
gh api "/repos/$ORG/$REPO/secret-scanning/alerts" \
| jq . \
| tee "$CASE_ID/github/secret-scanning-alerts.json"
```
检查特定警报:
```
ALERT_NUMBER="1"
gh api "/repos/$ORG/$REPO/secret-scanning/alerts/$ALERT_NUMBER" \
| jq . \
| tee "$CASE_ID/github/secret-scanning-alert-$ALERT_NUMBER.json"
```
决策:
- 如果警报是真实的云凭据格式,则继续遏制。
- 如果它是测试密钥或已知误报,记录原因并按流程关闭。
### 步骤 1.3:审查提交而不暴露密钥
```
COMMIT_SHA="replace_with_commit_sha"
git clone "https://github.com/$ORG/$REPO.git" "$CASE_ID/github/repo-copy"
cd "$CASE_ID/github/repo-copy"
git show --summary "$COMMIT_SHA" | tee "../commit-summary.txt"
git show --name-only "$COMMIT_SHA" | tee "../commit-files.txt"
```
如果密钥将显示在您的终端记录、截图或日志中,请勿打印完整差异。
如果必须检查差异,请立即编辑输出:
```
git show "$COMMIT_SHA" \
| sed -E 's/AKIA[0-9A-Z]{16}/AKIA****************/g' \
| tee "../commit-redacted.diff"
```
需捕获的证据:
- 已编辑的提交差异
- 提交元数据
- 受影响的文件路径
- 提交作者和时间戳
## 阶段 2:保留证据
### 目标
在不过度传播密钥的情况下,收集足够的证据用于响应、审计和根本原因分析。
### 步骤 2.1:记录初始事实
```
cat > "$CASE_ID/notes/initial-facts.md" <> "$CASE_ID/timeline/timeline.md"
```
### 步骤 4.2:禁用密钥
```
aws iam update-access-key \
--user-name "$IAM_USER" \
--access-key-id "$ACCESS_KEY_ID" \
--status Inactive
```
### 步骤 4.3:验证密钥已失效
```
aws iam list-access-keys \
--user-name "$IAM_USER" \
| tee "$CASE_ID/aws/iam-user-access-keys-after-disable.json"
```
预期结果:
```
{
"AccessKeyMetadata": [
{
"UserName": "ci-deploy-user",
"AccessKeyId": "AKIA_REDACTED_KEY_ID",
"Status": "Inactive"
}
]
}
```
决策:
- 如果状态为 `Inactive`,则继续调查。
- 如果禁用失败,请立即上报给云管理员。
- 如果生产中断,继续事件流程并安全轮换。
### 步骤 4.4:记录遏制
```
printf '| %s | Exposed AWS access key disabled | AWS IAM | YOUR_NAME | Status set to Inactive |\n' \
"$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
>> "$CASE_ID/timeline/timeline.md"
```
## 阶段 5:权限审查与影响范围
### 目标
确定暴露的凭据在暴露窗口期间可以访问什么。
### 步骤 5.1:列出直接附加的托管策略
```
aws iam list-attached-user-policies \
--user-name "$IAM_USER" \
| tee "$CASE_ID/aws/user-attached-policies.json"
```
对于每个附加的策略,捕获策略文档。
```
POLICY_ARN="arn:aws:iam::123456789012:policy/example-policy"
aws iam get-policy \
--policy-arn "$POLICY_ARN" \
| tee "$CASE_ID/aws/policy-metadata.json"
```
提取默认版本:
```
POLICY_VERSION="v1"
aws iam get-policy-version \
--policy-arn "$POLICY_ARN" \
--version-id "$POLICY_VERSION" \
| tee "$CASE_ID/aws/policy-document-$POLICY_VERSION.json"
```
### 步骤 5.2:列出内联用户策略
```
aws iam list-user-policies \
--user-name "$IAM_USER" \
| tee "$CASE_ID/aws/user-inline-policy-names.json"
```
对于每个内联策略:
```
INLINE_POLICY="example-inline-policy"
aws iam get-user-policy \
--user-name "$IAM_USER" \
--policy-name "$INLINE_POLICY" \
| tee "$CASE_ID/aws/user-inline-policy-$INLINE_POLICY.json"
```
### 步骤 5.3:检查组成员资格
```
aws iam list-groups-for-user \
--user-name "$IAM_USER" \
| tee "$CASE_ID/aws/user-groups.json"
```
对于每个组:
```
GROUP_NAME="example-group"
aws iam list-attached-group-policies \
--group-name "$GROUP_NAME" \
| tee "$CASE_ID/aws/group-$GROUP_NAME-attached-policies.json"
aws iam list-group-policies \
--group-name "$GROUP_NAME" \
| tee "$CASE_ID/aws/group-$GROUP_NAME-inline-policy-names.json"
```
### 步骤 5.4:查找高风险权限
审查所有收集的策略文档,查找:
```
iam:*
sts:AssumeRole
secretsmanager:GetSecretValue
ssm:GetParameter
ssm:GetParameters
kms:Decrypt
s3:GetObject
s3:ListBucket
dynamodb:Scan
dynamodb:Query
rds:*
lambda:UpdateFunctionCode
ecs:RunTask
ecr:GetAuthorizationToken
ec2:RunInstances
cloudtrail:StopLogging
guardduty:*
organizations:*
```
快速本地搜索:
```
rg -n "iam:\*|sts:AssumeRole|secretsmanager:GetSecretValue|ssm:GetParameter|kms:Decrypt|s3:GetObject|dynamodb:Scan|cloudtrail:StopLogging|ec2:RunInstances" "$CASE_ID/aws"
```
### 步骤 5.5:创建影响范围摘要
```
cat > "$CASE_ID/reports/blast-radius-summary.md" <
标签:AWS, CloudTrail, DPI, IAM, PB级数据处理, 云凭据管理, 凭据泄露, 安全运维, 密钥轮换, 泄露检测, 爆炸半径分析, 秘密扫描, 管理员页面发现, 网络安全研究, 调查分析, 逆向工具, 遏制措施, 金融科技