Solving Thunder-CTF: Level 03

Have you checked my write-up for previous levels? If not, here are the links:

Let’s get started with level 3:

python3 thunder.py create thunder/a3password

We will now check this service account’s permissions using the Python script in the Thunder CTF repo.

python scripts/test-permissions.py start/a3-access.json

As we can see, all the permissions are related to Google’s cloud functions service. We will move towards cloud functions for further investigation.

Since the service account has cloudfunctions.functions.sourceCodeGet permission, we can get the source code of the cloud function.

Listing the Google Cloud function, using the command:

gcloud functions list

Describing the cloud function:

gcloud functions describe a3-func-293057166056

We got the XOR password from the environment variables for the cloud function described above. The output suggests that the cloud function might be encrypted using XOR encryption, a simple symmetric encryption.

The XOR password is the encryption key for XOR encryption. In this type of encryption, the plaintext is bit-wise XORed with the key, and then we get the ciphertext. To get back plaintext data, simply XOR the ciphertext with the corresponding bits of the key that were used to encrypt it

Let’s try accessing the function using the httpsTrigger link. We get the following unauthenticated error.

NOTE: We have used Postman to make requests to the URLs

We need to pass an authentication token with the URL to fix this.

gcloud auth list

The currently active account is the service account created for this level. (* mark indicates that this account is currently active)

We need to get the identity token for this service account, which we can simply get using:

gcloud auth print-identity-token

Now, we will curl the cloud function URL we got, using the above identity token as the bearer token.

The output displays that we need to pass a password argument in this URL to access the cloud function.

We will pass some dummy passwords as arguments in this URL and see what will happen.

https://us-central1-cloudsecurityclub-dev.cloudfunctions.net/a3-func-293057166056?password=hello12

The response tells us that the password is an integer.

Let’s get the source code of the cloud function and understand its logic before proceeding with the attack.

We make a post request to the URL to download the source code of cloud function along with the access token of the service account. The response will provide a URL to download the source code.

https://cloudfunctions.googleapis.com/v1/projects/cloudsecurityclub-dev/locations/us-central1/functions/a3-func-293057166056:generateDownloadUrl

Note: We are hitting a different endpoint to download the source code. We are passing a different access token as well – generated from executing gcloud auth print-access-token

By visiting the link, we will download the zip file containing the source code.

These are the files in the zip folder: main.py and requirements.txt.

In main.py, we can see that ( password ^ XOR_FACTOR == XOR_PASSWORD ), which tells us XOR_PASSWORD in the environment variable is checking for the XOR of XOR_FACTOR and password.

Which indirectly tells us that, XOR_PASSWORD = password ^ XOR_FACTOR

Let’s find the password!

  • When we described the cloud function earlier, we got XOR_PASSWORD (value was 569436999751)

  • In this cloud function code (main.py), we have XOR_FACTOR (value was 347808535942)

  • We can find the password by doing

    • Given: Plaintext Password ^ XOR_FACTOR = XOR_PASSWORD

    • Password (Plaintext) = XOR_FACTOR ^ XOR_PASSWORD

  • So the password in our case will be 347808535942 ^ 569436999751, which gives password = 912380003777

We will now append this password to the URL and try to access the Google Cloud function by passing it.

This gives us the secret value and marks the end of Level 3.

If you want to read more about GCP misconfigurations, check out my Thunder CTF Level 4 write-up!

Reply

or to participate.