Pod Diagnostics

Description

We've discovered a mining pod tunnelling underneath a government facility. Luckily, we've managed to connect to an air-gapped control panel that was seemingly left enabled. Can you exploit it and help us track down the perpetrator controlling it?

Source

entrypoint.sh

#!/bin/bash
# Secure entrypoint
chmod 600 /entrypoint.sh

# Populate admin and session secret env
echo "ENGINEER_USERNAME=engineer" > /app/services/web/.env
echo "ENGINEER_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)" >> /app/services/web/.env
chown www-data:www-data /app/services/web/.env

/usr/bin/supervisord -c /etc/supervisord.conf

/challenge/web/auth.py

from functools import wraps
from flask import g, request, redirect, url_for, make_response, abort, render_template
import base64
import os

engineer_username = os.environ.get("ENGINEER_USERNAME")
engineer_password = os.environ.get("ENGINEER_PASSWORD")

if engineer_username is None or engineer_password is None:
    print("Missing engineer username and password, shutting down...")
    exit()

class AuthenticationException(Exception):
    pass

def auth_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        try:
            header_value = request.headers.get("Authorization")

            if header_value is None:
                raise AuthenticationException("No Authorization header")

            if not header_value.startswith("Basic "):
                raise AuthenticationException("Only Basic auth supported")
            
            _, encoded_auth = header_value.split(" ")

            decoded_auth = base64.b64decode(encoded_auth).decode()

            username, password = decoded_auth.split(":")

            if username != engineer_username or password != engineer_password:
                raise AuthenticationException("Invalid username and password")

            return f(*args, **kwargs)
        except AuthenticationException as e:
            response = make_response(render_template("error.html", status_code=401, error_message="Engineers Only!"), 401)
            response.headers["WWW-Authenticate"] = 'Basic realm="Engineer Portal"'
            return response

    return decorated_function

/challenge/web/main.py

/challenge/web/main.py

challenge/stats/index.js

challenge/pdf/index.js

Solution

Pod_Diagnostics.png

The applications displays the server statistics and updates every 30 seconds. We can download the diagnostics, but not really useful as we got what we see.

Index handler renders diagnostics and reports that have been submitted.

Report generation send request to port 3002 where PDF webapp lives, generates PDF and sends it.

main.py contains 2 other methods, but both need authentication.

Authentication is based on Authorization header. I think this rules our XSS, but CSRF is valid attack vector.

So............. what are we supposed to do?? Well obviously we can't steal anything if we don't control any variables, but nginx configuration did have something interesting in it.

There's caching functionality enabled, which could be dangerous.

The stats has an endpoint that returns main diagnostics on the page

proxy_cache_key "$arg_period"; passes the query argument period to the proxy.

If we add another period to the params something unexpected happens, the next url is cached and previous results are returned.

Pod_Diagnostics-1.png

We are able to inject HTML into the page which opens up XSS/CSRF vectors.

We can trigger the XSS via generating report, because the main website is visited which is cached and poison by us we get to inject anything. Another important thing to mind is that we need to poison 1m interval, as that's the default value when loading page.

Pod_Diagnostics-2.png

CyberChef Recipearrow-up-right

Pod_Diagnostics-3.png

/flag is readable? even through intended way is probably to use /readflag binary to read the file.

Pod_Diagnostics-4.png

Sidetracking, but sometime around I just got tired of copy pasting blobs and downloading files. I tried using Pipedream but I got limited from testing... Well why not deploy your own server??

Oracle offers Always Free machines, which is more then enough to handle all CTF shenaniganry, https://www.oracle.com/cloud/free/arrow-up-right.

Pod_Diagnostics-5.png

Update the PoC script, because It works on my machine problem.

Create simple application to handle the decoding:

Anyways, the report.py has some suspicious code usage.

merge function is famous for Class Pollution (Python's Prototype Pollution)arrow-up-right

The render method is also suspicious. The Template is generated from string and report is populating the values. SSTI (Server Side Template Injection)arrow-up-right

We can achieve RCE from Class Pollution: https://www.offensiveweb.com/docs/programming/python/class-pollution/arrow-up-right

But first we need to login. Using the XSS PoC script read the .env file which is holding the credentials.

Login, submit report, catch it in burp, edit the request with above JSON which will run /readflag and place it in static folder.

Get the flag: http://83.136.255.235:47563/static/flag.txtarrow-up-right

circle-check

References:

Last updated