Level 7a - DevSecMeow

Domain(s): Cloud

Palindrome has accidentally exposed one of their onboarding guide! Sneak in as a new developer and exfiltrate any meaningful intelligence on their production system.

Challenge URL 1

Navigating to the provided URL shows us some very cute images of cats...and also some details about the cloud infrastructure we are meant to attack.

Under the section 2 quick steps to get your staging access, we are provided with 2 URLs:

The first URL generates 2 pre-signed URLS to access the S3 bucket, one for a client.csr, and one for a client.crt.

Upon navigating to these 2 URLs, the first one displays a Signature Mismatched error, and the second one an Access Denied error.

client.csr refers to a certificate request, which is a file that is used to generate a certificate, client.crt. This means that we're likely expected to upload client.csr, which would trigger a lambda function that helps us to generate client.crt for us to download.

First, generate a CSR with OpenSSL.

Then use cURL to upload the file to the provided link.

Now, we should be able to retrieve the generated client.crt from the second link.

With some references to mTLS (mutual TLS), we can assume that the second URL can only be accessed after configuring this in the browser.

First, generates the PKCS#12 file with OpenSSL with the client key and certificate.

On Chrome, Open Settings > Privacy > Security > Manage device certificates. Then click Import and select client.p12.

You should be able to view the certificate in the list now.

Next, navigate to the second URL: https://13.213.29.24/arrow-up-right, ignore the security warning, and select the certificate you just uploaded when prompted.

After awhile, you should see a message that provides a set of AWS credentials.

Configure the credentials with aws configure and start enumerating the IAM.

First retrieve the username associated with the credentials.

Then retrieve the list of policies attached to the user.

Then retrieve the policy document to find out what permissions we have.

The policy document states that we have the following permissions:

Permissions:

  • IAM

    • ListAttachedUserPolicies

    • GetPolicy

    • GetPolicyVersion

    • List*Policies

    • Get*Policy

  • SSM

    • DescribeParameters

  • KMS

    • ListKeys

    • GetKeyPolicy

  • Events

    • ListRules

    • DescribeRule

  • CodePipeline

    • ListPipelines

    • GetPipeline - devsecmeow-pipeline

  • CodeBuild

    • ListProjects

    • BatchGetProjects

  • S3

    • PutObject - devsecmeow2023zip

Let's try enumerating CodePipeline.

Analyzing the output, you should see that the pipeline takes in input from a rawr.zip in the devsecmeow2023zip S3 bucket.

It then runs the CodeBuild project devsecmeow-build.

Next, we can use the batchGetProjects privilege to retrieve the CodeBuild configuration.

We can see that it spins up a container that contains the environment variable flag1.

According to the buildspec, the container runs the command terraform plan.

Now, there are 2 ways to achieve command execution to retrieve the first flag.

  1. Using the terraform plan command to start a reverse shell

  2. Writing a buildspec.yml file to override the default buildspec to run our own commands

We'll go with the first option for this writeup.

First, start a netcat listener and forward the port with ngrok.

Then, write a terraform file test.tf and compress it into rawr.zip.

Next, upload rawr.zip to the S3 bucket to trigger the pipeline and you should receive a shell.

Run the env command to retrieve the flag, and you should also see some important information for our next steps.

We can access the metadata endpoint with the credentials relative URI to retrieve the credentials associated with CodeBuild.

The endpoint responds with AWS credentials and a session token.

Configure a new AWS profile with aws configure --profile=devsecmeow or enter the following in .aws/credentials for us to enumerate further.

Using this new profile to run any command that the profile does not have privileges for, we see that we are currently assuming the codebuild-role role

Using the previous credentials we can list all IAM policies.

One of the policies stands out, iam_policy_for_ec2_production_role. Similarly, view the policy document.

We can see that EC2 instances with a role with this policy attached are able to access the S3 bucket associated with flag2. Therefore we know that we have to take over a production EC2 instance.

As CodeBuild spins up an EC2 instance to build the source code, its credentials should carry permissions that allow us to enumerate or even access EC2. We can verify this by using the initial profile which has IAM permissions, to list the role policies assigned to our assumed role.

We see that we have the permission "ec2:DescribeInstance*" which means we could list all of the EC2 instances.

The output of the command shows 2 EC2 instances, one each for staging and production (with the public IP 54.255.155.134)

Navigating to https://54.255.155.134arrow-up-right shows us a a similar error regarding an invalid certificate. This likely means we have to configure mTLS again.

The action in the codebuild-role role policy, "ec2:DescribeInstance*", states that we could also list the attributes associated with the EC2 instances.

Enumerating the instance attributes, we find some useful information from the UserData attribute.

After decoding the Base64 encoded value, we find an NGINX configuration file showing that the endpoint requires SSL to access the flag server on port 3000, along with the files server.key, server.crt and ca.crt.

Next, generate the PKCS#12 file for the production site

Then configure mTLS like before, navigate to https://54.255.155.134/arrow-up-right, and select the new certificate

And finally, we get more pictures of the cat! and the flag too.

FLAG: TISC{pr0tecT_yOuR_d3vSeCOps_P1peL1nes!!<##:}##>}

Last updated