2024 年 2 月,我们在六项 AWS 服务中发现了严重漏洞。这些漏洞的影响范围包括远程代码执行 (RCE) 、全服务用户接管(可能 提供 强大的管理访问权限)、操纵 AI 模块、暴露敏感数据、数据泄露和拒绝服务。
受影响的服务包括:
CloudFormation Glue EMR SageMaker ServiceCatalog CodeStar
这些漏洞可能会影响世界上任何使用过这些服务的组织。在本篇博文中,我们将详细解释可能导致资源占用的“影子资源”攻击媒介,以及可大幅提高攻击者成功率的“桶垄断”技术。
我们向 AWS 报告了这些漏洞,他们迅速作出响应并修复了这些漏洞。关于攻击者之前是否曾使用过此媒介来利用这些漏洞,AWS 表示他们“正在确认各团队的调查结果,如果客户受到任何报告的问题的影响,他们将直接联系客户”。
虽然 AWS 已缓解上述服务中的漏洞,但此类攻击可能仍然存在于某些场景中,或存在于其他服务、产品或开源项目中。建议AWS用户遵循我们的缓解措施部分,了解针对此类场景的最佳实践措施。
我们感谢 AWS 安全团队在此事上的合作。
时间线:
-
2024 年 2 月 16 日:我们向 AWS 安全团队报告了 CloudFormation、Glue、EMR、SageMaker 和 CodeStar 中的漏洞。
-
2024 年 2 月 16 日:AWS 承认并开始调查这些问题。
-
2024 年 2 月 18 日:我们报告了 ServiceCatalog 中的一个漏洞。
-
2024 年 3 月 16 日:AWS 确认他们已修复 CloudFormation 和 EMR 中的漏洞。
-
2024 年 3 月 25 日:AWS 确认他们已修复 Glue 和 SageMaker 中的漏洞。他们还提到,CodeStar 被认为已得到解决,因为新客户不再被允许创建项目,因为该服务计划于 2024 年 7 月弃用。
-
2024 年 4 月 30 日:我们报告称,CloudFormation 的当前修复使用户容易受到 DoS 攻击。
-
2024 年 5 月 7 日:AWS 表示他们正在努力修复 CloudFormation 问题。
-
2024 年 6 月 26 日:AWS 确认他们已修复 ServiceCatalog 和 CloudFormation 中的漏洞。
-
2024 年 8 月:该研究在 Black Hat USA 和 DEF CON 32 上进行了展示。
背景
我们在 AWS 上发现了一种新的攻击媒介,我们将其命名为“影子资源”。影子资源的一个例子是为支持各种服务而创建的 AWS S3 存储桶。在对这个媒介进行彻底调查时,特别是利用 S3 存储桶资源时,我们发现了一种我们称之为“Bucket Monopoly”的技术。这种技术可以显著提高利用影子 S3 存储桶资源的攻击的成功率。
在本篇博文中,我们将分享我们发现这些漏洞的历程。我们将解释缓解措施,提供有关如何检查您是否受到这些攻击媒介攻击的指导,并讨论 AWS 为解决这些漏洞而实施的修复措施。
发现
在使用 AWS CloudFormation 时,我们注意到,当您在新的区域中首次通过 AWS 管理控制台使用此服务创建新堆栈时,该服务会自动触发 AWS 创建一个 S3 存储桶来存储我们的 CloudFormation 模板。
最初,我们想知道有多少用户知道,当他们创建新服务(例如 CloudFormation)时,他们的帐户中会创建一个新的存储桶,专用于支持 CloudFormation。
我们还注意到有关为 CloudFormation 服务提供服务的 S3 存储桶的一个关键方面。除了区域名称之外,存储桶的名称在所有 AWS 区域中都是相同的(下一章将详细解释这一点)。
现在是时候提醒您有关 AWS S3 存储桶的一个小事实了。存储桶的名称在所有 AWS 账户中都是全局的并且是唯一的,因此如果您创建了一个名为的存储桶,那么cool-bucket-1 您将是世界上唯一拥有此存储桶的人,并且没有其他人能够创建以此名称命名的新存储桶。
这让我们怀疑:是否有人(可能是外部攻击者)以某种方式猜出 CloudFormation S3 存储桶的名称,并在受害者之前在不同区域创建一个新的存储桶?
出于这种担忧,我们深入研究并发现攻击者确实可以在未使用的 AWS 区域中设置存储桶,并等待受害者在新区域中使用 CloudFormation 服务,以秘密使用攻击者控制的 S3 存储桶作为 CloudFormation 服务的一部分。
我们已经清楚地表明,通过执行上述所有操作,攻击者可以使用植入其帐户的 S3 存储桶来执行代码、操纵或窃取数据,甚至在用户不知情的情况下完全控制受害者帐户。
在发现 AWS 架构中的这一重大漏洞后,我们将搜索范围扩大到其他 AWS 服务,并发现了更多漏洞。后来我们了解到,它们都共享一个共同的攻击媒介。
影子资源攻击向量
影子资源是指由 AWS 服务自动生成的资产,通常作为无服务器架构的一部分。这些资源通常在没有用户明确指示的情况下生成,可能包括各种 AWS 服务组件。至关重要的是,AWS 账户的所有者可能并不总是知道这些资源的存在。
S3 存储桶作为影子资源
S3 存储桶是一种用于管理文件、图像、视频和其他数据的在线存储容器,类似于基于云的硬盘。
一些 AWS 服务创建 S3 资源来存储必要的操作数据,但用户并不总是知道这些 S3 资源的存在。
例如,在我们的研究中,我们注意到CloudFormation(使用模板自动设置云资源的 AWS IaC 服务)会在没有我们明确指示的情况下自动生成 S3 存储桶(“影子存储桶”)。当我们在 AWS 管理控制台上使用 CloudFormation 上传模板文件时,就会发生这种情况,从而自动创建一个遵循特定命名约定的新存储桶。
上传模板文件时 CloudFormation 创建的存储桶
此存储桶由 CloudFormation 创建,具有特定的名称,由以下部分组成:
CloudFormation 创建的存储桶名称的结构
-
前缀:这是通过 AWS 管理控制台上传模板时为 CloudFormation 服务创建的 S3 存储桶的前缀 ( )。它在所有 AWS 账户中保持一致。"cf-templates"
-
哈希:这是一个包含字母数字字符()的随机 12 个字符哈希a-z, 0-9。
-
区域:这表示使用 CloudFormation 服务的区域名称
这是使用 AWS管理控制台时的默认行为,因为它会自动将您上传的 CloudFormation 模板保存在此 S3 存储桶中
CloudFormation 在 us-east-1 区域创建的存储桶示例
为同一帐户在不同区域创建模板将生成具有相同前缀和哈希值的 CloudFormation 存储桶名称。唯一的区别是区域部分,它将对应于使用 CloudFormation 的区域。
例如,如果某个账户在us-east-1区域使用 CloudFormation,则关联的存储桶名称为cf-templates-123abcdefghi-us-east-1。当同一账户在另一个区域(如 )使用 CloudFormation 时,eu-west-2AWS 将创建一个名为 的新存储桶cf-templates-123abcdefghi-eu-west-2。唯一的区别是区域名称。
如果用户在新区域使用 CloudFormation,则将使用相同的前缀和哈希值创建存储桶,但使用相关区域
总之,CloudFormation 存储桶名称由三个部分组成:常量服务名称前缀cf-templates-,一个随机的 12 个字符的字符串,有4,738,381,338,321,616,896 个可能选项,几乎不可能猜到,以及区域名称,这是公开信息(所有 33 个 AWS 区域都是已知的)。至于哈希值——攻击者能否获得此信息?我们将在本博客的后面部分探讨这个问题。
AWS CloudFormation 漏洞:“cf-templates-{Hash}-{Region}”
此时,我们有两个主要问题需要解决:
-
如果另一个用户已经创建了具有指定名称的存储桶,会有什么后果?
-
有人能猜出哈希值部分吗?我们应该把它当作秘密吗?
在回答这些问题之前,让我们简要描述一下用户使用 AWS 管理控制台创建新的 CloudFormation 堆栈时的工作流程。
CloudFormation 上的堆栈创建概述
C LoudFormation新堆栈工作流程
1.用户选择“上传模板文件”以启动 CloudFormation 堆栈的创建,从而调用API 请求。此过程使用CreateBucket API 请求CreateUploadBucket创建存储桶。
2.如果用户尚不存在 S3 存储桶,CloudFormation 将按照以下模式自动创建一个:cf-templates-{Hash}-{Region}。如果存储桶已存在,CloudFormation 将使用它。
-
每个帐户的哈希值都是唯一的,并且在不同地区保持不变
-
存储桶名称中的区域对应于启动 CloudFormation 服务的位置。
3.服务器返回 S3 存储桶名称。
4.用户调用PutObject API请求将模板文件存储在S3存储桶中。
5.验证等操作将在后台执行(例如,GetTemplateSummary和DescribeStacks)。
6.用户将完成堆栈的详细信息并发起CreateStackAPI 请求。
如果……CloudFormation 存储桶已被攻击者窃取怎么办?
为了探索 CloudFormation 中的漏洞,我们将使用两个 AWS 账户 - 一个作为受害者,另一个作为攻击者:
-
账户 A(受害者):通过在 AWS 管理控制台中通过 CloudFormation 部署新堆栈来模拟典型的用户行为。
-
账户 B(攻击者):尝试获取账户 A请求的资源,同时了解账户 A 的CloudFormation 哈希。
假设攻击者知道 AWS 上特定/目标账户的 CloudFormation 哈希部分。(如后所述,直接了解哈希至关重要。我们尚未找到从账户 ID 或任何其他账户元数据计算哈希的方法,但我们仍然发现用户公开此哈希的情况,例如在开源项目中等)。
正如我们在研究中所提到的,这个哈希值对于每个帐户来说都是唯一的,并且在所有地区都是相同的。
受害者在 中有一个堆栈us-east-1,因此攻击者可以在eu-west-2或受害者尚未使用的另一个区域中创建一个具有可预测名称的存储桶。当攻击者试图索取账户 A请求的资源时,它实际上执行了“资源抢注”,或者更具体地说,在本例中是“ S3 存储桶名称抢注”或“存储桶抢注”。这个想法在过去已经出现过,您可以阅读 Ian Mckay的一篇关于类似概念的精彩博客。
当受害者首次尝试部署新的 CloudFormation 堆栈时,将发生以下事件序列:eu-west-2
-
受害者发起操作:受害者在账户 A中操作,通过 AWS 管理控制台上传 CloudFormation 模板来启动该过程。此 CloudFormation 服务将检查是否cf-templates-{Hash}-{Region}存在具有该名称的 S3 存储桶。如果不存在,它将尝试创建一个。
-
攻击者已认领存储桶:受害者完全不知道攻击者在账户 B中创建了存储桶。由于 S3 存储桶名称在所有 AWS 账户中都是全局唯一的,因此预期的存储桶名称已被使用。
-
CloudFormation 错误:当账户 A 中的 CloudFormation 服务尝试创建 S3 存储桶并向其上传模板文件时,该服务遇到问题。尽管该服务识别出该存储桶存在,但该过程失败,CloudFormation 返回错误,通常是“ AccessDenied ”,表示该服务无法将模板文件上传到现有的 S3 存储桶。
当攻击者获取另一个 AWS 账户的 CloudFormation 服务的可预测存储桶名称时,受害者的 CloudFormation 服务将尝试访问和使用攻击者的存储桶
总之,通过了解其他 AWS 用户的 CloudFormation 模板的哈希值并在特定区域中声明他们的存储桶,攻击者可以阻止他们使用 CloudFormation 上的“上传模板文件”功能。
由于攻击者已经认领了 S3 存储桶,受害者无法使用 CloudFormation 服务
这可以视为拒绝服务 (DoS) 攻击。发生这种情况的原因是 S3 存储桶默认设置为block all public access,并且 S3 存储桶没有基于资源的策略,因此受害者角色无权对攻击者的存储桶执行操作。所以,我们想知道如果我们改变这一点会发生什么。让我们升级它!
如果……攻击者打开存储桶供公众访问并创建宽松的策略,该怎么办?
为了将攻击从 DoS 升级为更严重的影响,攻击者可以更改可预测的 S3 存储桶的配置,使其可公开访问。
这将允许受害者的 CloudFormation 服务访问它。
为了升级攻击,攻击者需要允许公众访问可预测的 S3 存储桶
但这还不够。要启用跨账户策略评估逻辑,攻击者需要在其S3 存储桶上创建一个基于资源的宽松策略。此策略应明确向另一个 IAM 主体(特别是易受攻击的 AWS 服务)授予权限。它应该允许诸如s3:Pu tObject、s3:GetObject、s3:ListBucket等操作。这样,受害者的易受攻击的服务将能够读取和写入攻击者控制的存储桶中的数据。
在以下示例中,我们编写了一个高度宽松的策略,允许受害者的服务访问攻击者的存储桶并对其采取任何操作。但是,该策略不需要如此宽松。请注意,如果您希望复制我们的步骤或在 PT 或 Red Team 评估中使用它,您应该定制策略,使其仅适合易受攻击的服务所需的操作。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::cf-templates-123abcdefghi-eu-west-2/*",
"arn:aws:s3:::cf-templates-123abcdefghi-eu-west-2"
]
}
]
}
在攻击者声明可预测存储桶、使其可公开访问并定义允许其他主体从中读取和写入数据的存储桶策略后,会发生一件有趣的事情。
账户 A中的 CloudFormation 服务尝试创建 S3 存储桶并将模板文件上传到其中,但由于该存储桶已经存在(在攻击者的账户中),因此它会信任它、访问它并将其模板文件放入其中。
这会导致 CloudFormation 上的信息泄露漏洞,因为攻击者现在可以读取受害者的 CloudFormation 服务写入恶意 S3 存储桶的文件。
鉴于 CloudFormation 模板可能包含敏感信息(例如环境变量、凭证等),如果用户不遵循最佳实践,此漏洞可能会对组织造成严重影响。攻击者可以利用他们部署的模板中暴露的信息。
如果……攻击者修改了模板文件怎么办?
为了将此漏洞提升到最高严重程度,我们将利用另一种名为CloudFormation Templates 中的资源注入的技术,该技术由 RhinoLab 发布(也归功于 Matt Fuller,@matthewdfuller)。
本质上,该技术利用了 CloudFormation 的检查时间到使用时间 (TOCTOU) 问题,使得攻击者有机会在执行 CloudFormation 模板之前对其进行修改。
这一次,该技术将会变得更加强大,因为许多原来的条件和先决条件对于我们的攻击媒介的成功来说不再是必要的。
为了强调此漏洞的严重性,我们遵循该技术的Pacu 模块的行为(Pacu 是一个开源 AWS 开发框架,旨在测试 AWS 环境的安全性)。
在我们深入了解攻击工作流程之前,攻击者需要完成以下步骤:
-
使用可预测的受害者名称声明存储桶。允许公共访问并为存储桶定义宽松的基于资源的策略,如前所示。
-
创建一个 Lambda 函数,该函数将资源或后门注入给定的模板文件。此 Lambda 函数必须设置为由攻击者存储桶上的PutBucketNotification事件触发。因此,每当将文件放入此存储桶时,Lambda 函数都会对其进行修改。
CloudFormation 漏洞概述
现在我们可以描述这次攻击以及如何在目标受害者的账户上获得管理员角色访问权限:
-
受害者通过 AWS 管理控制台使用 CloudFormation,然后单击“创建堆栈”。然后,用户选择“选择现有模板”,并使用Upload a template file 选项从其工作站中选择模板文件。
-
由于攻击者已经声明了受害者的 CloudFormation 服务使用的存储桶名称,因此用户的模板文件被写入攻击者的 S3 存储桶中。
-
Lambda 函数由 S3 触发PutBucketNotification,表明新文件被放入了攻击者的存储桶中。
-
Lambda 函数读取受害者的模板文件。
-
Lambda 函数修改了受害者的模板文件并注入了攻击者可以承担的新管理员角色。
-
Lambda 函数推送新的后门模板文件。
-
与此同时,用户尚未完成部署新的 CloudFormation 堆栈。他们仍然需要完成手动步骤,例如选择堆栈名称、批准功能等。用户完成这些步骤后,他们将单击“提交”以完成创建。这就是造成 TOCTOU 类(检查时间到使用时间)问题的原因,从而允许模板被篡改。
-
受害者的 CloudFormation 服务从攻击者的存储桶中获取恶意模板文件。
-
受害者的 CloudFormation 服务将部署被植入后门的模板文件,从而创建一个可供攻击者担任的新管理员角色。攻击者只需在其日志中搜索受害者的账户 ID,然后担任注入的管理员角色即可。
以下是演示该漏洞的概念验证(PoC)视频:
本质上,我们只需知道 CloudFormation 的唯一哈希值,就可以在目标组织中创建管理员角色(取决于调用 CloudFormation 的用户的权限)。在这种情况下,如果我们以某种方式找到该哈希值,并且 CloudFormation 的发起者拥有足够的权限,这将导致我们在云中可以实现的最严重后果,因为它允许我们接管受害者的帐户。
一些免责声明:
-
如上所述,要在受害者账户中创建管理员角色(后门),启动CloudFormation 服务的任何一方都需要具有管理 IAM 角色的权限。这取决于启动堆栈的用户拥有哪些权限,或在堆栈创建期间定义的 IAM 服务角色。请注意,即使这些权限仅限于特定资源,攻击者仍然可以根据受害者账户上的用户/角色的权限修改资源。例如,根据用例,修改 Lambda 函数、更改 EC2 实例、将容器映像更改为恶意映像或更改新部署的 S3 存储桶的策略。请务必记住,可以使用 AWS 管理控制台和部署堆栈的用户通常具有高级权限。
-
攻击者需要等待受害者在新的区域中首次部署新的 CloudFormation 堆栈才能成功发起攻击。虽然这个过程可能需要一些时间,但您需要考虑到在拥有数百个账户和数千个用户的大型组织中,发生这种情况的概率很高。
综上所述,我们发现了一种将资源甚至管理员角色注入另一个 AWS 账户的方法!但让我们讨论一下房间里的大象,攻击者仍然需要发现与受害者帐户关联的 CloudFormation S3 存储桶名称中的唯一哈希值,现在让我们来讨论一下这个问题。
CloudFormation S3 存储桶哈希
如上所述,CloudFormation 服务通过 AWS 控制台使用的 S3 存储桶名称包含以下格式:cf-templates-{Hash}-{Region}。此哈希对于每个帐户都是唯一的,并且在不同区域保持一致。它由 12 个字符(az,0-9)的字母数字序列组成,从而产生 4,738,381,338,321,616,896 种可能的组合,因此不可能简单地猜测或暴力破解。
在我们的研究中,我们尝试找到预测或计算此哈希值的方法,可能基于另一个唯一标识符,以便我们可以为每个帐户推断出它。我们的研究结果表明,此哈希值对于所有地区的每个帐户都是相同的,这表明它可能基于帐户 ID 或类似的唯一标识符。
然而,我们还没有找到一种直接从账户 ID 或任何其他与账户相关的元数据计算哈希值的方法。它似乎是一个随机值,从安全性方面来看是好的。
尽管如此,我们仅通过利用 GitHub 正则表达式搜索/Sourcegraph、抓取开放问题等,就识别出了不同 AWS 账户使用的大量哈希值。
本质上,这个向量对于共享或暴露该哈希的组织来说仍然非常危险。
探索更多漏洞
在调查 GitHub 上暴露的 CloudFormation 哈希时,我们发现了各种 S3 存储桶模式。这表明这些攻击媒介比我们最初想象的更为广泛,并且可能会对在其操作中创建和使用影子资源的其他服务造成更大的损害。
简单来说,一些 AWS 服务使用可预测的名称创建 S3 存储桶。它们通常使用AWS 账户 ID作为这些存储桶的唯一标识符,而不是使用哈希。例如,其中一个 AWS 服务使用的存储桶名称可能遵循以下模式:{Service Prefix}-{AWS Account ID}-{Region}。
为了寻找可能创建影子资源的易受攻击的服务,我们使用了以下方法:
-
AWS 文档审查:我们搜索了 AWS 文档,以查找详细介绍各种服务创建的 S3 存储桶模式的潜在文档。
-
爬取 AWS 服务:我们爬取了 AWS 服务,监控其运行期间 S3 存储桶或其他资源的创建情况。
-
自动执行 AWS 服务上的爬取:我们开发了一款名为 TrailShark 的开源工具,它可以提醒我们在我们的 AWS 账户中创建新的 S3 存储桶或由 API 调用生成的任何其他资源。此工具将 AWS CloudTrail 日志直接集成到 Wireshark 中,从而实现对 AWS API 调用的近乎实时的分析。在我们的用例中,它有助于识别在我们的爬取过程中创建的新资源。有关该工具的更多信息,请参阅此博客。
-
GitHub 正则表达式搜索:我们利用 GitHub 的正则表达式搜索功能并编写正则表达式模式来查找包含前缀、某些标识符和区域的 S3 存储桶名称。例如,我们搜索了包含标识符和区域/s3.amazonaws.com/[a-zA-Z0-9-]*-.*-(west|east)-(1|2)/的模式或变体。arn:aws:s3
我们发现 AWS 服务使用的几个潜在的 S3 bucket 是可预测的
我们发现的一个 S3 存储桶名称示例,怀疑其易受此攻击媒介攻击
经过验证和利用后,我们发现了几个存在漏洞的 AWS 服务。
我们审查了几十个AWS服务,总共发现了6个存在漏洞的AWS服务,下面我们描述了这些漏洞以及我们的研究过程:
AWS Glue 漏洞:“aws-glue-assets-{Account-ID}-{Region}”
AWS Glue 是一种由数据工程师和分析师使用的服务,可自动执行提取、转换和加载 (ETL) 过程,从而简化分析和机器学习的数据准备。
在我们的研究中,我们发现当用户使用带有 Visual ETL 工具的 AWS 管理控制台创建作业时,S3 存储桶用于存储 Glue 作业,这些作业主要是 Glue 执行的 Python 脚本。
Glue 服务根据以下模式自动为用户创建此 S3 存储桶:aws-glue-assets-{Account-ID}-{Region}。
Glue 服务创建的 S3 存储桶
由于此存储桶具有固定前缀,后跟账户 ID 和 Glue 服务的区域,因此其名称是可预测的。知道您的 AWS 账户 ID 的攻击者可能会在任何区域创建此存储桶(如果该存储桶尚不存在),然后等待受害者通过 AWS 管理控制台在新区域中首次使用 Glue ETL。这将导致受害者的 Glue 服务将文件写入攻击者控制的存储桶。
攻击场景和总体概念与CloudFormation漏洞类似。
我们将来检查几乎任何漏洞时都需要执行以下预先步骤:
-
攻击者需要获取受害者可预测的 S3 存储桶,以供存在漏洞的服务使用。
-
定义一个宽松的资源并允许公众访问存储桶。
-
定义一个将由触发PutBucketNotification并执行恶意操作的 Lambda 函数。
Glue 漏洞概述
在这种情况下,Lambda 函数会将代码注入到放入存储桶的任何文件中。事实上,此漏洞允许攻击者将任何代码注入受害者的 Glue 作业,从而导致远程代码执行 ( RCE )。在某些情况下,还可能在受害者的账户中创建其他资源或可由攻击者承担的管理员角色,具体取决于受害者授予 Glue 作业的角色。
大多数情况下,将使用 默认的 AWS Glue 服务角色。当用户选择标准 AWS Glue 服务角色(这是默认选项)时,将创建此角色。然后,AWS Glue 在他们的 AWS 账户中创建一个名为AWSGlueServiceRole的新 IAM 角色。此角色将具有允许创建、修改和删除 AWS Glue 作业的策略。此外,此角色可能被用于恶意目的,例如收集有关 IAM 角色的信息、可能提升权限以及访问和操纵 S3 存储桶和对象。
请注意,用户可以选择其他角色,在这种情况下,如果角色授予其 Glue 作业过多的权限,则可能导致攻击者完全攻陷帐户。因此,坚持最小特权原则并仅授予服务、作业和其他资源所需的权限至关重要。
我们注意到的另一个有趣的行为是,即使攻击者修改了 Glue 脚本的内容,现在该脚本是恶意的,当受害者尝试在 AWS 管理控制台中查看它时,显示的仍然是旧内容,而不是修改后的内容。这意味着在 GUI 中,恶意脚本对用户是隐藏的,即使受害者的 Glue 服务将运行修改后的/恶意的脚本。这是由于缓存机制而发生的。但是,如果受害者尝试编辑脚本,他们将接触到后门版本。
以下是演示该漏洞的概念验证(PoC)视频:
AWS EMR 漏洞:“aws-emr-studio-{Account-ID}-{Region}”
AWS EMR(Elastic MapReduce)是数据从业者和开发人员使用的一项服务,它使用流行的大数据框架(如 Apache Hadoop、Apache Spark、Apache Hive 等)处理和分析大型数据集,实现可扩展且经济高效的数据处理和分析。
我们在研究中发现,当用户使用 EMR 服务和“EMR Studio”创建工作室时,EMR 服务会自动生成一个 S3 存储桶。此 S3 存储桶遵循以下命名模式:aws-emr-studio-{Account-ID}-{Region}
EMR 服务创建的 S3 存储桶
由于我们已经知道这个存储桶名称是可预测的,并且包含一个常量前缀,后跟账户 ID 和 EMR 服务的区域,因此攻击者可以使用其 AWS 账户 ID 来攻击组织。他们可以使用这个可预测的名称创建一个无人认领的存储桶,然后等待受害者在新区域部署新的 EMR Studio。
EMR 漏洞概述
以下是 可能的攻击场景:
一旦受害者的 EMR 服务将文件写入攻击者的存储桶,攻击者就可以通过注入恶意代码来利用这一点。在这种情况下,Lambda 函数将恶意代码注入受害者的 EMR 服务写入攻击者存储桶的 Jupyter 笔记本 (.ipynb) 文件中。当用户在 EMR Studio 中打开笔记本时,这可能会导致跨站点脚本 (XSS) 攻击。
例如,攻击者可以将用户重定向到伪造的 AWS 登录页面以窃取其凭据。更糟糕的是,如果分配给服务的角色具有更高的权限,攻击者可以创建资源或危及整个帐户。
值得一提的是,当用户尝试在 EMR 中创建一个新的工作室时,AWS 默认建议创建一个AmazonEMRStudio_ServiceRole_{ID}以该服务相关权限命名的服务角色——“我们使用名称...为您创建一个服务角色”。
此角色包括针对Put和对象执行诸如 之类的操作。Getaws-emr-studio-{Account-ID}-{Region}
但是,AWS 在策略中强制执行一个条件,以检查aws:ResourceAccountEMR 使用的 S3 存储桶。这确保了 S3 存储桶属于受害者的帐户。在我们的案例中,由于 EMR 将尝试与之交互的 S3 存储桶与其他帐户(攻击者)相关联,这将触发错误消息并阻止创建 EMR 工作室。
此时,用户有两种选择可以成功创建工作室:
-
选择现有角色:通常,用户可能会选择现有角色。通常,所选角色可能具有不受限制的s3:*权限aws:ResourceAccount。虽然这允许部署 EMR 工作室,但它也可能授予可能被攻击者利用的过于宽松的权限。
-
遵循 AWS 建议的权限:用户可以遵循 EMR 服务建议的权限详细信息并创建类似的角色。这次,EMR 工作室的创建将会成功,因为 AWS 管理控制台的权限详细信息不AmazonEMRStudio_ServiceRole_{ID}包含aws:ResourceAccount条件。仅当 AWS 为用户创建角色时才会添加此条件。
与 AWS 建议的策略相比,AWS 创建的角色的 IAM 策略更加严格
以下是演示该漏洞的概念验证(PoC)视频:
AWS SageMaker 漏洞:“sagemaker-{Region}-{Account-ID}”
AWS SageMaker 是一种大规模构建、训练和部署机器学习模型的服务,为整个工作流程提供全面的工具。
作为该生态系统的一部分,Amazon SageMaker Canvas 是一个无代码的可视化平台,可让非开发人员和业务分析师轻松开发、训练和部署模型。
在我们的研究中,我们发现当用户创建 SageMaker Canvas 时,SageMaker 服务会自动创建一个 S3 存储桶来存储服务使用的文件。此 S3 存储桶的命名模式如下:sagemaker-{Region}-{Account-ID}。
SageMaker Canvas 创建的 S3 存储桶
世上并没有什么新鲜事——这个存储桶是可预测的,攻击者可以在用户首次使用服务之前认领它。在这种情况下,攻击者只需要 AWS 账户 ID 和选定的区域。然后,他们可以将存储桶配置为公开访问,并建立一个宽松的存储桶策略,授予受害者对外部 S3 存储桶的完全访问权限。
SageMaker 漏洞概述
以下是 SageMaker 可能遭遇的攻击场景:
在这种攻击场景中,威胁更多地与信息泄露和数据操纵有关。每次 SageMaker Canvas 用户尝试创建数据集或将数据导入服务时,这些数据都会被写入攻击者的 S3 存储桶(位于 下Canvas/default-{Time}/*)。之后,这些数据将被 SageMaker Canvas 服务为用户使用,从而导致重大风险,例如:
-
数据泄露:敏感的训练数据可能会暴露给攻击者。
-
数据操纵:攻击者可以修改数据集,导致模型不准确或其他恶意后果。
以下是演示该漏洞的概念验证(PoC)视频:
AWS CodeStar 漏洞:“aws-codestar-{Region}-{Account-ID}”
AWS CodeStar 是一种通过集成用于编码、构建和部署应用程序的 AWS 开发工具来简化项目管理的服务。
以下是 CodeStar 可能遭受的攻击场景:
与上一种情况类似,如果存储桶名称被攻击者夺取,合法用户将无法使用该服务,并且在尝试创建 CodeStar 项目时 会收到“项目创建失败”消息。
受害者端将显示一条错误消息,因为攻击者已经认领了 CodeStar 将尝试使用的存储桶
发生这种情况的原因是,攻击者的账户下已经存在该服务所需的存储桶。本质上,这会产生拒绝服务 (DoS) 场景,攻击者会阻止用户使用特定的 AWS 服务。
以下是演示该漏洞的概念验证(PoC)视频:
AWS 服务目录漏洞:“cf-templates-{Hash}-{Region}”
在 AWS 中,服务目录是一种旨在帮助组织创建和管理在 AWS 上使用的已批准资源目录的工具。服务目录有助于确保标准化、符合组织政策,并使用户能够快速部署仅批准的服务。
通常,AWS 中的特权用户将在 AWS Service Catalog 中创建产品组合来组织产品并将其分发给最终用户。AWS Service Catalog 中的产品是一组 AWS 资源,其中可以包括 EC2 实例、存储卷、数据库等。然后,这些资源可在 AWS 中部署给其他用户。
有多种方法可以将产品添加到 Service Catalog,其中一种方法是使用 AWS CloudFormation。如果选择此方法,用户可以选择上传 CloudFormation 模板。上传 CloudFormation 模板后,AWS Service Catalog 会创建一个 S3 存储桶来存储该模板。
在我们的研究中,我们发现存储 CloudFormation 模板的 S3 存储桶按照以下模式命名:cf-templates-{HASH}-{Account-ID}。拥有组织 CloudFormation 哈希(且在各个区域保持一致)的攻击者可以预测此模式。这揭示了我们在初始 CloudFormation 分析中发现的相同漏洞(第一个漏洞)。
服务目录创建的 S3 存储桶
该漏洞可能允许攻击者将远程资源注入到 Service Catalog 产品的 CloudFormation 模板文件中,从而部署恶意资源,或者在某些情况下添加攻击者可以冒充的管理员用户。
Service Catalog 漏洞概述
以下是Service Catalog可能遭受的攻击场景 :
关于此漏洞影响的重要免责声明。模板部署过程所具有的权限可能有所不同,因此注入恶意角色将在很大程度上取决于启动产品的用户。
然而,利用此漏洞,攻击者可以修改合法用户部署的现有资源并在其中植入后门。
此外,一些产品创建者(通常是特权用户)选择使用启动约束,允许他们指定 AWS Service Catalog 在部署产品时将承担的 IAM 角色,而不管启动产品的用户的权限如何。
这对于使具有有限权限的用户能够安全地部署资源特别有用。在这种情况下,攻击者可以利用这一点,因为即使用户的权限较低,产品的部署过程也可能具有管理员授予的更高权限。
以下是演示该漏洞的概念验证(PoC)视频:
开源中的影子资源攻击向量
在我们的研究中,我们发现这种攻击媒介不仅影响 AWS 服务,还影响组织用于在其 AWS 环境中部署资源的许多开源项目。许多开源项目都会自动创建 S3 存储桶作为其功能的一部分,或者指示其用户部署 S3 存储桶。例如,它们可能会提供类似这样的命令sam deploy --s3-bucket PREFIX-$AWS_ACCOUNT_ID-$AWS_REGION…。这些存储桶通常使用常量前缀和用户的帐户 ID 来创建唯一的存储桶名称,有时还包括将部署服务或逻辑的区域。正如我们所见,这非常危险。具有您组织的帐户 ID 或其他唯一标识符的攻击者可以在受害者之前创建存储桶。
#!/bin/bash
s3_bucket="s3-prefix-${ACCOUNT_ID}-${REGION}"
HEAD_BUCKET=$(aws s3api head-bucket --bucket ${s3_bucket} 2>&1 || true)
if [ -z "$HEAD_BUCKET" ]; then
echo "Already exists"
else
aws s3api create-bucket --bucket ${s3_bucket} --region "${REGION}" --create-bucket-configuration LocationConstraint="${REGION}"
echo "New bucket: ${s3_bucket}"
fi
在创建存储桶之前检查存储桶是否存在的 Bash 脚本示例。此代码片段存在问题,因为即使 S3 存储桶存在,运行也不会失败
后果取决于开源项目的逻辑。在某些项目中,如果存储桶已经存在并允许您选择另一个存储桶名称,则该过程将失败。在其他情况下,该过程将完全失败。然而,有些情况下,攻击者会将其数据写入攻击者声明的存储桶,从而让攻击者完全访问文件。这允许攻击者修改文件并在您的帐户中执行恶意操作,甚至可能接管它,这取决于部署者的权限或稍后将使用被操纵文件的服务/逻辑。
#!/bin/bash
if ! aws s3 ls "s3://$1" > /dev/null 2>&1; then
echo "Creating bucket: $1"
if ! aws s3 mb "s3://$1" ; then
echo "Could not create bucket $1"
exit 1
fi
fi
尝试检查存储桶是否存在的脚本示例。但是,此脚本仍然容易受到攻击,因为在受害者之前认领存储桶并设置宽松策略的攻击者可能会导致第一个条件 ( ! aws s3 ls…) 被绕过,从而导致其他检查被跳过
另一个有趣的点是,了解开源和其他 AWS 服务的可预测 S3 存储桶名称以前可能导致“拒绝钱包”攻击,正如几个月前所展示的那样。此后,AWS 缓解了这种攻击媒介。
受影子资源影响的过去服务
我们观察到过去易受此攻击媒介攻击的服务,但现在它们已得到修复。例如,如果尚未指定任何内容,Athena 服务以前会为查询结果创建一个默认的 S3 存储桶。默认存储桶遵循格式,这是可预测的,攻击者可能会认领。现在,Athena 要求用户为查询结果指定一个 S3 存储桶,因此 AWS Athena 不再容易受到此攻击媒介的攻击。aws-athena-query-results-MyAcctID-MyRegion
AWS 文档指出,AWS 不再为用户创建格式为 aws-athena-query-results-MyAcctID-MyRegion 的默认位置
AWS 账户 ID 是秘密
AWS 账户 ID 是否应被视为秘密的问题长期以来一直是安全研究人员和 AWS 用户争论的焦点。意见不一 -一些人认为AWS 账户 ID 不是秘密,而另一些人则认为它应该保密(您可以阅读 Daniel Grzelak 的精彩博客文章,了解原因)。
总体而言,多年来的趋势一直是建议组织尽可能保密其 AWS 账户 ID。尽管普遍的假设是仅知道账户 ID 不足以破解账户,但攻击者仍可能使用它来收集有关您的 AWS 账户的信息等等。
AWS 还在其文档中提到,“虽然账户 ID 与任何识别信息一样,应该谨慎使用和共享,但它们并不被视为秘密、敏感或机密信息”。
然而,根据我们的研究,我们坚信账户 ID 应该被视为秘密,因为可能存在其他类型的类似漏洞,只需知道账户 ID 即可进行。
桶大富翁
在之前的漏洞中,我们针对的是其他账户的特定区域。但是,我们不会只关注一个区域,而是可以声明用户尚未声明的所有可能区域。在下一节中,我们将描述一种称为“存储桶垄断”的技术。虽然这种方法与本研究中发现的易受攻击的服务不再相关,因为问题已经得到修复,但它对于开源项目和未发现的易受攻击的组件尤其重要。此策略增加了毫无戒心的受害者与攻击者拥有的 S3 存储桶交互的可能性,如果易受攻击的组件具有可预测的 S3 存储桶名称,则可能导致完全的帐户入侵或其他恶意操作。
攻击者无需瞄准单个区域,而是可以针对易受攻击的组件的特定 S3 存储桶模式声明所有未声明的区域
由于 S3 存储桶名称是全局唯一的,我们可以检查哪些存储桶存在且已被受害者的帐户认领,因为我们知道其易受攻击的组件将在每个区域使用的确切存储桶名称模式。通过创建 GET 请求Prefix-{Hash}-{Region}.s3.amazonaws.com(或其他模式),我们可以确定存储桶是否存在或是否空闲,并显示一条NoSuchBucket消息。
通过这样做,我们可以识别受害者尚未用于组件服务或开源项目的所有区域。然后,我们可以在所有这些未认领的区域中设置存储桶和 Lambda 函数(可选),并等待受害者使用它们。AWS 目前有33 个区域,因此即使受害者已经在所有可用区域中创建了可预测的存储桶名称,攻击者也可以等待新区域发布并立即认领可预测的存储桶名称。
当用户在新区域首次使用存在漏洞的组件时,该组件将与攻击者控制的 S3 存储桶进行交互
水桶垄断步骤:
-
步骤 1 – 识别存储桶命名约定:为了查找影子资源,我们通常依赖于识别可预测的存储桶命名约定。我们通过查找包含前缀或后缀以及标识符(如帐户 ID 或哈希)以及可选区域(在模式中包含区域会增加在多个区域部署相同服务的可能性)的存储桶名称来开始侦察。可以使用 GitHub Regex Search 识别常见模式、使用 TrailShark 等工具抓取 AWS 服务或查看 AWS 文档来实现此侦察。
-
步骤 2 - 发现存储桶命名约定的唯一标识符:可预测的存储桶名称通常包含唯一标识符,以区分部署存储桶的不同帐户。在大多数情况下,此标识符是受害者的公共帐户 ID。但是,有时它是一个唯一的哈希值(CloudFormation、Service Catalog)。如果是这种情况,攻击者将尝试确定此哈希值是否被意外泄露。公共帐户 ID 被广泛暴露,攻击者有很多方法可以获取它们。以下是几个示例:
-
使用 GitHub Search/Sourcegraph :攻击者可以通过查询类似这样的模式找到许多暴露的帐户 ID /arn:aws:iam::[0-9]{12}/,它将返回部分后的公共帐户 ID ,目前GitHub 上arn:aws:iam::有157k 个结果。
-
收集 S3 存储桶名称:攻击者可以从 GitHub 或GrayhatWarfare等平台收集 S3 存储桶名称,这些平台收集暴露的存储桶和其他资源,然后使用这些名称从存储桶名称中找到 AWS 账户 ID,使用此方法,Jarom Brown 能够收集近197k 个唯一账户 ID。
-
从 AWS 访问密钥 ID 恢复帐户 ID :可以从 AWS 访问密钥 ID 派生帐户 ID。您可以阅读Tal Be'ery 撰写的有关此主题的精彩博客,该博客基于Aidan Steele的研究。
更有价值的资源是已知 AWS 账户列表,其中包括来自众多大型组织和供应商的账户 ID。另一个已知有效账户 ID列表包含超过 38,000 个有效账户 ID。
在我们的研究过程中,我们根据此列表确定了几个使用 AWS Glue 服务 aws-glue-assets-{Account-ID}-{Region} 的可预测 AWS s3 存储桶的组织。我们观察到一些组织在至少两个区域部署了 AWS Glue S3 存储桶的情况,其他组织则扩展到三个或四个区域。这种模式表明,组织可能会将之前易受攻击的服务扩展到其他区域,攻击者可以在这些区域控制之前易受攻击的服务所使用的存储桶。
-
步骤 3 – 在所有区域创建未认领的存储桶:攻击者利用他们对命名约定和账户 ID 的理解,在所有 AWS 区域中策略性地创建具有可预测名称的 S3 存储桶,而这些存储桶尚不存在。然后,攻击者打开存储桶以供公共访问并定义宽松的策略。具体来说,如果攻击者知道受害者的账户 ID,他们可以通过设置将存储桶配置为仅允许从受害者的账户访问"Principal": {"AWS": "arn:aws:iam::{Victim-Account-ID}:root"}。
通过这样做,他们可以拦截受害者与这些 S3 存储桶的未来交互。本质上,攻击者垄断了各个 AWS 区域中与易受攻击的服务相关的所有存储桶,等待受害者启动和使用易受攻击的服务。
AWS 如何解决这些漏洞
在我们于 2024 年 2 月报告之后,AWS 开始解决我们发现的漏洞(您可以在本博客开头查看完整的时间线),使 CloudFormation、Glue、EMR、SageMaker 和 Service Catalog 中不再存在这种攻击媒介。虽然这些服务的修复细节各不相同,但总体方法是一致的:如果存储桶已经存在,AWS 将添加序列/随机数或提示用户选择新的存储桶名称,从而忽略攻击者认领的存储桶。
对于 CodeStar,该问题被认为已得到解决,因为新客户不再被允许创建项目,因为该服务计划于 2024 年 7 月弃用。
我们还观察到 AWS 通知用户将为服务操作创建的资源的情况。这是一种很好的通知用户的方式,帮助他们了解某些服务在操作过程中会创建 S3 存储桶,并且这些存储桶应该得到安全处理。
CloudFormation Application Composer 通知用户将要创建的 S3 存储桶
关于攻击者是否曾经使用过这种攻击方式,AWS 表示他们“正在确认各个团队的调查结果,如果客户受到任何报告的问题的影响,我们将直接与客户联系”。
摘要、缓解措施和建议
在这篇博客中,我们报告了 AWS 服务中的大约 6 个漏洞,这些漏洞可能使攻击者能够利用使用 AWS 的组织,而最严重的影响可能是完全接管 AWS 账户。
我们解释了这些漏洞是如何发生的,我们将一种新的攻击媒介命名为“影子资源”。我们还描述了一种可用于最大化此攻击媒介影响的技术。
虽然上述服务中的漏洞已被 AWS 缓解,但此攻击媒介仍然适用于其他 AWS 服务和开源项目。
因此,实施某些缓解措施和措施至关重要:
-
'aws:ResourceAccount' 条件:为了防止用户或服务角色访问您不信任的存储桶,您可以为服务使用或承担的角色定义范围策略,并在 JSON 策略中包含条件元素。通过使用aws:ResourceAccount条件,您可以检查存储桶的资源所有者的 AWS 账户 ID。例如,EMR Studio 为用户创建的默认服务角色被称为并包含服务运行所需的权限。在此角色中,AWS 强制执行策略中的条件,以检查 EMR 使用的 S3 存储桶的 AWS 账户 ID 是否由用户自己拥有。这有效地防止用户访问和写入数据到攻击者拥有的 S3 存储桶中。以下是此实现的一个示例:AmazonEMRStudio_ServiceRole_{ID}aws:ResourceAccount
{
"Sid": "ObjectActions",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::aws-emr-studio-<AWS_ACCOUNT_ID>-us-east-1/*"
],
"Condition": {
"StringEquals": {
"aws:ResourceAccount": "AWS_ACCOUNT_ID"
}
}
}
使用 AWS 条件检查资源所有者的策略示例
值得一提的是,某些 AWS 服务需要访问托管在另一个 AWS 账户中的资源。使用aws:ResourceAccount基于身份的策略可能会影响您的身份访问这些资源的能力,因此需要检查和验证这一点。
验证预期的存储桶所有者:我们建议使用博客中提到的名称模式验证 S3 存储桶的所有者,以确保您的服务使用的 S3 存储桶确实在您的帐户下。可以使用以下命令完成此操作:
aws s3api list-objects-v2 --bucket <BUCKET_NAME> --expected-bucket-owner <OWNER_ACCOUNT_ID> <AWS_ACCOUNT_ID>
例如:您可以对类似这样的可预测模式执行扩展搜索aws-glue-assets-{Account-ID}-{Region}。在这种情况下,您需要使用您的 AWS 账户 ID 检查每个 AWS 区域的胶水存储桶所有者。如果您收到“拒绝访问”消息,则表明存储桶不在您的帐户下,您应该验证存储桶的所有者以及您是否信任此帐户。–expected-bucket-owner 检查对于在其操作中创建 S3 存储桶的开源项目也很有用,可以安全地验证存储桶是否已被其他人认领。如果是这样,您将需要创建一个具有不同名称的新 S3 存储桶。
-
命名 S3 存储桶:建议不要在存储桶名称中使用可预测或静态的标识符,而是为每个区域和帐户生成唯一的哈希值或随机标识符,并将该值合并到 S3 存储桶名称中。此方法有助于防止攻击者过早认领您的存储桶。
原文始发于微信公众号(Ots安全):Bucket Monopoly:通过影子资源入侵 AWS 账户
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论