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

or to participate.