询问ChatGPT
Black Hat 2025最新披露的ECScape漏洞研究,揭示了AWS ECS服务中IAM安全边界的系统性缺陷。该漏洞允许攻击者通过伪造ECS代理会话,绕过隔离机制窃取同主机所有任务的IAM凭证,实现权限提升。研究表明,这一攻击基于ECS默认配置即可实施,影响数百万运行在EC2上的容器实例。本文将深入剖析攻击原理、演示实际利用过程,并探讨云原生架构下的新安全范式。 资源: 注:本文翻译自Sweet Security - Naor Haziz[4]的文章《ECScape: Understanding IAM Privilege Boundaries in Amazon ECS》[5],可点击文末“阅读原文”按钮查看英文原文。 全文如下: 本文是我们关于Amazon ECS安全的教育系列文章的第二部分。在第一部分 - Amazon ECS on EC2深度解析[6]中,我们探讨了ECS代理、IAM角色和ECS控制平面如何为任务提供凭证。本文将展示当具有不同权限级别的任务共享同一EC2主机时,这些机制如何导致已知风险。这种跨任务凭证暴露凸显了当工作负载共享同一EC2实例时,依赖每个任务IAM范围界定和任务执行边界的固有风险,同时也解释了为什么Fargate(每个任务在独立的micro‑VM中运行)能提供更强的隔离性。我们的目标是帮助您理解Amazon ECS中的IAM权限边界,以及如何安全配置您的服务。 云环境提供了无与伦比的灵活性和可扩展性,但也带来了复杂的安全考量。如果您误以为存在容器级隔离而实际并不存在,则AWS服务之间微妙的交互可能会导致意外的权限暴露。在本文中,我将带您了解我是如何在Amazon ECS(弹性容器服务)中发现这种跨容器IAM凭证暴露的,演示相关技术(称为**"ECScape"**),并分享保护您自身环境的安全经验。通过揭开控制平面的神秘面纱,我们希望为读者提供构建隔离架构的知识,并推动相关改进。 快速回顾:在EC2启动类型中,ECS控制平面会承担每个任务角色,通过ACS WebSocket将凭证推送给代理,再由代理通过169.254.170.2分发给任务。ECScape正是滥用了这个交付路径。 我最初并非专门研究ECS,而是为了完善一个基于eBPF的实时监控工具。为了构建精确的每个任务仪表板,我需要一种快速本地化的方法来实现:进程→容器→ECS任务的映射,并标记集群名称、任务ARN和服务名称等元数据。 在实验中,我首先尝试从Docker容器标签获取数据(ECS会自动为每个任务添加包含任务ARN、任务定义家族(含版本号)、集群ARN和容器名称等标签)。但令人意外的是,这些标签中唯独缺少服务名称。 为获取缺失的服务名称,我转向ECS代理在每个容器网络命名空间内暴露的ECS任务元数据端点(v4版本,位于169.254.170.2/v4/…)。从容器内部查询该端点后,我成功获取了包括服务名称、任务定义族、版本号等完整信息——这完美契合我的监控需求。 出于职业敏感,我思考是否能让eBPF传感器直接模拟代理行为——通过查询相同元数据端点来聚合主机上任意进程的数据。但在尝试前,我复查了EC2实例IAM角色(即附加到容器主机的 好奇心驱使我进行了网络流量抓包分析。通过搭建本地代理观察ECS代理与AWS端点的通信,我发现了令人震惊的现象: 此刻我意识到,ECS控制平面正在通过这个WebSocket通道主动推送任务凭证给代理。虽然这是代理向容器分发凭证的正常机制,但一个危险的想法浮现:如果我能劫持这个通道,是否就能获取本不该属于我容器的凭证? 更关键的是:如果控制平面将所有任务凭证都发送给代理,那我能否伪装成代理,诱骗AWS也向 这个疑问最终催生了ECScape攻击技术——一个探索如何通过突破容器边界并伪装ECS代理来窃取其他任务凭证的攻击场景。 下面我们将逐步拆解ECScape的实际攻击流程。攻击者(某个容器内的恶意进程)的目标是获取同一EC2主机上所有其他任务的IAM凭证。具体步骤如下: 攻击起点是一个已被入侵的容器(EC2上运行的任意低权限ECS任务)。在默认配置下,容器可以访问实例元数据服务(IMDS)。只需向 此时攻击者持有EC2实例的临时凭证(代表容器实例的STS会话)。需特别注意:这些凭证并非应用容器的任务角色凭证。由于IAM信任边界限制,仅凭实例配置文件的凭证无法直接接管任务角色: 因此,若攻击者尝试直接用实例凭证调用AWS STS来担任其他任务角色,将会因任务角色的信任策略(且可能存在IAM权限缺失)而失败。攻击者无法通过常规的 AssumeRole API 调用转向任务角色,必须另辟蹊径——这正是伪装代理的价值所在。 安全须知: 从容器内部读取IMDS(HTTP GET请求)不会被CloudTrail记录,因此初始凭证窃取行为具有隐蔽性。但当攻击者使用窃取的实例凭证调用AWS API时(后续步骤),这些操作将在CloudTrail日志中显示为实例角色所为。 ECS代理并非与通用的公共API端点通信,而是通过AWS为每个集群和容器实例分配特定的轮询端点进行控制平面交互。攻击者利用窃取的实例角色凭证,调用ECS API 实例IAM角色默认拥有调用DiscoverPollEndpoint的权限(这是代理正常工作的基础权限)。若API调用意外失败,攻击者仍可能通过特征猜测端点(通常包含区域标识和集群特征值),但直接调用API是最可靠的方式。至此,攻击者已掌握控制平面通信发起连接的目标地址。 真实的ECS代理连接ACS时需提交多项标识信息,以便后端知道由哪个集群和哪个特定的容器实例(EC2 主机)发起,攻击者必须伪造这些数据才能完成伪装。关键信息包括: 攻击者通过先前使用的任务元数据端点(169.254.170.2)可轻松获取集群ARN(每个任务的元数据都包含集群信息)。真正的挑战在于获取容器实例ARN——该信息通常不会通过标准元数据端点暴露给任务。但ECS代理提供了一个自省API(通常从主机访问),可返回容器实例ARN等敏感信息。在漏洞利用过程中,我们发现通过查询特定的本地端点,竟然可以从容器内部获取容器实例ARN。虽然也可以通过AWS API的 关键发现: 容器能访问代理自省API本身就是一个隔离缺陷。该API本应只绑定主机localhost或Unix套接字,但若暴露在链路本地地址且未被iptables规则过滤,容器便可直接访问。虽然这只是攻击链中的一小环,但充分说明了安全暴露面如何被攻击者利用。 至此,攻击者已掌握集群ARN、容器实例ARN等关键标识,完成了伪装ECS代理的全部准备工作。 此刻,攻击者需要与ECS控制平面建立伪造的代理会话。使用步骤2获取的轮询端点URL(例如 WebSocket URL包含所有标识符和配置的查询参数,例如: 关于此步骤的重要说明: 如果签名和参数全部正确,AWS会接受该WebSocket连接,就像对待真实容器实例上的ECS代理一样。从ECS控制平面的视角来看,我们的恶意进程现在只是该实例的另一个已授权代理会话。 事实证明,AWS并未严格强制实施"每个实例仅限一个代理"的规则。在我的测试中,最终出现了同一容器实例的两个并发连接——一个来自真实的ECS代理,另一个来自我的伪装会话。控制平面会同时向两者发送消息(如果AWS限制每次只能有一个连接,我的伪造代理会话可能会使真实代理离线或被拒绝,从而引发警报。但就目前情况而言,我可以在完全隐蔽的情况下窃听数据流)。 当伪造的WebSocket会话建立后,攻击者将与真实ECS代理共享同一个多路复用的ACS消息流。通过这个通道,ECS控制平面会持续推送结构化消息:心跳包(包含序列号的存活检测)、任务生命周期指令(启动/停止/更新命令)、遥测数据,以及最重要的——IamRoleCredentials凭证载荷。 需要明确ECS处理任务凭证的标准流程:ECS服务(AWS中的 由于我们的伪造代理会话包含 伪造的代理通道还能保持隐蔽性。恶意会话会模拟代理的预期行为——确认消息、递增序列号、发送心跳——因此不会引发异常。ECS实际上允许同一容器实例存在多个认证会话,因此真实代理仍能正常运作并接收相同的凭证消息。从控制平面的视角看,这只是常规的凭证推送流程,毫无异常。 CloudTrail可见性分析: 需要注意的限制/细节: 总之,ECS将AssumeRole过程集中在控制平面,然后将这些临时凭据“移动”到主机代理,依赖ACS通道的保密性和按任务划分的元数据范围来实现隔离。通过伪装代理的上游连接,ECScape彻底瓦解了这种信任模型:一个被攻陷的容器可以被动收集同EC2实例上所有其他任务的IAM角色凭证,并立即以这些权限执行操作。 ECScape漏洞对所有在共享EC2主机上运行ECS任务的用户都产生了深远影响: ECScape实机演示如下: 在ECScape实机演示中,我在同一EC2实例上部署了三个ECS任务,来演示低权限容器如何提权并入侵敏感资源: 演示过程中展示了 核心结论:当容器与高权限任务共享主机时,即使本身没有有效权限的容器也可能入侵高价值资源。这打破了多数团队依赖的隔离假设。 AWS官方对此问题的回应是:ECS正在按其设计初衷运行:共享同一EC2主机的容器默认处于同一信任域,除非用户主动隔离。换言之,AWS认为这是"预期行为"(其完整回应将在后文详述),因此既未发布补丁也未分配CVE编号。这意味着加固ECS-on-EC2环境的责任落在了用户肩上。 以下关键防护措施可有效防御ECScape类攻击场景: 通过实施上述措施——特别是严格限制任务对IMDS的访问——可显著降低ECScape类攻击的风险。值得注意的是,本研究发布后AWS已更新官方文档,明确警示:"同一EC2实例上运行的任务可能获取属于其他任务的凭证",并强烈推荐使用Fargate获得更强的隔离保障,并通过CloudTrail监控跨任务角色使用情况。 当我们通过AWS协调披露计划报告ECScape漏洞时,经过技术评审,AWS确认该现象属于ECS在EC2上的设计特性而非安全漏洞。AWS认为:除非用户主动实施隔离,否则共享同一EC2实例的容器默认处于同一信任域。由于未突破AWS的安全边界,AWS未发布CVE编号或安全公告,但强调客户应据此设计架构。 AWS已通过ECS安全最佳实践博客[8]公开重申这一立场,明确建议需要强隔离的场景应选用Fargate。 尽管如此,AWS仍采取了两个重要举措: 从研究者视角看,ECScape深度探讨了ECS如何整合控制平面角色假设、主机凭证分发和容器隔离机制。核心教训在于:必须将每个容器视为潜在突破口并严格限制其影响范围。AWS提供的抽象层(任务角色、元数据服务等)虽然简化了开发,但当不同权限级别的任务共享主机时,其安全性完全取决于隔离机制的强度——而这些机制可能存在微妙缺陷。 随着行业向强隔离模式演进(如Fargate的per-task microVM、Firecracker、gVisor等沙箱技术,乃至Nitro Enclave等硬件隔离方案),这类跨容器凭证窃取将愈发困难。但当前仍有大量环境因成本或管理因素在共享EC2实例上运行异构工作负载。ECScape模糊了配置错误、设计取舍与漏洞利用之间的界限,凸显了纵深防御的重要性。阻断非必要IMDS访问、实施最小权限、隔离关键任务、监控异常行为等不仅是最佳实践清单项目,更是能切断攻击链的关键防御节点。 最终,提升此类场景的安全性需要共同责任:云服务商需持续优化隔离原语和凭证分发机制,云用户则需在设计时假设任何容器都可能变为恶意实体。通过深入理解ECS凭证分发机制(如本文所述)和信任边界,您将能做出更明智的云架构和监控决策。一、引言
二、内容提要
ECS_AWSVPC_BLOCK_IMDS
设置)。同时对所有任务IAM角色实施最小权限原则,并移除不必要的Linux能力(限制被入侵容器的操作能力)。下文将详细介绍最佳实践和检测技巧。三、发现过程
ecsInstanceRole
)的权限,发现一个异常现象:该角色并不具备ecs:ListServices等常规ECS API权限,理论上它无法获取服务名称。然而代理却通过元数据端点准确提供了服务名称——这说明代理显然是从ECS控制平面而非公开API获取的这些信息。?sendCredentials=true
我
发送这些凭证?四、ECScape攻击原理:伪装ECS代理窃取其他任务凭证
sendCredentials
4.1 步骤1:通过IMDS窃取EC2实例角色凭证
http://169.254.169.254/latest/meta-data/iam/security-credentials/{InstanceProfileName}
发送curl请求,即可获取EC2主机IAM角色的访问密钥、秘密密钥和会话令牌——这些正是主机上ECS代理使用的凭证。至此,恶意容器已成功窃取主机角色凭证。ecs-tasks.amazonaws.com
(ECS服务),不信任EC2实例角色本身sts:AssumeRole
权限4.2 步骤2:发现轮询端点URL(
ecs:DiscoverPollEndpoint
)ecs:DiscoverPollEndpoint
。该API会返回形如https://ecs-a-1..amazonaws.com
的专属URL,这正是代理接收ACS消息的真实通信端点。4.3 步骤3:收集所需标识信息(集群ARN、容器实例ARN等)
ecs:ListContainerInstances
获取,但这通常需要实例角色不具备的额外IAM权限。最终我们利用代理的自省API成功获取了包括容器实例ARN和代理版本在内的所有关键信息。4.4 步骤4:伪造并签署ACS WebSocket请求(伪装成代理)
https://ecs-a-1.region.amazonaws.com
这类形式)和步骤3获得的标识符,攻击者构建一个与真实ECS代理完全相同的WebSocket连接请求。最关键的是,该请求必须使用窃取的实例配置文件凭证进行SigV4签名,这样AWS才会将其认证为来自合法容器实例的请求(真实代理进行API调用时也使用相同的签名流程)。wss://ecs-a-1.<region>.amazonaws.com/ws?
agentHash=<agent-hash>&
agentVersion=<agent-version>&
clusterArn=arn:aws:ecs:<region>:<account-id>:cluster/<cluster-name>&
containerInstanceArn=arn:aws:ecs:<region>:<account-id>:container-instance/<instance-uuid>&
dockerVersion=<docker-version>&
protocolVersion=<protocol-version>&
seqNum=1&
sendCredentials=trueecs:Poll
操作(通常还包括我们使用的ecs:DiscoverPollEndpoint
)。默认ECS实例角色策略确实包含ecs:Poll
权限,因此没有问题。如果ecs:Poll
未被允许,控制平面会拒绝连接。移除ecs:Poll
也会破坏真实代理的认证流程,因此该操作不可行。sendCredentials=true
。这是关键标志,用于告知ACS后端:"该代理需要接收此实例上所有任务的IAM凭证 payload"(正常代理始终设置此参数,因为它需要这些凭证)。4.5 步骤5:从ACS通道收割所有任务角色凭证
ecs-tasks.amazonaws.com
主体)会为每个任务角色(以及任务执行角色(如果配置了的话))执行STS:AssumeRole
操作。ECS代理从不直接调用STS服务。控制平面会代您承担角色,获取临时凭证,然后通过ACS通道将这些凭证下发给代理。代理将其缓存在内存中,当容器请求凭证时提供给容器(执行角色凭证的传递方式类似,但由代理内部用于拉取镜像、写入日志等操作,不会通过元数据端点暴露)。sendCredentials=true
参数,且认证为正确的容器实例,ECS控制平面会推送该实例上所有配置了IAM角色的运行中任务的IamRoleCredentials
消息。每条凭证消息包含:任务ARN(用于标识所属任务)、IAM角色ARN、凭证ID(用于元数据URI)、AccessKeyId
、SecretAccessKey
、SessionToken
、过期时间以及角色类型标记(标识是任务的应用角色还是执行角色)。例如,如果该主机上有五个配置了IAM角色的任务,连接建立后我们将立即收到五组独立凭证。其中一组属于我们已攻陷的当前任务(已持有无需获取),但其余凭证属于其他任务——这代表着直接的横向提权机会。ecs:DiscoverPollEndpoint
和构成WebSocket基础的ecs:Poll
长轮询连接)会在CloudTrail中显示为容器实例IAM角色的操作
这是少数可能的检测点之一:如果任务A的角色突然执行了非常规操作(尤其是在预期上下文或时间窗口之外),就会触发告警。
关键点:仅通过ACS接收凭证载荷的行为不会产生任何CloudTrail事件——这是AWS到代理的内部推送。五、影响:为何ECScape漏洞危害如此严重
这些信息能帮助攻击者绘制主机运行图谱,识别高价值目标。ecs:Poll
及相关API调用是ECS代理的常规操作(尽管来自同一实例的额外连接可能异常,但本身不会产生明显噪音)。task roles
在执行操作。CloudTrail日志仅会记录该角色(及任务ARN会话上下文)的行为,而不会显示明显的"第三方"迹象。除非与任务预期行为进行关联分析,否则无法直接判断凭证是否被盗。如果攻击者足够谨慎——例如仅执行符合该角色常规活动的操作(读取该角色通常访问的数据,或在非异常时段执行动作)——可能不会立即触发告警。Task B
的角色在任务B未运行或空闲时执行了某些管理操作——这提示任务B的凭证遭到了滥用。这有助于事件响应(尽管属于事后追溯)。s3-control-task
:该任务具有S3完全访问权限的任务角色,但没有任务执行角色。database-task
:该任务不具备任务角色,但其任务执行角色具有获取名为db-secret
的密钥的权限,该密钥会作为环境变量注入容器。ecscape-task
:攻击者控制的任务。其任务角色附加了Deny *
策略(理论上无法访问任何AWS API),且不具备任务执行角色。ecscape-task
如何:s3-control-task
的任务角色凭证,并利用其删除S3存储桶——这是该角色原本无法执行的操作。database-task
的任务执行角色凭证,直接打印db-secret
的明文内容。六、ECS 缓解措施与最佳实践
ECS_AWSVPC_BLOCK_IMDS
设置限制特定任务
这是最有效的防护手段:若容器无法访问IMDS,则无法窃取伪装ECS代理所需的实例凭证ecs:Poll
或ecs:DiscoverPollEndpoint
权限ecs:*
权限),此类配置可能使攻击者无需实例凭证即可自主发起攻击。七、负责任披露与AWS官方回应
引用链接
[1]
Black Hat USA 2025议题简介:https://www.blackhat.com/us-25/briefings/schedule/#ecs-cape--hijacking-iam-privileges-in-amazon-ecs-45686[2]
Black Hat USA 2025演讲PPT:https://i.blackhat.com/BH-USA-25/Presentations/US-25-Haziz-ECS-cape-Hijacking-IAM-Privileges-in-Amazon-ECS-Wednesday.pdf[3]
PoC源码:https://github.com/naorhaziz/ecscape[4]
Naor Haziz:https://www.sweet.security/author/naor-haziz-2[5]
《ECScape: Understanding IAM Privilege Boundaries in Amazon ECS》:https://www.sweet.security/blog/ecscape-understanding-iam-privilege-boundaries-in-amazon-ecs[6]
**第一部分 - Amazon ECS on EC2深度解析**:https://naorhaziz.com/posts/under-the-hood-of-amazon-ecs/[7]
责任共担模型:https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-shared-model.html#security-shared-model-ec2[8]
ECS安全最佳实践博客:https://aws.amazon.com/blogs/security/security-considerations-for-running-containers-on-amazon-ecs/[9]
博客文章:https://aws.amazon.com/blogs/security/security-considerations-for-running-containers-on-amazon-ecs/