
1. 项目概述当合法云服务成为攻击跳板最近在分析一些高仿真的钓鱼邮件和BEC商业邮件欺诈攻击案例时我发现了一个越来越明显的趋势攻击者不再仅仅依赖那些容易被标记为垃圾邮件的自建邮件服务器或免费邮箱。他们开始大规模地“劫持”和滥用像 Amazon SESSimple Email Service这样的合法、信誉良好的云邮件服务。这就像小偷不再翻墙而是大摇大摆地刷门禁卡从正门进入大楼因为门禁系统本身是可信的。这个项目标题——“基于 Amazon SES 的钓鱼与 BEC 攻击机理及闭环防御研究”——精准地指向了这个安全攻防的前沿阵地。它探讨的不仅仅是“有人用 SES 发钓鱼邮件”这个现象而是深入到了攻击者如何系统性地利用 SES 的全链路机制以及我们作为防御方如何构建一个从身份到内容再到行为的、环环相扣的防御体系。我花了相当一段时间跟踪、复现和分析这类攻击发现其技术细节和对抗思路非常值得深挖远不是简单配置几个 SPF/DKIM 记录就能解决的。简单来说这个内容适合所有关心云安全、邮件安全、企业安全运营SOC的同行。无论你是安全工程师、运维负责人还是业务线的技术主管理解攻击者如何“合法作恶”以及如何搭建有效的监测与响应闭环都是当下不可或缺的一课。接下来我会结合我实际分析中的发现拆解攻击链条的每一个环节并分享一套经过验证的、可落地的防御思路与工具脚本。2. 攻击链路全解析从密钥泄露到成功欺诈要防御必须先透彻理解攻击。基于 Amazon SES 的攻击之所以高效且隐蔽是因为它完美地融入到了正常的云服务流量中。攻击链路通常不是单点突破而是一个精心设计的多阶段工程。2.1 攻击入口IAM密钥的获取与滥用一切始于一个有效的 AWS 访问密钥Access Key ID 和 Secret Access Key。攻击者获取它的途径远超普通人的想象绝不仅仅是“员工电脑中病毒”那么简单。公开代码库泄露这是最常见的源头。开发者在 GitHub、GitLab 等平台提交代码时不慎将包含密钥的配置文件如.env、aws/credentials或硬编码在脚本中的密钥一并上传。攻击者使用自动化工具持续扫描公开仓库一旦发现立即收录。我曾在一次应急响应中发现攻击者利用的密钥来自公司半年前一个测试项目废弃的仓库那个仓库甚至早已被创建者遗忘。第三方服务泄露企业使用的第三方SaaS、监控工具、CI/CD平台如果存在安全漏洞其存储的AWS密钥也可能外泄。攻击者会攻击这些“薄弱环节”来迂回获取核心云资产。服务器入侵与元数据服务滥用如果攻击者通过漏洞获取了EC2实例的控制权他们可以直接访问实例元数据服务IMDS来获取附加在该实例上的IAM角色临时凭证。如果该角色拥有SES发送权限攻击链路就此打通。钓鱼与凭证窃取针对运维或开发人员的钓鱼攻击诱导其登录伪造的AWS控制台或CLI工具从而窃取临时会话令牌或密钥。关键点攻击者获取的往往不仅是SES权限。一个泄露的密钥可能关联着拥有SES:SendEmail、SES:SendRawEmail、IAM:ListUsers甚至S3:GetObject权限的IAM用户或角色。这为他们后续的侦察和攻击铺垫了道路。一旦密钥到手攻击者会迅速进行验证和侦察。他们会用AWS CLI执行诸如aws ses list-identities来查看该账户下已验证的域名和邮箱地址发送源用aws iam get-user或aws sts get-caller-identity来确认密钥的有效性和所属身份信息。这个过程通常在几分钟内完成且流量与正常API调用无异。2.2 伪装艺术高仿真邮件伪造技术有了发送通道下一步是让邮件看起来绝对可信。SES本身是合规的邮件服务其发出的邮件天然拥有较高的送达率。攻击者在此基础上施展了多种伪装技术发件人地址欺骗这是BEC攻击的核心。SES允许发送者指定“源邮箱地址”。攻击者会精心伪造一个与公司高管如CEO、CFO或合作方极其相似的地址。同形异义字攻击使用看起来与拉丁字母相同的其他语言字符。例如用西里尔字母的“а”U0430替换拉丁字母的“a”U0061。ceoсompany.com注意第一个c是西里尔字母在肉眼看来几乎无法分辨。子域名伪装注册一个与目标公司域名相似的域名然后利用SES验证该域名。例如目标公司域名为company.com攻击者注册company-hr.com或company-news.com然后以financecompany-news.com的名义发送邮件在匆忙中极易被误认。显示名欺骗这是最简单也最有效的方法。在邮件头中设置From: 张总经理 (CEO) attackersgmail.com。大多数邮件客户端在收件箱列表和阅读界面会突出显示“张总经理 (CEO)”而将真正的邮箱地址attackersgmail.com放在不起眼的位置。邮件内容与模板克隆样式克隆直接截取或从历史邮件中提取目标公司的官方邮件HTML模板包括Logo、页脚、版权声明、社交媒体图标等做到像素级还原。语境化社交工程攻击者会通过LinkedIn、公司官网等渠道研究目标组织架构和近期动态如项目上线、财务结算期。在BEC邮件中他们会模仿高管的语气制造紧急性和权威性例如“我在会议中不方便电话。请立即向以下新供应商账户支付一笔加急款项合同后补。”规避内容过滤图片化文本将关键诱导性文字如“点击这里更新密码”、“立即转账”做成图片逃避基于文本关键词的过滤系统。动态内容加载邮件HTML中嵌入指向攻击者控制服务器的脚本在邮件打开时实时拉取最新的钓鱼内容使得静态邮件扫描失效。字符编码混淆使用非常见的字符编码或HTML实体编码来书写敏感词汇干扰简单的正则表达式匹配。2.3 多阶段跳转URL链路的伪装与追踪直接让用户点击一个可疑域名链接的成功率太低。现代钓鱼攻击普遍采用多阶段跳转来隐藏真实意图并筛选受害者。第一跳可信的中转站攻击者会利用大量的已建站但安全性较弱的网站如被黑的WordPress博客、免费的云存储服务、甚至是一些允许用户提交内容的合法网站如GitHub Gist、Pastebin作为初始跳转链接。邮件中的链接可能看起来是https://github.com/user/legit-project/blob/main/notice.html或https://docs.google.com/document/d/...。这些域名信誉良好能轻松通过初步的URL信誉检查。第二跳短链接与流量分发第一跳的页面可能只是一个简单的HTML元刷新跳转或者通过JavaScript在0.5秒后重定向。重定向的目标往往会经过一个短链接服务如 bit.ly, tinyurl.com这进一步隐藏了最终地址并能为攻击者提供点击数据统计——他们可以知道有多少人打开了邮件多少人点击了链接。最终目的地钓鱼着陆页或恶意软件最终页面可能是一个高度仿冒的Office 365登录页、公司内网门户、或银行登录界面。对于BEC可能直接是一个伪造的“付款信息更新”表单要求用户填写供应商银行账户信息。页面部署在另一个云服务如AWS S3静态网站、Azure Blob Storage或快速注册的廉价VPS上并可能配置了Cloudflare等CDN来隐藏真实IP。这个“合法服务 - 中转站 - 短链 - 最终恶意页面”的链条使得基于单次URL检测的防御手段非常乏力。攻击者还可以随时更换链条中的任何一个环节。3. 构建闭环防御体系从被动拦截到主动狩猎面对如此狡猾的攻击链点状的防御措施必然失效。我们需要的是一个覆盖攻击生命周期各阶段的、能够自动联动响应的闭环防御体系。这个体系我将其分为四个层次云身份层、邮件内容层、URL智能层、行为分析层。3.1 云身份层防御管好你的钥匙这是最根本的一层目标是让攻击者拿不到、用不了、用了也被立刻发现。最小权限原则与密钥生命周期管理绝对不要为任何IAM用户或角色分配SES:*这种宽泛权限。创建仅包含SES:SendEmail、SES:SendRawEmail和必要SES:GetSendQuota等权限的专属策略。为不同的应用或服务创建独立的IAM角色而非使用根账户或长期密钥。强制使用临时凭证对于所有需要调用SES的应用程序、Lambda函数或EC2实例配置IAM角色通过元数据服务获取临时安全凭证。彻底避免在代码中硬编码长期密钥。定期轮换密钥对于必须使用长期访问密钥的场景如某些本地脚本建立严格的轮换机制如每90天并使用AWS Secrets Manager或HashiCorp Vault等工具自动化管理。启用并严格监控GuardDutyAWS GuardDuty 是一个托管的威胁检测服务。你必须全局启用它并确保覆盖所有区域。重点关注以下与SES相关的威胁情报UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration 可能表示实例凭证被窃取。PenetrationTest:SES/EmailFraud GuardDuty 测试或真实攻击通过SES发送欺诈邮件。UnauthorizedAccess:EC2/SSHBruteForce或UnauthorizedAccess:EC2/RDPBruteForce 成功入侵可能导致后续SES滥用。将 GuardDuty 的发现事件自动发送到 CloudWatch Events并触发 Lambda 函数进行自动响应例如自动禁用涉事的IAM密钥将攻击源IP加入网络ACL黑名单并发送高优先级告警到Slack或SIEM系统。使用IAM Access Analyzer与配置审计使用 IAM Access Analyzer 定期扫描你的资源策略如S3存储桶策略、KMS密钥策略找出任何向外部账户或公开互联网暴露的权限这些可能是攻击者横向移动的跳板。使用 AWS Config 建立合规规则例如“确保所有SES发送身份域名或邮箱都通过了DKIM签名验证”。一旦配置偏离立即告警。3.2 邮件内容层防御在收件箱前筑起高墙这一层聚焦于在邮件到达用户收件箱之前尽可能识别和拦截恶意邮件。强化SPF、DKIM和DMARC配置这是邮件身份验证的基石但很多企业配置不全或错误。SPF 在你的域名DNS中明确列出所有被授权代表你发送邮件的服务器IP或服务如include:amazonses.com。确保策略为-all硬失败表示非列表内的服务器发送的邮件应被拒绝。DKIM 务必为SES中验证的每一个域名启用DKIM签名。SES会提供一对公私钥你将公钥以DNS TXT记录发布。DKIM能证明邮件在传输中未被篡改且确实来自你的SES服务。这是对抗发件人伪造的关键。DMARC 这是策略层。设置DMARC记录pquarantine或preject并指定一个邮箱用于接收聚合报告rua和取证报告ruf。DMARC告诉接收方服务器当SPF或DKIM验证失败时该如何处理隔离或拒绝并给你反馈报告让你知道谁在冒充你的域名发信。利用SES内置高级反垃圾邮件与反病毒功能在SES控制台的“配置集”中确保启用了所有可用的“启用”选项。自定义规则集 这是核心武器。你可以创建规则来扫描邮件内容。头部规则 检查From地址是否与Return-Path地址所属的已验证域名不匹配常见于欺骗。IP信誉规则 虽然SES IP池信誉好但可以结合接收到的DMARC报告将已知的恶意发送IP加入黑名单。内容匹配规则 使用正则表达式匹配高风险的BEC关键词如“紧急付款”、“更改账户”、“电汇指令”、“礼品卡”尤其是当这些词出现在邮件正文而非附件中时。可以设置分数阈值超过则标记或拒绝。附件与URL预扫描对于入站邮件可以配置SES将邮件先投递到一个S3存储桶然后触发Lambda函数。Lambda函数调用像VirusTotal API对公开文件或企业自建的沙箱对内部邮件对附件进行静态和动态分析。同时提取邮件中的所有URL并使用无头浏览器如Puppeteer安全地访问检查其最终跳转目的地、页面标题和内容是否与钓鱼特征匹配。这能有效破解多阶段跳转。3.3 URL智能层防御动态分析与实时阻断针对多阶段跳转我们需要更智能的URL分析能力。内部URL信誉库与实时检测建立一个内部服务专门用于分析和评级URL。当用户点击邮件中的任何链接前可通过邮件网关重写链接或浏览器插件实现先将该URL提交到此服务。服务执行以下检查域名年龄与注册信息 使用Whois查询刚注册几天或注册信息隐藏的域名风险极高。域名相似度 计算链接域名与公司内部可信域名的视觉相似度如Levenshtein距离。paypa1.com与paypal.com相似度极高。实时爬取与解析 安全地爬取目标URL分析其HTML标题、元描述、表单字段是否要求输入密码、银行卡号、以及页面内的所有二次跳转链接直至最终页。与威胁情报集成 查询 VirusTotal、URLhaus、PhishTank 等公开威胁情报源以及企业采购的商业威胁情报。链接重写与点击追踪在所有外发邮件尤其是来自客服、营销系统的邮件中强制使用邮件安全网关或SES配置集功能重写所有的HTTP链接使其先经过公司控制的代理服务器。例如将https://example.com/page重写为https://links.yourcompany.com/redirect?urlhttps://example.com/pageidabc123。这样做有两个好处一是可以对所有出站点击进行安全扫描防止公司账号被黑后向外发钓鱼链接二是可以收集点击数据如果某个链接被大量内部用户点击后指向了恶意网站能立即告警。3.4 行为分析层防御发现异常模式攻击者可以伪装内容但很难完全模仿正常用户的发送行为模式。这一层是发现高级威胁的关键。建立SES发送行为基线利用CloudWatch Logs记录SES的所有发送事件需在配置集中启用。将日志流式传输到Amazon OpenSearch或第三方SIEM中。分析历史数据建立基线例如每个发送身份From地址通常的发送量、发送频率、发送时间段。通常的收件人域名分布内部同事、合作伙伴、客户域。邮件大小的典型范围。编写检测规则当出现以下异常时告警突发性发送 某个身份在短时间内发送量激增500%。异常时间发送 在非工作时间如凌晨2-5点出现大量发送。收件人模式异常 突然向大量从未联系过的外部域名发送邮件或收件人列表中存在大量随机生成的邮箱名常见于钓鱼广撒网。发送失败率飙升 由于目标域名拒收SPF/DKIM失败或邮箱不存在导致Bounce率异常升高。用户报告与反馈闭环这是最有效但常被忽视的一环。在邮件客户端显著位置部署“报告钓鱼”按钮如通过Office 365的Report Message插件或自定义插件。用户报告的邮件被自动转发到安全团队的分析邮箱并触发一个工单。安全团队分析后如果确认为钓鱼立即执行以下操作提取攻击者使用的发送源From地址、IP、URL、附件哈希等指标IoC。在SES规则集、邮件网关、URL过滤器中全局封禁这些IoC。如果涉及内部账号泄露立即禁用该账号的SES权限并重置密码。将相关情报反馈到云身份层和URL智能层的检测规则中完善防御策略。这个“人机结合”的闭环能让防御体系不断学习和进化。4. 实操部署一个可落地的自动化响应示例理论需要实践来落地。这里我分享一个基于AWS原生服务构建的自动化响应方案的核心部分。这个方案实现了当GuardDuty检测到SES相关的恶意行为时自动禁用涉事IAM密钥并通知安全团队。架构概览GuardDuty 发现威胁事件。CloudWatch Events 捕获该事件并触发一个 Lambda 函数。Lambda 函数解析事件提取涉事的IAM访问密钥。Lambda 调用IAM API禁用该密钥。Lambda 通过Amazon SNS发送邮件/SMS或直接调用Slack Webhook将事件详情发送给安全团队。核心Lambda函数代码Python示例import json import boto3 import os import logging from botocore.exceptions import ClientError logger logging.getLogger() logger.setLevel(logging.INFO) iam_client boto3.client(iam) sns_client boto3.client(sns) # 从环境变量读取SNS主题ARN用于发送告警 SNS_TOPIC_ARN os.environ[SNS_TOPIC_ARN] def lambda_handler(event, context): logger.info(fReceived event: {json.dumps(event)}) # 1. 从CloudWatch Events中解析GuardDuty事件详情 try: # GuardDuty事件嵌套在event的detail字段下 guardduty_detail event[detail] finding_type guardduty_detail.get(type, ) resource_affected guardduty_detail.get(resource, {}) access_key_details resource_affected.get(accessKeyDetails, {}) # 提取访问密钥ID和所属用户 access_key_id access_key_details.get(accessKeyId) principal_id access_key_details.get(userName) # 或使用principalId if not access_key_id: logger.warning(No AccessKeyId found in the GuardDuty finding.) return {statusCode: 200, body: No action taken.} logger.info(fThreat Finding: {finding_type}) logger.info(fTarget AccessKeyId: {access_key_id}, User: {principal_id}) # 2. 根据检测类型决定是否执行密钥禁用这里示例为SES相关欺诈 ses_fraud_types [ UnauthorizedAccess:IAMUser/InstanceCredentialExfiltration, PenetrationTest:SES/EmailFraud, CryptoCurrency:EC2/BitcoinTool.B!DNS # 举例挖矿可能导致凭证泄露 ] if finding_type in ses_fraud_types: # 3. 禁用IAM访问密钥 try: response iam_client.update_access_key( UserNameprincipal_id, AccessKeyIdaccess_key_id, StatusInactive ) logger.info(fSuccessfully deactivated AccessKey {access_key_id} for user {principal_id}) action_taken f已禁用IAM用户 {principal_id} 的访问密钥 {access_key_id}。 except ClientError as e: error_msg fFailed to deactivate key {access_key_id}: {str(e)} logger.error(error_msg) action_taken f尝试禁用密钥失败: {error_msg} else: action_taken f事件类型 {finding_type} 未触发自动禁用规则请人工审查。 logger.info(action_taken) # 4. 发送告警通知 message f 【AWS安全事件自动响应】 事件类型: {finding_type} 事件详情: {guardduty_detail.get(description, N/A)} 严重等级: {guardduty_detail.get(severity, N/A)} 涉及资源: - IAM用户: {principal_id} - 访问密钥ID: {access_key_id} 自动响应动作: {action_taken} 事件原始ID: {guardduty_detail.get(id)} 请安全团队立即登录AWS控制台或SIEM系统进行后续调查。 sns_client.publish( TopicArnSNS_TOPIC_ARN, SubjectfAWS GuardDuty 警报 - {finding_type}, Messagemessage ) logger.info(Alert sent via SNS.) except KeyError as e: logger.error(fError parsing event structure: {str(e)}) return {statusCode: 400, body: Invalid event format.} except Exception as e: logger.error(fUnexpected error: {str(e)}) return {statusCode: 500, body: Internal server error.} return {statusCode: 200, body: Processing complete.}部署与配置要点创建IAM角色为Lambda函数创建一个执行角色该角色必须拥有以下权限策略信任策略允许Lambda服务担任此角色。权限策略包含iam:UpdateAccessKey针对特定资源或条件、sns:Publish以及必要的日志写入权限logs:*。重要为了遵循最小权限原则最好在策略的Condition中限制iam:UpdateAccessKey仅能对由GuardDuty事件触发的、特定的用户或密钥执行。这是一个高级安全实践。环境变量在Lambda函数配置中设置环境变量SNS_TOPIC_ARN为你预先创建的SNS主题ARN。创建CloudWatch Events规则事件源选择 “Event Pattern”。服务名称选择 “GuardDuty”。事件类型选择 “GuardDuty Finding”。可以进一步细化例如只匹配严重程度为“高”或特定类型如PenetrationTest:SES/EmailFraud的事件。目标选择上面创建的Lambda函数。测试你可以在GuardDuty控制台生成模拟的样本发现GuardDuty提供此功能来测试整个自动化流程是否正常工作。注意事项自动化响应是一把双刃剑。误报可能导致合法服务中断。因此在初期建议将响应动作设置为“记录”而非“禁用”并配合人工审核。运行一段时间确认规则准确率极高后再切换到自动禁用模式。同时务必确保有快速恢复通道例如另一个需要人工审批的Lambda函数来重新激活密钥。5. 常见问题与排查技巧实录在实际部署和运营这套防御体系的过程中我遇到了不少坑也总结了一些排查技巧。问题1DMARC报告收不到或解析困难。排查首先检查你的DNS记录是否发布正确rua标签指定的邮箱地址格式是否为mailto:dmarc-reportsyourdomain.com。确保该邮箱服务器能接收外部邮件且邮箱未满。技巧不要用个人邮箱建议创建一个专门的邮箱如postmaster或dmarc并配置自动转发规则将报告邮件转发到安全团队的工单系统或分析平台。可以使用开源的DMARC报告解析工具如parsedmarc将海量的XML报告自动解析、聚合并可视化这能让你一眼看清谁在冒充你的域名。问题2SES发送被大量拒收高Bounce率。排查检查发送身份域名或邮箱是否已完成SES的验证流程包括DKIM配置。检查该身份的发送配额和速率限制是否超限。检查接收方域名的反垃圾邮件策略。可以先用mail-tester.com这类服务测试你的邮件内容得分。最关键的一步查看SES的“发送统计信息”和CloudWatch中的Reputation.BounceRate和Reputation.ComplaintRate指标。如果Bounce率突然飙升很可能你的发送列表质量差包含大量无效地址或者你的IP/域名信誉因被用于攻击而受损。技巧始终采用“双重确认”订阅制收集邮箱并定期清理不活跃用户。对于新验证的域名或从低量突然转向大批量发送需要有一个“预热”过程逐步提升发送量以建立良好的发送信誉。问题3自动化响应Lambda函数误禁了合法密钥。排查立即查看CloudWatch Logs中该Lambda函数的执行日志还原触发事件的原始GuardDuty发现详情。检查发现中的resource.accessKeyDetails.userName和accessKeyId是否确实对应了攻击行为还是GuardDuty出现了误报例如一次授权的安全测试被识别为攻击。技巧在自动化响应规则中增加“白名单”机制。在Lambda函数开头读取一个存储在S3或DynamoDB中的“豁免IAM用户列表”如果触发的密钥属于列表中的用户如某个用于自动化运维的特定服务账号则跳过禁用操作仅发送高级别告警。同时建立紧急响应流程确保被误禁的关键业务密钥能通过备用方案如另一组IAM凭证或根账户在5分钟内恢复。问题4用户依然点击了漏网的钓鱼链接。排查这往往是URL跳转链中使用了全新的、信誉库中不存在的域名或者邮件内容的社会工程学技巧极高。技巧加强用户培训定期进行模拟钓鱼演练。让员工亲身体验一次高仿真的钓鱼攻击在可控范围内比发十封安全教育邮件都有效。对点击了模拟钓鱼链接的员工提供即时、友好的互动式培训。终端防护在员工电脑上部署EDR终端检测与响应或浏览器安全插件。这些工具可以基于行为如进程突然访问敏感文件目录并尝试外联来检测勒索软件或凭证窃取作为邮件网关后的最后一道防线。事后追溯如果用户报告了钓鱼邮件立即在邮件网关、代理日志、DNS查询日志中搜索该邮件的Message-ID或其中包含的独特URL找出还有哪些内部用户收到了或点击了同一批邮件进行快速隔离和通知。防御基于云服务的钓鱼和BEC攻击是一场持续的动态对抗。攻击者的技术在进化我们的防御体系也必须迭代。这套闭环防御的核心思想不是追求绝对的不可能被突破而是通过层层设防极大地提高攻击者的成本和难度同时通过快速的检测与响应将攻击造成的损失控制在最小范围。真正的安全在于假设会被突破并为此做好周全的准备。