jrlyons13/aws-incident-response-lab

GitHub: jrlyons13/aws-incident-response-lab

一个基于 Terraform 的 AWS 安全实验室项目,通过模拟加密劫持攻击来练习和演示 EC2 实例的自动化事件检测、隔离与通知流程。

Stars: 0 | Forks: 0

# AWS EC2 事件响应隔离实验室 (v1.5) 一个适合初学者的 Terraform 项目,用于练习 EC2 事件响应隔离。在 `us-east-1` 中部署一个小型实验室,模拟 cryptojacking/资源耗尽事件,并让 CloudWatch + SNS 自动触发隔离。 ## 本实验室的功能 ### v1.0(手动隔离) - 创建一个包含公有子网、Internet gateway、route table 和关联的 VPC - 启动一个带有正常安全组(允许来自您的 IP 的 SSH,允许来自任何位置的 HTTP)的 Amazon Linux EC2 实例 - 创建一个没有入站或出站规则的隔离安全组 - 提供一个接受 EC2 实例 ID 并对实例进行隔离的隔离 Lambda ### v1.4(自动化 cryptojacking 模拟) - 添加了一个**模拟器 Lambda**,它使用 **SSM Run Command** 启动临时的 CPU 压力工作负载 - 添加了一个专为实验室测试调优的 **CloudWatch CPU 告警** - 将告警状态更改发布到 **SNS** - 配置 SNS 以调用**隔离 Lambda** - 增强隔离功能以: 1. 为所有挂载的卷创建带标签的 **EBS 快照** 2. 移除 IAM instance profile 3. 附加隔离安全组 4. 发布详细的 SNS 通知 ### v1.5(Slack 通知) - 添加了一个 **Slack 通知 Lambda** 作为第二个 SNS 订阅者 - 从 **AWS Secrets Manager** 读取 Slack **Incoming Webhook URL** - 发送人类可读的 Slack 消息,用于: - **CloudWatch 告警** — 标题:`CloudWatch Alarm Triggered` 或 `CloudWatch Alarm Cleared` - **隔离事件** — 标题:`Isolation Has Occurred` 或 `Isolation Failed` - **不**修改现有的隔离 Lambda 手动隔离仍然适用于: ``` { "instance_id": "i-0123456789abcdef0" } ``` ## 架构 **AWS 自动化事件响应实验室 v1.5** — 检测 → 保留证据 → 遏制 → 通知 ![AWS 自动化事件响应实验室 v1.4 架构图](https://static.pigsec.cn/wp-content/uploads/repos/cas/71/7100e1b428d644586dbb450a66c687ba237d86083b653303b6b8a73e9724d176.png) ### SNS 通知扇出 所有事件均发布到一个 SNS topic。多个订阅者接收每条消息: | 订阅者 | 协议 | 用途 | |------------|----------|---------| | 隔离 Lambda | Lambda | 自动化遏制 | | Slack 通知 Lambda | Lambda | 格式化的 Slack 告警 | | 电子邮件 | 电子邮件 | 手动订阅(可选) | ### 工作流程摘要 1. 操作员调用模拟器 Lambda 2. 模拟器 Lambda 通过 SSM 在 EC2 实例上运行短暂的 CPU 烧录循环 3. EC2 CPU 利用率上升 4. CloudWatch 告警进入 `ALARM` 状态 5. SNS 将告警发送到 **Slack**、**电子邮件**,并调用**隔离 Lambda** 6. 隔离 Lambda 创建带标签的 EBS 快照,移除 IAM profile,附加隔离 SG,并将结果发布到 SNS 7. SNS 将隔离结果发送到 **Slack** 和**电子邮件** 在完整的试运行期间,您应该会收到**两条 Slack 消息**和**两封电子邮件**: 1. CloudWatch 告警通知 2. 隔离完成通知 ## 前置条件 在部署之前,请确保您具备: 1. 已安装 **Terraform** >= 1.5 2. 已安装并配置好 **AWS CLI** 3. 拥有具有创建 VPC、EC2、IAM、Lambda、SNS、CloudWatch、SSM 和 Secrets Manager 资源权限的 **AWS 凭证** 4. 一个 **Slack Incoming Webhook URL**(用于 v1.5 Slack 通知) ### 配置 AWS 凭证 ``` aws configure ``` 使用 `us-east-1` 作为默认区域。 验证凭证: ``` aws sts get-caller-identity ``` ## 项目文件 | 文件 | 用途 | |------|---------| | `main.tf` | 网络、EC2、IAM、SNS、CloudWatch 告警和 Lambda 资源 | | `variables.tf` | 输入变量 | | `outputs.tf` | 部署后的有用值(包括 `slack_notifier_lambda_name`、`slack_webhook_secret_name`) | | `lambda_function.py` | 隔离处理程序代码 | | `simulator_lambda.py` | CPU 压力模拟器处理程序代码 | | `slack_notifier_lambda.py` | Slack 通知处理程序代码 | ## 部署实验室 在此项目目录中: ``` terraform init terraform plan terraform apply ``` apply 完成后: ``` terraform output ``` ### 配置 Slack Webhook Secret (v1.5) Terraform 会创建 Secrets Manager secret,但**您需要手动添加 Webhook URL**,这样它就不会存储在 Terraform 状态或代码中。 在 `terraform apply` 之后,运行: ``` aws secretsmanager put-secret-value ` --secret-id (terraform output -raw slack_webhook_secret_name) ` --secret-string "https://hooks.slack.com/services/YOUR/WEBHOOK/URL" ``` 或者在 AWS 控制台中: 1. 打开 **Secrets Manager** 2. 选择在 `terraform output slack_webhook_secret_name` 中命名的 secret 3. 选择 **Retrieve secret value** → **Edit** 4. 粘贴您的 Slack Incoming Webhook URL 5. 保存 在设置此 secret 值之前,Slack 通知器 Lambda 将无法工作。 secret 值必须**仅为 Webhook URL** — 没有引号、没有 JSON 包装、没有多余的空格。 ### Slack 消息示例 在完整的事件模拟期间,Slack 通知器会发送**纯文本**消息(禁用 markdown 是为了确保可靠地显示 CloudWatch 告警详细信息)。 **消息 1 — CloudWatch 告警** ``` CloudWatch Alarm Triggered Alarm: ir-isolation-lab-cpu-high State: ALARM Instance: i-0123456789abcdef0 Metric: CPUUtilization GreaterThanThreshold 90 Reason: Threshold Crossed: 1 datapoint was greater than the threshold (90.0). Time: 2026-07-01T06:00:00.000+0000 ``` **消息 2 — 隔离完成** ``` Isolation Has Occurred Incident Type: SimulatedCryptoJacking Instance ID: i-0123456789abcdef0 Snapshots: snap-0abc123def4567890 IAM Profile: disassociated_iam_instance_profile Quarantine SG: sg-0abc123def4567890 Status: isolated Time (UTC): 2026-07-01T06:00:03.950737+00:00 ``` 如果隔离失败,标题将更改为 **Isolation Failed** 并包含错误行。 如果告警解除,标题将为 **CloudWatch Alarm Cleared**。 Slack 消息将发送到**您创建 Incoming Webhook 时配置的频道** — 而不是发送到私信 (DM)。 ### 测试 Slack 通知 通过 SNS 发送通用测试消息: ``` aws sns publish ` --topic-arn (terraform output -raw sns_topic_arn) ` --subject "IR Lab Slack Test" ` --message "Test notification from the incident response lab." ``` 您应该会看到一条主题为 `IR Lab Slack Test` 的通用 Slack 消息。 在完整的事件模拟期间,您应该会收到**两条 Slack 消息**: 1. 当 CPU 告警进入 `ALARM` 状态时的 **CloudWatch Alarm Triggered** 2. 隔离 Lambda 完成后的 **Isolation Has Occurred** 如果 Slack 消息未出现,请检查 `terraform output -raw slack_notifier_lambda_name` 的 CloudWatch Logs。日志包含检测到的消息类型(`alarm`、`isolation` 或 `generic`)。 Terraform 还会在该目录中创建一个名为 `ir-isolation-lab-key.pem` 的私钥文件。 ### 订阅 SNS 通知 电子邮件订阅需要手动确认: ``` aws sns subscribe ` --topic-arn (terraform output -raw sns_topic_arn) ` --protocol email ` --notification-endpoint you@example.com ``` 检查您的收件箱并确认订阅。 ## v1.5 测试计划 1. 运行 `terraform apply` 2. 将 Slack Webhook URL 添加到 Secrets Manager 3. 确认 EC2 以应用 SG 和 IAM instance profile 启动 4. 如果是手动配置的,请确认 SNS 电子邮件订阅 5. 发送测试 SNS 消息并确认其出现在 Slack 中 6. 调用模拟器 Lambda 7. 观察 CloudWatch CPU 指标上升 8. 确认 CloudWatch 告警进入 `ALARM` 9. 确认 **Slack 消息 1:** `CloudWatch Alarm Triggered` 10. 确认 SNS 触发隔离 Lambda 11. 确认存在带有事件标签的 EBS 快照 12. 确认 IAM instance profile 已被移除 13. 确认已附加隔离 SG 14. 确认 HTTP 访问失败 15. 确认 **Slack 消息 2:** `Isolation Has Occurred` 16. 确认 SNS 电子邮件包含告警和隔离详细信息 17. 运行 `terraform destroy` 18. 验证所有实验室资源均已被移除 ## 在事件发生前验证实例 ### 测试 HTTP ``` curl http:// ``` 您应该会看到包含 `IR Isolation Lab` 的 HTML。 ### 确认 SSM 在线 apply 后等待几分钟,然后检查: ``` aws ssm describe-instance-information ` --filters "Key=InstanceIds,Values=$(terraform output -raw ec2_instance_id)" ``` 在调用模拟器之前,实例应显示为 `Online`。 ## 调用模拟器 Lambda ### AWS 控制台 1. 打开 **Lambda** 2. 选择 `terraform output -raw simulator_lambda_name` 3. 创建一个测试事件,如 `{}` 或: ``` { "instance_id": "i-0123456789abcdef0" } ``` 4. 运行测试 ### AWS CLI ``` $functionName = terraform output -raw simulator_lambda_name aws lambda invoke ` --function-name $functionName ` --payload "{}" ` simulator-out.json Get-Content simulator-out.json ``` 模拟器默认启动一个安全且持续约 6 分钟的 CPU 压力循环。 ## 观察自动化响应 ### CloudWatch CPU 指标 1. 打开 **CloudWatch** -> **Metrics** -> **EC2** -> **Per-Instance Metrics** 2. 选择实验室实例的 `CPUUtilization` 3. 确认模拟器运行后利用率上升 ### CloudWatch 告警 打开在以下位置命名的告警: ``` terraform output cloudwatch_alarm_name ``` 在持续的高 CPU 负载后,它应进入 `ALARM` 状态。 ### 隔离 Lambda 日志 打开以下内容的 CloudWatch Logs: ``` terraform output isolation_lambda_name ``` 确认快照创建、IAM profile 移除以及隔离 SG 附加。 ## 手动隔离路径(仍受支持) 您仍然可以手动调用隔离: ``` { "instance_id": "i-0123456789abcdef0" } ``` 隔离 Lambda 还接受 SNS 告警 payload,并在需要时回退到 `TARGET_INSTANCE_ID` 环境变量。 ### AWS CLI ``` $instanceId = terraform output -raw ec2_instance_id $functionName = terraform output -raw isolation_lambda_name aws lambda invoke ` --function-name $functionName ` --payload "{\"instance_id\":\"$instanceId\"}" ` out.json Get-Content out.json ``` ## 验证隔离是否生效 在自动化或手动隔离之后: 1. **HTTP 应当失败** curl http:// 2. **EC2 控制台检查** - 仅附加了隔离安全组 - IAM instance profile 已被移除 3. **EBS 快照** - 打开 **EC2** -> **Snapshots** - 查找带有以下标签的快照: - `Incident=true` - `IncidentType=SimulatedCryptoJacking` - `CreatedBy=IncidentResponseLab` 4. **SNS 通知** - **电子邮件**应包含事件类型、实例 ID、快照 ID、IAM 结果、隔离 SG ID、时间戳和最终状态 - **Slack** 应显示 `CloudWatch Alarm Triggered`,随后是 `Isolation Has Occurred` ## 恢复正常访问(可选) 要在不销毁所有内容的情况下再次运行实验室: - 运行 `terraform apply` 以恢复应用 SG 和 IAM instance profile,或者 - 在 EC2 控制台中手动重新附加它们 如果实例已被隔离,您可能需要在 SSM 再次工作之前恢复网络连接。 ## 清理 当您完成练习后: ``` terraform destroy ``` 出现提示时键入 `yes`。 如果保留有本地生成的文件,您也可以将其删除: - `ir-isolation-lab-key.pem` - `lambda_function.zip` - `simulator_lambda.zip` - `slack_notifier_lambda.zip` ## 成本说明 如果保持运行,主要成本是 EC2 实例(`t3.micro`,在免费套餐之外约为 8-10 美元/月)。在隔离期间创建的 EBS 快照在删除之前也会产生少量存储成本。完成后请销毁资源。 ## 实验室限制 - 隔离用于遏制练习,而非完整的取证保留 - Lambda 会替换目标实例上的所有安全组 - SSH 访问取决于在 apply 时检测到您当前的公网 IP - SNS 电子邮件订阅需要手动确认 - 模拟器仅使用临时的 CPU 压力;它不是真正的恶意软件 - 由于 CloudWatch 告警时机的原因,自动化隔离可能在模拟器启动后需要 1-2 分钟 - Slack 消息仅发布到 Webhook 频道;请确认您正在查看正确的频道 ## 故障排除 | 问题 | 修复 | |-------|-----| | `terraform plan` 因凭证错误失败 | 运行 `aws configure` 并使用 `aws sts get-caller-identity` 验证 | | 模拟器因 SSM 错误失败 | 等待 SSM agent 上线;如果缺失,使用 `dnf install -y amazon-ssm-agent` 安装 | | 告警从未进入 `ALARM` | 确认模拟器已运行;检查 CPU 指标;在变量或告警控制台中降低阈值 | | 隔离 Lambda 权限错误 | 重新运行 `terraform apply`;检查 CloudWatch Logs | | 未收到 SNS 电子邮件 | 在您的收件箱中确认订阅 | | 隔离后 HTTP 仍然有效 | 刷新 EC2 控制台;确认已附加隔离 SG | | Slack 测试有效但缺少告警/隔离消息 | 打开 Webhook 频道;搜索 `CloudWatch Alarm Triggered`;检查 Slack Lambda 日 | | Slack Lambda 报告 secret 错误 | 确认 secret 值是纯 Webhook URL,没有引号或 JSON 包装 | | 完全没有 Slack 消息 | 确认已设置 secret 值;运行 SNS 测试发布;检查 `/aws/lambda/` 日志 |
标签:AWS, DPI, ECS, Terraform, 安全实验环境, 库, 应急响应, 自动化运维, 逆向工具