- Cloud Security Club
- Posts
- Solving GCP Goat
Solving GCP Goat
GCPGoat (by Joshua Jebaraj) focuses on providing a comprehensive learning environment for GCP security. It includes scenarios for attacking various GCP services, such as Google Kubernetes Engine (GKE), Cloud Storage, SQL instances, and App Engine.
This project differs from other vulnerable GCP projects we have checked out.
This project is not a CTF, so there’s no flag under each scenario. Rather, it’s a set of challenges containing misconfigured GCP resources. Each challenge has a clear title denoting the misconfigured resource (like GCS, GKE, etc.).
The lab setup could be more straightforward. For some challenges, there are more steps apart from terraform init
and terraform apply
.
If you want to quickly jump to solution of a particular challenge, here you go:
Attacking GCS
You can set up the challenge as per the documentation.
During the setup, we set the unique bucket name as “gcpcsc123” and the challenge has created a GCS bucket – gcpcsc123-backup
gsutil ls
Now, let’s try to access this storage bucket without using our service account.
Simply visiting this storage bucket URL shows that all of the bucket objects are publicly list
https://storage.googleapis.com/storage/v1/b/<gcpgoat-bucket>/o
We see juice-shop.zip
present in the bucket. We can download the ZIP file by visiting the URL
https://storage.googleapis.com/storage/v1/b/<gcpgoat-bucket>/o/juice-shop.zip?alt=media
Extracting the zip file, we can find the secret.
Attacking SQL instance
You can set up the challenge as per the documentation.
This challenge creates a database and gives the public IP of the database in the output. In our case, the DB’s IP is 35.194.155.109.
Let’s check if the database is publicly exposed.
nmap -Pn <EXTERNAL_IP>
We see that port 3306 is open for connections.
Let’s try to log in to MySQL using MySQL Client. (You can install the client using sudo apt install mysql-client-core-8.0
)
The database lets us log in without a password!
mysql -u root -h 35.194.155.109
Note: This database allowed login without a password, but such databases are rare
By running this command, we successfully logged in to the database instance, and now we can search for some vital information from here.
With this, we were able to access the database instance. It didn’t contain any sensitive data or flags.
Attacking Artifact registry
You can set up the challenge as per the documentation. This setup involves quite a few steps and could be more straightforward.
As per the CTF description, this scenario assumes that we have found the project and repo names.
In our case, the project name is cloudsecurity-dev
, and the repo name is gcp-goat/secret
.
The container registry hostname follows the <region>-docker.pkg.dev
pattern. Trying to find the location shows our registry is in the us-central1 region
Now, we will download and run this Docker image.
We can find the file creds.json
inside the container containing the service account key.
Attacking GKE
You can set up the challenge as per the documentation.
After successfully deploying the challenge, we get the entry point to the challenge - http://<external_ip_of_node>:30003/page
.
Visiting the page shows us the following web page:
After testing for several server-side injections (command injection, SQLi, etc.), server-side template injection worked.
Now, we will exploit this SSTI vulnerability with the tool tplmap.
python3 tplmap.py -u http://<node-external-ip>:30003/page?name=gcp-goat --os-shell
We can now access everything from the shell in the application’s container.
This container runs on Google Kubernetes Engine (GKE) nodes. Each GKE node has an attached default service account (with Project Editor permissions). So, if you get a shell inside the container running on GKE, you can view and modify other resources in the project.
For example, I can list the project’s GCS buckets and VM instances from the container.
Attacking Google App Engine
You can set up this challenge by following the documentation.
This challenge deploys an App Engine app that provides us with the URL https://cloudsecurityclub-dev.wl.r.appspot.com
Visiting the URL shows the following webpage:
As this application takes any URL as input, let’s try passing the Instance Metadata endpoint to it along with the header Metadata-Flavor: Google
.
The metadata server is at http://metadata.google.internal
, and the endpoint that grants temporary credentials is at /computeMetadata/v1/instance/service-accounts/default/token
. Let’s try accessing it.
We got the access token corresponding to the service account, which we can use to access the resources.
Privilege escalation
You can set up the challenge as per the documentation.
The challenge provides us with a service account key. Let’s find the permissions of the service account.
python3 test-permissions.py creds.json
Note: This test-permissions.py
script is a fork of the Thunder-CTF project. We have modified it to check the permissions related to the creds.json
file, in order to display the permissions associated with this service account.
Now, we will impersonate other service accounts using this service account. Impersonation provides the current user/service account with the privileges of some service account.
With this command, we export the email of the compute engine’s default service account.
export SA_EMAIL=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")-compute@developer.gserviceaccount.com
With this command, we impersonated the service account with the privileges of the default-compute-engine’s service account.
gcloud config set auth/impersonate_service_account $SA_EMAIL
NOTE: The default service account used to have the automatic permission (Editor Role) attached to it by default, but from 03 May 2024 onwards, this automatic role is disabled. So, our default compute engines don’t have any permissions associated with them, but earlier, they used to have the Editor role associated with them for the project.
So, to demonstrate this scenario and how we can impersonate the permissions of other SAs to the particular SA, we will explicitly set the EDITOR role for the default service account for the compute engine.
gsutil ls
The permissions of the default compute engine’s SA help us list the contents of the buckets.
gcloud compute instance list
With this we have completed all the challenges.
Reply