ctf, LFI, pentest, Uncategorized, Web Attacks

This CTF was made by Jimmy to test a number of aspects. It was also keen as the previous one on attention to some details. So without further ado, lets get into what made this journey awesome.

Know About Thy Target

This was the first step and for this I used Nmap just to get  a feel of what we are working with.

Nmap scan on all ports

Nmap scan on all ports

From here we have a few attack points.

  • Apache (Pronounced “Bloated Webserver“)
  • MySQL Server
  • 2 RPC Services

Looking at the odds bruteforce would take a bit of time against MySQL and there is a chance that the root account is actually disabled on it. So instead of this its easier to see if “Our Bloated Highness” would hold favour to our cause.

I call on thee great apache show me mercy

Loading the application hosted on apache we notice 2 things:

  • Login – Possibilities here are input injection attacks like SQL Injection, XSS
  • URL has a page parameter that dynamically calls pages – Possibilities here are more functional level issues like LFI, RFI.

Well on testing the login form for input injection attacks they failed as quotes were filtered. We later found out that this was because of the use of prepared statements.

$stmt = $mysqli->prepare(“SELECT * FROM users WHERE user=? AND pass=?”);
$stmt->bind_param(‘ss’, $luser, $lpass);


For those with little faith in simple tests a scanner would be left at the same injuncture, this is output from one.

Thou shalt not call on netsparker to do your logical work, load brain module

Thou shalt not call on Netsparker to do your logical work, load brain module

Seeing that this was not working in our favour it was safer to try the second option, even though the site yields no serious issues from a scanner perspective. Pages load dynamically see below as to why:

I don't care Imma Include Files via the URL so that I can feel good about my self ~ said the index file

I don’t care Imma Include Files via the URL so that I can feel good about my self ~ said the index file


Notice that you can access directly a page or include it , in the page parameter but it gets loaded without an extension. That my friend is classical file inclusion. what this means is if we want to load the config file our URL would be something like:

However as we notice the files are PHP we cannot read them. if you try add a regular payload to test e.g.


These don’t work so the LFI is not as straight forward as thought but we are not done yet. The webserver is bloated meaning it has a feature that is usable , an alternative method to retrieve files; enter php://filter  used to validate and sanitize external input. Everything is abusable, now its also a fact that if we use this to retrieve data from the server it will interpret it still therefore we need to convert it to a format the server will not attempt to interpret the information, supported methods for this filter for this are as seen here.

So now what was needed was to invoke filter to pull a resource then convert the resource(file) into base64 so that apache doesn’t interpret and execute it. This helps generate the payload structure as below:


and voila after that decode base64 and you have the source.

Read the Config File (who was to bruteforce that again???)

Read the Config File (who was to bruteforce that again???)

So now on logging into mysql and reading the DB.

User Accounts Base64 encoded

User Accounts Base64 encoded

Next idea would be to backdoor on decoding the base64 passwords:

kent: JWzXuBJJNy
mike: SIfdsTEn6I
kane: iSv5Ym2GRo

Logging in to the app with these accounts we can’t upload a backdoor because it checks files uploaded on both extension and mime types, the extension check is whitelisting rather than blacklisting so that cannot be abused.

$whitelist = array(“.jpg”,”.jpeg”,”.gif”,”.png”);
if (!(in_array($file_ext, $whitelist))) {
die(‘Not allowed extension, please upload images only.’);
if(strpos($filetype,’image’) === false) {
die(‘Error 001’);
if($imageinfo[‘mime’] != ‘image/gif’ && $imageinfo[‘mime’] != ‘image/jpeg’ && $imageinfo[‘mime’] != ‘image/jpg’&& $imageinfo[‘mime’] != ‘image/png’) {
die(‘Error 002’);
if(substr_count($filetype, ‘/’)>1){
die(‘Error 003’);

Uploading the shell via MySQL was also impossible because into dumpfile and into outfile were not working , reading using load_file also returned nulls. Enter dirbuster.

Admins leave clutter in binary there's 0 and 1 but right now we in alphabet mode we get o for ooopss!!!

Admins leave clutter in binary there’s 0 and 1 but right now we in alphabet mode we get o for ooopss!!!

There loading it shows that its here we have a shell given to us. In the Next article we will discuss how to take down the rest of the pieces and capture the flag , the tricks are less from this point.

Leave a Reply

Your email address will not be published. Required fields are marked *

February 2024