- Cloud Security Club
- Posts
- Solving Thunder-CTF: Level 03
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