ykorku/aws-threat-response
GitHub: ykorku/aws-threat-response
基于 Terraform 构建的 AWS EC2 自动化威胁检测与应急响应流水线,通过 GuardDuty 触发 Lambda 自动完成取证快照、实例隔离和告警通知。
Stars: 1 | Forks: 0
# AWS 上的自动化 EC2 威胁检测与响应
这是一个小型但贴近真实的应急响应 pipeline:Amazon GuardDuty 检测到针对 EC2 实例的威胁,EventBridge 将警报路由到 Lambda 函数,该函数随后进行取证快照,将实例隔离到无网络的安全组中,使用 incident 元数据对其进行标记,并通过 SNS 向人工发出警报——整个过程无需任何人接触控制台。
这不是一个简单的“GuardDuty 触发 Lambda 也跟着触发”的玩具演示。该函数会做出谨慎的决策:它会在更改任何内容之前保留证据,它会遵循手动覆盖标签以便人工可以让实例退出自动化流程,并且当 GuardDuty 引用了一个不存在的实例时(在使用样本警报进行测试时会发生这种情况),它会优雅地失败。
## 架构
```
EC2 instance (compromised)
|
v
GuardDuty -- detects the threat
|
v
EventBridge -- routes the finding
|
v
Lambda -- snapshots volumes, isolates instance, tags it
|
+----------------> SNS (emails you)
|
+----------------> CloudTrail (every API call is logged)
```
所有内容均使用 Terraform 进行配置——无需在控制台上手动点击。这听起来简单,但实际上意义重大:任何人都可以在 AWS 控制台中点击按钮,但在工作中,别人真正期望你做的是编写基础设施即代码,而且这也是使该项目可复现和可审查的关键。
## 前置条件
- 一个让你可以放心创建少量计费资源的 AWS 账户(请参阅下方的 **成本**——这很便宜但并非免费)
- 配置好 AWS CLI 且其凭证拥有创建 VPC、EC2 实例、GuardDuty detectors、CloudTrail、Lambda、IAM 角色、SNS topic 和 EventBridge 规则的权限
- [Terraform](https://developer.hashicorp.com/terraform/install) >= 1.5
- 本地无需安装 Python 3.12——Terraform 会为你打包 Lambda 代码
## 部署说明
1. 复制示例变量文件并填入你的电子邮件地址:
cp terraform.tfvars.example terraform.tfvars
编辑 `terraform.tfvars` 并将 `alert_email` 设置为你能在测试期间查收的邮箱地址。
2. 初始化并应用:
terraform init
terraform plan
terraform apply
3. **确认 SNS 订阅。** 在应用配置后的一分钟内,你会收到一封来自 AWS 的电子邮件,要求你确认订阅。点击其中的链接——如果你跳过这一步,你将永远收不到警报,并会为此困惑十分钟。
4. 记录下输出信息,特别是 `test_instance_id` 和 `guardduty_detector_id`——你将在测试时用到它们。
## 测试 —— 两种方法
GuardDuty 的样本警报使用的是你账户中不存在的占位符实例 ID,这非常贴近现实(你希望你的函数能够在“警报引用了找不到的资源”时不发生崩溃),但这并不能实际演练隔离/快照逻辑。因此,请通过这两种方式进行测试。
### 方法 1:样本警报(验证连线配置)
```
aws guardduty create-sample-findings \
--detector-id \
--finding-types UnauthorizedAccess:EC2/SSHBruteForce
```
在一两分钟内,你应该会收到一封 SNS 电子邮件,提示在警报中引用的实例“在该账户中找不到”。这是正确的预期结果——它确认了 GuardDuty、EventBridge 和 Lambda 在端到端层面上已正确连接在一起。
### 方法 2:针对真实测试实例的手动调用(验证修复逻辑)
这才是真正证明隔离和快照逻辑有效的测试,也是最值得你录屏放入个人作品集的测试。
1. 打开 `test/sample_finding_event.json`,并将 `REPLACE_WITH_YOUR_TEST_INSTANCE_ID` 替换为 `test_instance_id` 的输出值。
2. 使用该事件直接调用 Lambda:
aws lambda invoke \
--function-name \
--payload file://test/sample_finding_event.json \
--cli-binary-format raw-in-base64-out \
response.json
3. 检查 `response.json`——你应该会看到 `"status": "isolated"` 以及一系列快照 ID。
4. 在控制台或 CLI 中进行验证:该实例的安全组现在应该是隔离组,应该有一个标记为 `Purpose=forensic-auto-isolation` 的新 EBS 快照,并且该实例应该带有 `IncidentStatus=isolated` 标签。你还应该会收到第二封包含真实隔离摘要的 SNS 电子邮件。
5. 可选但值得一做的步骤:将测试实例打上 `do-not-auto-remediate=true` 标签,重新运行调用,并确认函数会跳过隔离并仅向你发送通知。这个细节表明你考虑了误报的情况,而不仅仅是顺利执行的常规路径。
## 成本
每个账户的 GuardDuty 都有 30 天的免费试用,之后将按分析的事件进行计费(对于单个测试实例,每个月只需几美元)。CloudTrail 的管理事件追踪是免费的;在这种规模下,用于存储日志的 S3 存储桶成本仅为几分之一美分。在大多数账户中,`t3.micro` 测试实例都符合免费套餐条件。测试完成后,请运行 `terraform destroy` 以避免产生任何持续的计费。
```
terraform destroy
```
## 威胁模型 —— 它能防御什么,不能防御什么
此 pipeline 负责检测并响应 GuardDuty 中与 EC2 相关的警报类型:例如,受感染的实例正在扫描 SSH 暴力破解目标、与已知的命令控制 endpoint 进行通信,或表现出加密货币挖矿行为。它无法检测 GuardDuty 本身未涵盖的威胁(它完全依赖 GuardDuty 的检测——这里没有任何自定义检测逻辑),并且它也无法防范已经获取了具有修改安全组或禁用 GuardDuty 权限的 IAM 凭证的攻击者,因为在那一步,他们可以直接撤销隔离操作。
## 权衡取舍以及面向生产环境我会做出的改变
自动化修复总是需要在速度与误报导致中断的风险之间进行权衡。在面试中,有几个决策是值得你能为其辩护的:
**为什么选择隔离而不是终止?** 终止操作会销毁证据。隔离到无网络的安全组中可以在保留实例及其卷以供调查的同时,及时止血(阻止外部的 C2 流量,防止横向移动)。
**为什么使用基于标签的覆盖,而不是总是自动修复?** 生产环境中存在一些实例,针对它们的自动网络切断比威胁本身造成的后果更严重——例如数据库主节点。`do-not-auto-remediate` 标签为运维人员提供了一个紧急出口,而无需禁用整个 pipeline。
**在真正的生产环境部署中我会添加的内容:** 针对较低严重性警报的人工审批步骤(仅在超过严重性阈值时才进行自动修复,对其余警报则通过寻呼机通知相关人员);通过 GuardDuty 的委托管理员功能进行多账户聚合,而不是使用单账户 detector;以及在 EventBridge 目标上添加死信队列,以防止失败的 Lambda 调用被无声无息地忽略掉。
## 可能的扩展
- 添加严重性阈值,以便仅针对高严重性警报触发自动隔离;较低严重性的警报仅进行通知。
- 扩展 Lambda 功能,同时撤销与实例角色关联的任何 IAM 凭证,以防入侵涉及被盗的临时凭证。
- 将此与网络层检测(例如,VPC 上的 Suricata 传感器)结合使用,以将云控制平面检测与针对同一攻击的网络层检测进行对比。
标签:AWS, DPI, ECS, Serverless, Terraform, 自动化运维, 逆向工具, 速率限制