本文为译文,原文链接:https://frichetten.com/blog/aws-api-enum-vuln/
以下是我在AWS API中发现的一个错误的技术写入,该错误允许您枚举角色的某些权限,而无需登录CloudTrail。它影响了40种不同AWS服务的645个不同的API操作。这对渗透测试员或红队列举他们被盗的角色或用户可以访问的权限,而无需提醒蓝队,因为CloudTrail中没有生成日志。
本文分为两部分。第一个是关于如何利用漏洞的快速总结。第二个是对发现和技术分析的解释。
完整的PoC和脚本在这里可用。
什么是脆弱的
该漏洞允许您枚举给定角色是否有权调用AWS API操作,而无需在特定条件下登录CloudTrail。
- AWS服务使用JSON 1.1协议。
- API操作返回唯一的错误代码,具体取决于权限集。
- 与该操作关联的资源设置为“*”。
我识别的每个易感API的完整列表可以在这里找到。
利用过程
该漏洞影响使用POST请求和X-Amz-Target标头的某些AWS服务(每个AWS API都使用不同的协议类型。有些使用GET请求,有些使用POST到API端点等)。大多数这些服务要求Content-Type标头为“application/x-amz-json-1.1”。在大多数情况下,发送“application/x-amz-json-1.0”会给您带来错误;通常是404-“UnknownOperationException”或500-“InternalFailure”。
但是,在具有易受攻击API调用的服务上,如果您没有调用API的权限,您将获得403响应。如果角色确实有权调用API,您将获得404。由于这些是技术上“格式错误”的请求,因此这些流量都不会发送到CloudTrail。这意味着您可以枚举给定角色是否有权在不记录该侦察的情况下进行API调用。重要的是要注意,只有当角色有权进行API调用时,并且资源设置为“*”,您才会收到404响应。
要查看此操作,如果您调用secretsmanager:ListSecrets,在将Content-Type标头设置为“application/x-amz-json-1.0”时,您将获得403响应。
但是,如果我们修改进行侦察的角色,并提供以下策略,我们会收到404响应,表明我们有权在不登录CloudTrail的情况下拨打此调用。
注意:并非所有操作都可以根据403/404错误代码枚举。请继续阅读以获取更详细的解释和边缘案例。
发现
找到这个漏洞的过程发生了许多转折,在我意识到我拥有什么之前,我陷入了许多兔子洞。
是什么开始搜索的?作为我为ShellCon演讲的一部分,我开始整理我认为攻击AWS的主要主题以及我自己的一些研究。有一件事让我很突出——需要在不登录CloudTrail的情况下识别一组访问密钥。在攻击AWS时,在不知道AWS与哪个角色/用户相关联的情况下访问AWS凭据的情况并不少见。
以前,有一种滥用sdb:ListDomains的方法,不支持CloudTrail。不幸的是,在2020年8月,它获得了CloudTrail的支持,因此无法在OPSEC安全方式使用。
因此,我开始搜索API调用,这些调用可用于识别您在不登录CloudTrail的情况下运行的角色(我最终在不那么戏剧性的位置[推文]发现了这一点)。我特别有信心我会找到一个,因为许多AWS服务会错误地通知您拨打电话的角色的名称和帐户ID。我只需要找到一个没有出现在CloudTrail中的。
在手动完成大量操作后,我最终转向了针对AWS控制台。对于那些不知道的人来说,控制台可能会使用未记录的API,这可能会提供额外的功能(Rhino Security有一篇很好的博客文章,描述了他们如何滥用未记录的API来升级AWS帐户中的特权)。
从那里我开始狩猎。最终,我偶然发现了一个没有出现在AWS文档macie😃escribeMacieAccountDetails中的Macie API。
为了可靠地调用它并进行更多测试,我使用了AWS API签名示例来简化事情。AWS中的每个API调用都必须使用特定格式进行签名,绝对建议使用其模板示例。
果然,如果您没有进行API调用的权限,您将获得400个响应,其中包括调用角色!
成功!我们的目标是在不登录CloudTrail的情况下枚举我们的呼叫身份。然而,我开始感到好奇。如果我尝试提供不存在的操作,会发生什么?您将获得400-“UnknownOperationException”。这就是奇迹发生的地方。
我对Content-Type标头感兴趣。如上所示,指定的标头是“application/x-amz-json-1.1”。这个标题真的很重要,因为偏离它会给你带来一个类似的错误,就像如果你提供了一个不存在的操作一样。然而,我知道AWS库中的其他API使用“application/x-amz-json-1.0”,我想知道这将如何运作。反应很奇怪。当提供不存在的操作并修改Content-Type标头时,您将获得403而不是400。
你注意到这有什么奇怪的吗?通过指定不同的内容类型标头,我不仅得到了不同的响应代码,还让它在指定无效操作时返回调用角色。这让我想知道,如果我选择了一个通常登录CloudTrail的Macie API,那会怎么样。如果我设置了不同的内容类型标头,它会记录吗?因此,我选择了macie:ListMemberAccounts操作,并进行了测试。
果然,它没有登录到CloudTrail,我收到了403的回复。下一个想法是:“好吧,如果角色有权拨打那个电话,会发生什么,回应是什么?”我允许它这样做,并重新运行脚本。
该死,我真的希望它能提供内容。找到一种在不登录CloudTrail的情况下返回内容的API调用的方法将是一个神圣的圣杯。伤心地,我在办公桌前站了几分钟。这里有东西,我只是无法把手指放在上面。你觉得这很奇怪吗?这些响应代码彼此之间没有关联。
我在一些刮刮纸上画了一张小图表,盯着它。
该图表确实阐明了漏洞。如果我使用1.0标头,我会根据我是否拥有权限获得不同的响应代码!这是一件大事的原因是,通常情况下,如果您需要枚举您的权限,您需要使用枚举-iam等工具,该工具强制API调用并报告哪些有效。当然,问题在于,您将在CloudTrail中填充大量日志,而防御者可能会发现您。有了这个,我可以在不登录CloudTrail的情况下确定角色是否拥有某种权限!
这就是事情变得更复杂的地方。我知道这对Macie中的某些API调用有效,但其他API系列呢?我很快就偶然发现了秘密经理,他也很脆弱。我的下一个问题是:“这适用于特定资源吗?如果角色有权读取特定秘密,我可以做出这个决定吗?”
简短的答案是否定的。无论出于什么原因,在IAM策略中设置特定的ARN都不会触发漏洞。它将返回403个回复。只有当策略的资源设置为“”时,漏洞才会触发。我推论到,在验证请求的过程中,在策略中设置“”跳过验证中的某个步骤(注:我没有这方面的具体证据)。
既然我对漏洞的工作原理有一些标准,我需要弄清楚所有可能易受攻击的API调用。重要的是要注意,仅仅因为AWS服务中的一个调用是易受攻击的,这并不意味着每个调用都是脆弱的。以Kinesis为例;Kinesis:ListStreams会起作用,但Kinesis:ListShards不起作用。更具体地说,每当“application/x-amz-json-1.0”标头与kininesis:ListShards一起使用时,我都会收到500个回复。无论我们是否得到许可。
那么,如何测试每个AWS API调用特定漏洞呢?
扩大规模
这样做的方法来自一个意想不到的地方。我上面提到的enumerate-iam工具有一个功能,它可以通过从AWS GitHub repo中读取AWS API定义来更新自己。我从那本书中提取了一页,并创建了一个脚本,该脚本将以编程方式调用使用JSON 1.1协议的每个AWS API。然后,我运行了两次这个脚本,一次是没有权限的角色,一次是具有:的角色。该脚本将捕获响应代码、服务名称、操作和响应主体的散列。
然后,我比较了这两个输出,并检查了响应代码不同的情况。此外,我后来发现了一些服务,无论权限如何,它们都会返回相同的响应代码,但会有一个不同的响应主体(因此我使用哈希来比较它们)。
将我的输出与CloudTrail进行比较以确保没有显示,我有一个完整的API列表,这些API没有登录到CloudTrail。该列表由40种不同AWS服务的645个唯一的API调用组成,这些调用是:
概念验证
由于这项工作,我创建了一个概念验证,该证明将测试所有这些易受攻击的API,并确定调用角色是否有权使用它们。让我们使用以下策略并测试PoC。
这些东西是否出现在CloudTrail中?
正如您从屏幕截图中看到的,在等待30分钟后,我们检测到的权限都没有登录到CloudTrail(查看时间戳)。
AWS响应
我于9月2日联系了AWS安全团队。他们非常有礼貌,很容易合作(向Krishanu和Zack大声)。在他们那边挖掘并重现问题后,他们最终确定这不是一个漏洞。虽然我理解他们的立场,但我不同意这个结论。在我看来,攻击AWS基础设施最困难的部分之一是找到您对您已泄露的角色拥有哪些权限。您可以使用工具来强制执行这些权限,但这是一个非常嘈杂的过程,可能会触发警报(这是一件好事)。由于这个错误,对手可以枚举他们是否拥有数百个API权限,而不会在防御方造成任何警报。