- Cloud Security Club
- Posts
- Solving GCP Pentest Lab CTF
Solving GCP Pentest Lab CTF
GCP-Pentest-Lab is a vulnerable environment designed to explore and exploit GCP misconfigurations. This project contains different misconfigurations (with six flags), and the flags have no specific format. Players start as random users through a web application and must find their way through various security flaws without relying on traditional web or OS-level exploits.
Table of Contents
Setup
Go to any command line (Linux preferred). Configure your Google Cloud account as given in the initial steps of this lab.
First, clone the GitHub repository.
We can see the terraform files in it that we need to run to spin up this lab.
terraform init
terraform apply
While deploying, enter the project ID of the GCP project you will use to run this lab.
Note: For this blog post, we are deploying on a GCP project named cloudsecurityclub-gcp
We get a public IP of the VM, which is the entry point to the labs.
Flag-1
Description: Flag 1 is in an open bucket
Solution:
Let’s try visiting the IP address from the output in the browser.
The images on this website are hosted on GCP buckets. The name of the bucket is cloudsecurityclub-gcp-prod-bucket.
We can see if the bucket is misconfigured to list the contents of the bucket.
https://storage.googleapis.com/storage/v1/b/cloudsecurityclub-gcp-prod-bucket/o
When we tried to do so, we got an error message saying the user didn’t have the .list
permission on the resource. In simple terms, the objects in this bucket can be public, but the bucket doesn’t list all the objects in it.
However, the Flag 1 description says it is an open bucket. Let’s see if other images are hosted elsewhere.
In one of the images on the website, we can see that the bucket name (cloudsecurityclub-gcp-dev-bucket) differs from the previous bucket we found.
We will see if this bucket is misconfigured and lists all the objects.
https://storage.googleapis.com/storage/v1/b/cloudsecurityclub-dev-dev-bucket/o
We can see the list of all the objects in this public “dev” bucket.
Now, we will analyze all the objects.
We can see this object named flag1.txt
. We will download it using the mediaLink
given.
Just click on that mediaLink
URL or paste it into the browser.
The downloaded file has our first flag.
Flag-2
Description: Flag 2 is in another bucket, but this one isn’t public 🙂
Solution:
From the objects in the same cloudsecurityclub-gcp-dev-bucket, we find another interesting file – sync_sa_key.json
.
Upon downloading it in the same way as above, we got the below key.
The service account file contains base64 content. We will decode this base64 string and rename it as decoded_sync_sa_key.json
.
Now, we will activate the service account with this decoded key.
Now, we will list the buckets using this service account.
gsutil ls
We now will list the content of cloudsecurityclub-gcp-secret-bucket
.
This shows that this bucket has flag2.txt
.
We got the second flag.
Also, when we list the content of the other secret-secret bucket, we can see that this bucket has flag-6.txt
.
We got an error when copying this flag-6.txt
from this bucket.
We’ll get back to it later. We will go to find the next flag now.
Flag-3
Description: “Flag 3 is sitting inside some source code.”
Solution:
We will access the web application’s source code by SSHing into the virtual machine.
For that, first, we will set the public ssh-key into the metadata of the compute instance. Then we will try to ssh into the instance and search for the source code there.
We will generate the ssh-key:
ssh-keygen -t rsa -b 4096
We will keep the name of the SSH key as ssh-key-gcp
We can see that SSH private key and public key are created.
We will set this public key in the metadata of the compute instance and use the private key to ssh into the instance.
We will now add the SSH key to the metadata of the instance
gcloud compute instances add-metadata cloudsecurityclub-gcp-flask-vm
--metadata=ssh-keys="ubuntu:<ssh-key-gcp.pub> ubuntu" --zone=us-east4-a
NOTE: You can check the name of the instance and the zone by listing the compute instances - gcloud compute instances list
Now, we will use the private key to SSH into the instance.
ssh -i <private-key> username@<external_ip_address>
We are inside the compute instance now. We can see the machine’s name, which is also the name of the compute instance.
Inside the /etc
folder, we can see the gcp-pentest-flask-app folder.
Getting into that folder and listing the contents of it
We can see app.py
inside it.
Since the flag-3 description states that the flag is in some source code, let’s explore the source code.
We found the third flag in the source code comments.
Now, we will move to the fourth flag.
Flag-4
Description: “Flag 4 is a secret, literally!”
Solution:
The first thing someone can think of regarding GCP infrastructure is the secret manager, as they store confidential information (secrets, in other words).
Let’s see if the VM’s default access token has access to list and fetch secrets from the secret manager. First, we get the access token.
curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
export ACCESS_TOKEN_DEFAULT_SA=<token>
We will try to access the secret manager by requesting the URL below with the access token of the default service account.
curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" "https://secretmanager.googleapis.com/v1/projects/cloudsecurityclub-gcp/secrets"
The output says an entry in the secret manager with the name flag-4
. We will try to access it.
We will again make a curl request on the URL below, appending the secret name flag-4
. Every secret can have multiple versions. Using the latest will fetch the contents of the most recent version. Also, we must use the access method to get the data stored in the secret manager.
Our final curl command looks like the following:
curl "https://secretmanager.googleapis.com/v1/projects/cloudsecurityclub-gcp/secrets/flag-4/versions/latest:access" --header "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA"
The data for flag 4 is visible and in a base64-encoded format. Let’s decode it.
We have found the fourth flag.
Flag-5
Description: “Flag 5 is inside some instance but isn’t a file! “
Solution:
Let’s see if there’s any juicy information in the instance’s metadata.
We can see that this service account we got from cloudsecurityclub-gcp-dev-bucket is currently active on my local system.
gcloud auth list
First, we will list the compute instance with the help of this service account.
gcloud compute instances list
We can see the instance’s name and zone from the above information.
First, we will set the access token of the service account we activated from the key we got from the dev bucket into the environment variable ACCESS_TOKEN
.
export ACCESS_TOKEN=$(gcloud auth print-access-token)
We will pass it on to the curl request we will make next to retrieve the metadata.
export METADATA=$(curl -H "Authorization: Bearer $ACCESS_TOKEN" "https://www.googleapis.com/compute/v1/projects/cloudsecurityclub-gcp/zones/us-east4-a/instances/cloudsecurityclub-gcp-flask-vm?fields=metadata")
We can see the request was successful, and we received the response.
echo $METADATA | jq
We got the 5th flag stored in the startup script in the compute instance’s metadata.
Flag-6
Description: “Flag 6 is in yet another bucket, but this one is the most restricted yet!”
Solution:
While getting the second flag, we saw a super-secret bucket containing the flag6 file.
We will try to access that bucket using the default service account’s access token for the compute instance.
curl -H 'Metadata-Flavor: Google' http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
We got the access token of the default service account.
We will use this access token to see if we can access the flag6 object in the super secret bucket.
curl -H "Authorization: Bearer $ACCESS_TOKEN_DEFAULT_SA" "https://storage.googleapis.com/storage/v1/b/cloudsecurityclub-gcp-super-secret-bucket/o/flag6.txt?alt=media"
Finally, we found the 6th flag.
Reply