qkhnh/Cloud-Incident-Response-Automation
GitHub: qkhnh/Cloud-Incident-Response-Automation
基于 AWS Serverless 架构的云安全事件响应自动化项目,通过 GuardDuty 检测威胁后自动隔离受损 EC2 实例,并提供带 HMAC 签名验证的审批恢复机制,解决手动响应延迟高、效率低的问题。
Stars: 0 | Forks: 0
# 云事件响应自动化
本项目使用 GuardDuty、EventBridge、Lambda 和自定义威胁情报实现了 AWS 中的威胁检测与响应自动化。当检测到潜在的安全事件时,系统会隔离受影响的 EC2 实例,将其标记为已入侵,并通过 SNS 发送实时警报。单独的 Lambda 函数可以将实例恢复到健康状态。
# 目录
[1. 项目概述与目标](#1-project-overview--objectives)
[2. 架构图与数据流](#2-architecture-diagram--data-flow)
[3. 使用的工具与 AWS 服务](#3-tools--aws-services-used)
[4. 构建步骤](#4-build-steps)
[5. 攻击模拟与结果](#5-attack-simulation--results)
[6. 恢复](#6-restoration)
# 1. 项目概述与目标
在 AWS 上管理基础设施时,快速检测并响应安全事件至关重要。手动的事件响应流程(例如识别受损的 EC2 实例、进行隔离以及通知安全团队)可能需要耗费大量的时间和精力。在此延迟期间,攻击者可能会继续窃取敏感数据,导致安全风险增加并对业务造成潜在损害。
为了解决这些挑战,我构建了一个完全自动化的事件响应流水线。该流水线能够即时检测恶意活动,隔离受损实例,清晰地标记受影响的资源,并通过实时通知向安全团队发出警报。
# 2. 架构图与数据流
# 3. 使用的工具与 AWS 服务
1. Amazon EC2
2. Amazon S3
3. Amazon SNS
4. Amazon EventBridge
5. Amazon GuardDuty
6. Amazon VPC
7. Amazon CloudWatch
8. Amazon DynamoDB
9. AWS IAM
10. AWS Lambda
# 4. 构建步骤
### 4.1 创建自定义威胁 IP 列表 (S3)
1. 打开记事本、VS Code 或任何纯文本编辑器,然后输入攻击者的 IP 地址(不需要表头或引号)
2. 保存文件并记录下来以备后用
3. AWS 控制台 → S3 → 创建存储桶
4. 输入存储桶名称(例如,GD-Threat-List)→ 保留默认设置 → 创建存储桶
5. 打开存储桶 → 上传 → 添加文件 → 选择刚才创建的文件 → 上传
6. 复制对象 URL(您将在步骤 4.3 中将其粘贴到 GuardDuty 中)
### 4.2 创建用于警报的 SNS 主题
1. 控制台 → SNS → 主题 → 创建主题
2. 类型:标准 | 名称:GD-incident-alerts(例如 IncidentAlerts、incident-alerts)→ 创建主题
3. 进入主题 → 创建订阅
- 协议:Email | 终端节点:您的电子邮件
4. 点击“创建订阅” → 打开确认电子邮件并点击“确认订阅”
5. 复制主题 ARN(Lambda 环境变量需要)
### 4.3 启用 GuardDuty 并输入您的威胁 IP 列表
1. 控制台 → GuardDuty → 入门 / 启用(如果尚未启用)
2. 左侧导航栏 → 列表 ▸ 添加威胁 IP 列表
- 名称:Threat-ip-list(例如 CustomThreatIPs、ipthreatlist) | 格式:纯文本
- 位置:粘贴步骤 4.1 中的 S3 对象 URL
- 添加列表
3. 获取 Detector ID:
- 左侧导航栏 → 设置 → “Detector” 部分。
- 记下 Detector ID。
### 4.4 开启 VPC Flow Logs(发送到 CloudWatch)
1. 控制台 → VPC → 您的 VPC → 选择默认 VPC
2. 选项卡 → 流日志 → 创建流日志
- 筛选条件:All
- 目标:发送到 CloudWatch Logs
- 创建新的日志组(例如 vpc-flow-logs、Flow-logs)
- IAM 角色:创建新角色 (vpc-flow-logs-role)
- 创建流日志
### 4.5 网络与安全组
1. 创建隔离安全组
- 控制台 → EC2 → 安全组 → 创建
- 名称:sg_deny_all(例如 sg_deny_all、sg_block_everything)
- VPC:默认
- 入站:移除所有 → 清空
- 出站:移除所有 → 清空 → 创建安全组
2. 为“目标机”创建安全组
- 名称:sg_target(例如 TARGET、target_sg)
- 入站 → 添加规则 SSH 22 | 源:0.0.0.0/0
- 入站 → 添加规则 HTTP 80 | 源:0.0.0.0/0
- 出站 → 默认 → 创建
3. 为“攻击机”创建安全组
- 名称:sg_attacker(例如 ATTACKER、attacker_sg)
- 入站 → 添加规则 SSH 22 | 源:我的 IP
- 出站 = 默认 → 创建
### 4.6 启动 EC2 实例
1. 启动目标实例
- 控制台 → EC2 → 启动实例
- 名称:target-instance(例如 Target、TARGET-EC2)
- AMI:Amazon Linux 2(符合免费套餐条件)
- 实例类型:t2.micro
- 密钥对:创建或选择现有密钥(如果是新的,请下载 .pem 文件)
- 网络设置:
- VPC:默认
- 子网:默认
- 自动分配公有 IP:启用
- 安全组:从步骤 4.5 中选择 sg_target
- 存储:保留默认 (8 GB gp2)
- 启动实例
2. 启动攻击机实例
- 控制台 → EC2 → 启动实例
- 名称:attacker-instance(例如 Attacker、Attacker-EC2)
- AMI:Kali Linux
- 实例类型:t2.micro
- 密钥对:创建或选择现有密钥(如果是新的,请下载 .pem 文件)
- 网络设置:
- VPC:默认
- 子网:默认
- 自动分配公有 IP:启用
- 安全组:从步骤 4.5 中选择 sg_attacker
- 存储:保留默认 (8 GB gp2)
- 启动实例
### 4.7 创建事件响应 Lambda(隔离)
1. 控制台 → Lambda → 创建函数
- 名称:GuardDutyIncidentResponder
- 运行时:Python 3.x
- 权限:创建具有基本 Lambda 权限的新角色 → 创建函数
2. 添加环境变量(配置 → 环境变量 → 编辑 → 添加):
- BLOCKING_SG_ID = sg_deny_all 的 ID(来自 4.5)
- SNS_TOPIC_ARN_NEW = SNS 主题 ARN(来自 4.2)
- APPROVAL_BASE_URL = 临时占位符(例如 https://example.com/placeholder)。您将在 4.12 中设置真实的 Function URL
- APPROVAL_SECRET_PARAM = 您将在 4.9 中创建的 SSM 参数名称(例如 /guardduty/approval/secret)
- INCIDENT_TOKENS_TABLE = IncidentTokens(您将在 4.8 中创建)
- EXPIRE_MINUTES = 60(或您想要的自定义数字)
- INSTANCE_TAG_KEY = IncidentStatus
- QUARANTINED_VALUE = Quarantined
3. 将代码粘贴到函数编辑器中 → 部署。
- 代码应当:
- 描述实例 → 循环遍历每个 ENI → 用拒绝所有流量的安全组替换原安全组。
- 标记实例:OriginalSGs= 和 IncidentStatus=Quarantined。
- 生成 token = uuid4().hex,expires_at = now + EXPIRE_MINUTES*60。
- 使用 HMAC-SHA256 签名 instanceId|findingId|token(密钥来自 SSM)。
- 使用 token + sig(+ findingTitle)构建审批 URL 并发布到 SNS。
4. 为角色附加最小权限的 IAM 策略(配置 → 权限 → 角色名称 → 添加内联策略):
- EC2: DescribeInstances, ModifyNetworkInterfaceAttribute, CreateTags
- DynamoDB(表:IncidentTokens):PutItem
- SNS:在您的主题 ARN 上执行 Publish
- SSM:对您的密钥执行 GetParameter(带解密)
- 日志:CloudWatch Logs 权限
### 4.8 为审批令牌创建 DynamoDB 表
1. 控制台 → DynamoDB → 创建表
2. 表名:IncidentTokens
3. 分区键:token(字符串)→ 创建表
4. 启用 TTL(表 → 其他设置 → TTL):
- 属性名称:expires_at → 启用
5. 数据项结构(Lambda 将存储/读取的内容):
- token(主键 PK),instanceId,findingId,findingTitle,created_at(整型),expires_at(整型),used(布尔型)
### 4.9 创建 SSM 参数(HMAC 密钥)
1. 控制台 → Systems Manager → Parameter Store → 创建参数
2. 名称:/guardduty/approval/secret(或您选择的路径)
3. 类型:SecureString
4. 值:一个长的随机字符串(≥32 个字符)→ 创建参数
5. 您将在两个 Lambda 中通过 APPROVAL_SECRET_PARAM 引用此名称。
### 4.10 创建恢复 Lambda(重新应用原始安全组)
1. 控制台 → Lambda → 创建函数
- 名称:RestoreGuardDutyInstance
- 运行时:Python 3.x → 创建函数
2. 行为逻辑(粘贴代码 → 部署):
- 从事件中读取 instanceId。
- 从实例中读取 OriginalSGs 标签,并拆分为列表。
- 对于每个 ENI,调用 ModifyNetworkInterfaceAttribute(Groups=)。
- 标记 IncidentStatus=Healthy。
3. 环境变量:
- RESTORE_FUNCTION_NAME = RestoreGuardDutyInstance
- RESTORED_VALUE = Healthy
- INSTANCE_TAG_KEY = IncidentStatus
- SNS_TOPIC_ARN_NEW = 您的 SNS 主题 ARN
4. 恢复角色的 IAM 权限:
- EC2:
- DescribeInstances
- ModifyNetworkInterfaceAttribute
- DescribeNetworkInterfaces
- CreateTags
- DeleteTags
- SNS:
- Publish
- CloudWatch Logs
- 附加 AWSLambdaBasicExecutionRole(创建/写入日志)
### 4.11 创建确认审批 Lambda(+ Function URL)
1. 控制台 → Lambda → 创建函数
- 名称:ConfirmApproval
- 运行时:Python 3.x → 创建函数
2. 环境变量:
- RESTORE_FUNCTION_NAME = RestoreGuardDutyInstance
- INCIDENT_TOKENS_TABLE = IncidentTokens
- APPROVAL_SECRET_PARAM = /guardduty/approval/secret
3. 暴露 HTTP 端点:配置 → 函数 URL → 创建函数 URL
- 认证类型:NONE(用于演示/测试)→ 保存
- 复制函数 URL。
4. 粘贴代码(然后部署)。代码应当:
- 解析查询字符串:instanceId,findingId,findingTitle?,token,sig,confirm。
- 验证来自 DynamoDB 的 token 记录:
- 存在,used == False,now < expires_at,ID 匹配。
- HMAC 签名匹配(密钥来自 SSM)。
- 使用 findingTitle(回退到 ID)显示居中的确认页面。
- 在批准时(confirm=1):条件更新 used=true,然后 InvokeFunction(RESTORE_FUNCTION_NAME, InvocationType="Event")。
5. ConfirmApproval 角色的 IAM 权限:
- DynamoDB(表:IncidentTokens)
- GetItem
- UpdateItem
- SSM Parameter Store(参数:/guardduty/approval/secret)
- GetParameter
- Lambda(函数:RestoreGuardDutyInstance)
- InvokeFunction
- CloudWatch Logs
- 附加 AWSLambdaBasicExecutionRole(创建/写入日志)
### 4.12 更新 Responder 的 APPROVAL_BASE_URL
- 返回 GuardDutyIncidentResponder → 配置 → 环境变量 → 编辑。
- 设置 APPROVAL_BASE_URL = 步骤 4.11 中的函数 URL(不带尾部斜杠)。
- 保存 → 再次部署响应器。
### 4.13 创建 EventBridge 规则(GuardDuty → Responder)
- 控制台 → Amazon EventBridge → 规则 → 创建规则
- 名称:GuardDutyToIncidentResponder
- 规则类型:具有事件模式的规则 → 下一步
- 事件源:AWS 服务 → GuardDuty → 事件类型:GuardDuty Finding → 下一步
- 目标:Lambda 函数 → GuardDutyIncidentResponder → 下一步 → 创建规则
# 5. 攻击模拟与结果
### 5.1 执行的攻击
为了触发 GuardDuty 发现,从 Kali EC2 实例对目标 EC2 实执行了两种不同的攻击:
- SSH 暴力破解攻击:GuardDuty 检测到源自攻击者实例的重复失败 SSH 登录尝试,将其归类为针对目标 EC2 的暴力破解攻击。
- 与自定义威胁列表的通信:由于攻击者的 IP 地址已被添加到自定义威胁 IP 列表 (S3) 中,因此目标 EC2 与此 IP 之间的任何通信都会被标记。GuardDuty 发出了一项发现,指出目标 EC2 正在与自定义威胁列表中的 IP 进行通信。
### 5.2 GuardDuty 检测
1. 在 AWS 中打开 GuardDuty 控制台。
2. 在几分钟内,您应该会看到出现新的安全发现,例如:
### 5.3 自动隔离
1. 一旦 GuardDuty 发出发现,EventBridge 规则会将其转发给 IncidentResponder Lambda。
2. Lambda 会自动:
- 将目标实例标记为 Quarantined。
- 分离其当前的安全组。
- 附加拒绝所有流量的安全组,以阻止所有入站/出站流量。
- 向您创建的 SNS 主题发布警报。
## “隔离”后的目标 EC2 标签
## “隔离”后的目标 EC2 安全组
## 隔离后的事件通知电子邮件(包含审批 URL)
# 6. 恢复
### 6.1 审批链接(电子邮件 → 确认页面)
1. 隔离后,将收到一封包含审批链接的 SNS 电子邮件(已在步骤 5 中捕获)。
2. 当打开该链接时,确认页面将显示 GuardDuty 发现的标题和目标实例 ID,允许授权用户确认恢复操作。
3. 链接中包含带有过期时间窗口的签名 token(可通过 ConfirmApproval Lambda 的环境变量进行配置,例如 LINK_TTL_SECONDS)。过期的链接将被拒绝,从而防止未经授权或失效的审批。
## 确认页面
## 点击批准后
## 使用链接后
## 链接过期后
### 6.2 审批 → 恢复工作流
审批后,ConfirmApproval Lambda 会调用 Restore Lambda,其有效载荷包含:
- instanceId
- findingId
- findingTitle(用于审计/日志记录)
- source(例如,email-approval)
Restore Lambda 将执行以下操作:
1. 重新附加原始安全组:
- 检索并重新应用由事件响应器保存的原始安全组集合(或来自实例元数据/标签,例如 OriginalSecurityGroups)。
- 从主 ENI 分离拒绝所有流量的安全组。
2. 更新标签与状态:
- 在标签中将 Quarantined 替换为 Healthy,并在 CloudWatch Logs 中记录 ResponsePhase=Restored、RestoredAt=。
3. 通知与日志:
- 发布 SNS 消息指示实例已被恢复,包括 instanceId、findingId 和 findingTitle。
- 向 CloudWatch 写入结构化日志以供审计(审批来源、token 有效性、参与者 IP/用户代理(如果已捕获))。
## 恢复通知电子邮件
## “恢复”后的目标 EC2 标签
## “恢复”后的目标 EC2 安全组
# 3. 使用的工具与 AWS 服务
1. Amazon EC2
2. Amazon S3
3. Amazon SNS
4. Amazon EventBridge
5. Amazon GuardDuty
6. Amazon VPC
7. Amazon CloudWatch
8. Amazon DynamoDB
9. AWS IAM
10. AWS Lambda
# 4. 构建步骤
### 4.1 创建自定义威胁 IP 列表 (S3)
1. 打开记事本、VS Code 或任何纯文本编辑器,然后输入攻击者的 IP 地址(不需要表头或引号)
2. 保存文件并记录下来以备后用
3. AWS 控制台 → S3 → 创建存储桶
4. 输入存储桶名称(例如,GD-Threat-List)→ 保留默认设置 → 创建存储桶
5. 打开存储桶 → 上传 → 添加文件 → 选择刚才创建的文件 → 上传
6. 复制对象 URL(您将在步骤 4.3 中将其粘贴到 GuardDuty 中)
### 4.2 创建用于警报的 SNS 主题
1. 控制台 → SNS → 主题 → 创建主题
2. 类型:标准 | 名称:GD-incident-alerts(例如 IncidentAlerts、incident-alerts)→ 创建主题
3. 进入主题 → 创建订阅
- 协议:Email | 终端节点:您的电子邮件
4. 点击“创建订阅” → 打开确认电子邮件并点击“确认订阅”
5. 复制主题 ARN(Lambda 环境变量需要)
### 4.3 启用 GuardDuty 并输入您的威胁 IP 列表
1. 控制台 → GuardDuty → 入门 / 启用(如果尚未启用)
2. 左侧导航栏 → 列表 ▸ 添加威胁 IP 列表
- 名称:Threat-ip-list(例如 CustomThreatIPs、ipthreatlist) | 格式:纯文本
- 位置:粘贴步骤 4.1 中的 S3 对象 URL
- 添加列表
3. 获取 Detector ID:
- 左侧导航栏 → 设置 → “Detector” 部分。
- 记下 Detector ID。
### 4.4 开启 VPC Flow Logs(发送到 CloudWatch)
1. 控制台 → VPC → 您的 VPC → 选择默认 VPC
2. 选项卡 → 流日志 → 创建流日志
- 筛选条件:All
- 目标:发送到 CloudWatch Logs
- 创建新的日志组(例如 vpc-flow-logs、Flow-logs)
- IAM 角色:创建新角色 (vpc-flow-logs-role)
- 创建流日志
### 4.5 网络与安全组
1. 创建隔离安全组
- 控制台 → EC2 → 安全组 → 创建
- 名称:sg_deny_all(例如 sg_deny_all、sg_block_everything)
- VPC:默认
- 入站:移除所有 → 清空
- 出站:移除所有 → 清空 → 创建安全组
2. 为“目标机”创建安全组
- 名称:sg_target(例如 TARGET、target_sg)
- 入站 → 添加规则 SSH 22 | 源:0.0.0.0/0
- 入站 → 添加规则 HTTP 80 | 源:0.0.0.0/0
- 出站 → 默认 → 创建
3. 为“攻击机”创建安全组
- 名称:sg_attacker(例如 ATTACKER、attacker_sg)
- 入站 → 添加规则 SSH 22 | 源:我的 IP
- 出站 = 默认 → 创建
### 4.6 启动 EC2 实例
1. 启动目标实例
- 控制台 → EC2 → 启动实例
- 名称:target-instance(例如 Target、TARGET-EC2)
- AMI:Amazon Linux 2(符合免费套餐条件)
- 实例类型:t2.micro
- 密钥对:创建或选择现有密钥(如果是新的,请下载 .pem 文件)
- 网络设置:
- VPC:默认
- 子网:默认
- 自动分配公有 IP:启用
- 安全组:从步骤 4.5 中选择 sg_target
- 存储:保留默认 (8 GB gp2)
- 启动实例
2. 启动攻击机实例
- 控制台 → EC2 → 启动实例
- 名称:attacker-instance(例如 Attacker、Attacker-EC2)
- AMI:Kali Linux
- 实例类型:t2.micro
- 密钥对:创建或选择现有密钥(如果是新的,请下载 .pem 文件)
- 网络设置:
- VPC:默认
- 子网:默认
- 自动分配公有 IP:启用
- 安全组:从步骤 4.5 中选择 sg_attacker
- 存储:保留默认 (8 GB gp2)
- 启动实例
### 4.7 创建事件响应 Lambda(隔离)
1. 控制台 → Lambda → 创建函数
- 名称:GuardDutyIncidentResponder
- 运行时:Python 3.x
- 权限:创建具有基本 Lambda 权限的新角色 → 创建函数
2. 添加环境变量(配置 → 环境变量 → 编辑 → 添加):
- BLOCKING_SG_ID = sg_deny_all 的 ID(来自 4.5)
- SNS_TOPIC_ARN_NEW = SNS 主题 ARN(来自 4.2)
- APPROVAL_BASE_URL = 临时占位符(例如 https://example.com/placeholder)。您将在 4.12 中设置真实的 Function URL
- APPROVAL_SECRET_PARAM = 您将在 4.9 中创建的 SSM 参数名称(例如 /guardduty/approval/secret)
- INCIDENT_TOKENS_TABLE = IncidentTokens(您将在 4.8 中创建)
- EXPIRE_MINUTES = 60(或您想要的自定义数字)
- INSTANCE_TAG_KEY = IncidentStatus
- QUARANTINED_VALUE = Quarantined
3. 将代码粘贴到函数编辑器中 → 部署。
- 代码应当:
- 描述实例 → 循环遍历每个 ENI → 用拒绝所有流量的安全组替换原安全组。
- 标记实例:OriginalSGs=
### 5.3 自动隔离
1. 一旦 GuardDuty 发出发现,EventBridge 规则会将其转发给 IncidentResponder Lambda。
2. Lambda 会自动:
- 将目标实例标记为 Quarantined。
- 分离其当前的安全组。
- 附加拒绝所有流量的安全组,以阻止所有入站/出站流量。
- 向您创建的 SNS 主题发布警报。
## “隔离”后的目标 EC2 标签
## “隔离”后的目标 EC2 安全组
## 隔离后的事件通知电子邮件(包含审批 URL)
# 6. 恢复
### 6.1 审批链接(电子邮件 → 确认页面)
1. 隔离后,将收到一封包含审批链接的 SNS 电子邮件(已在步骤 5 中捕获)。
2. 当打开该链接时,确认页面将显示 GuardDuty 发现的标题和目标实例 ID,允许授权用户确认恢复操作。
3. 链接中包含带有过期时间窗口的签名 token(可通过 ConfirmApproval Lambda 的环境变量进行配置,例如 LINK_TTL_SECONDS)。过期的链接将被拒绝,从而防止未经授权或失效的审批。
## 确认页面
## 点击批准后
## 使用链接后
## 链接过期后
### 6.2 审批 → 恢复工作流
审批后,ConfirmApproval Lambda 会调用 Restore Lambda,其有效载荷包含:
- instanceId
- findingId
- findingTitle(用于审计/日志记录)
- source(例如,email-approval)
Restore Lambda 将执行以下操作:
1. 重新附加原始安全组:
- 检索并重新应用由事件响应器保存的原始安全组集合(或来自实例元数据/标签,例如 OriginalSecurityGroups)。
- 从主 ENI 分离拒绝所有流量的安全组。
2. 更新标签与状态:
- 在标签中将 Quarantined 替换为 Healthy,并在 CloudWatch Logs 中记录 ResponsePhase=Restored、RestoredAt=
## “恢复”后的目标 EC2 标签
## “恢复”后的目标 EC2 安全组
标签:AWS, AWS Lambda, CISA项目, CloudWatch, DevSecOps, DPI, DynamoDB, EC2安全, EventBridge, GuardDuty, IP 地址批量处理, Serverless, SNS, SOAR, 上游代理, 云防护, 威胁情报, 安全告警, 安全编排与自动化响应, 实例隔离, 开发者工具, 网络安全, 自动化运维, 逆向工具, 隐私保护