python3 thunder.py destroy
Your virtual environment must be active to use thunder.py:
source ../env-tctf/bin/activate
python3 thunder.py create thunder/a3password
Activate the service account given to you. You MUST do this, or the level will not work as intended.
gcloud auth activate-service-account --key-file=start/a3-access.json
In this level, the secret is hidden somewhere in the cloud infrastructure. Use the given compromised credentials to find it
Test the permissions of the given credentials using the test-permissions.py script.
The credentials have the permission cloudfunctions.functions.list
List the cloud functions in the project:
gcloud functions list
Get more information about the function:
gcloud functions describe [function]
Try calling the function:
curl [httpsTrigger]
The function returned a 403 response, meaning you need to authenticate your request. Google's documentation for cloud function authentication can be found here.
To authenticate the request, we need to include an "identity" token (different than an "access" token) in the request.
Generate an identity token for the service account:
gcloud auth print-identity-token
Call the function using the token:
curl [httpsTrigger] -H "Authorization: Bearer [identity-token]
Or, do this in one command:
curl [httpsTrigger] -H "Authorization: Bearer $(gcloud auth print-identity-token)"
The function wants a "password" argument. Try including one by adding "?password=abc" to the end of the url. Obtaining the source code for the function might help with finding the password the function seeks.
The credentials you are using have the permission cloudfunctions.functions.sourceCodeGet. As a result, you are able to download the code of the function to figure out what it is doing. Use the Cloud Functions REST API method projects.locations.functions.generateDownloadUrl to download the source code.
Go to the REST reference here. This documentation describes how to make a request to the API to create a link to download the source code of a cloud function.
In this case, you can use the "Try this API" feature on the right. Fill in the "name" field, formatting it as the documentation specifies. You will also need an access token, which is not the same as the identity token you generated earlier. To generate an access token, run:
gcloud auth print-access-token
In the "Try this API" window, click "show standard parameters," and paste the access token into the field "access token."
Leave the request body empty, and uncheck both "Google Oauth 2.0" and "API key," as we are using the access token for authentication. Click execute, and download the source code by curling or browsing the link given in the response.
In main.py, we see in line 19 that the function expects XOR_PASSWORD, an environment variable, to be equal to the result of the bitwise xor of the entered password and XOR_FACTOR (password ^ XOR_FACTOR).
XOR_FACTOR is a constant in the code, and XOR_PASSWORD is an environment variable that can be found by running:
gcloud functions describe [function]
To find the password, compute the result of XOR_PASSWORD ^ XOR_FACTOR. Call the function, passing the correct password to the "password" argument.
Serverless architectures using things such as Cloud Functions or Lambdas can improve security be removing the ability for an adversary to persist on a machine within the cloud deployment. However, when setting up a function, a developer must specify the cloud resources the function has access to. If a developer misconfigures these permissions, an adversary can use them to compromise an application. In this level, permissions allowing an attacker to view a project's functions allows them to gain access to source code that then allows them to analyze the code directly for vulnerabilities such as an insecure use of cryptography. While it may seem obvious to most people that an XOR-based encryption scheme is easily reversed and broken, the use of XOR to encrypt data is unfortunately being done in practice and sometimes by security companies that would be expected to know better!