Hackers! It looks like the Grinch has released his Diary on Grinch Networks. We know he has an upcoming event but he hasn’t posted it on his calendar. Can you hack his diary and find out what it is?

My Diary

Flag6 1

The 6th Flag and fourth app. With a fresh cup of coffee we are ready to go. As usual we are starting with the analysis of the page. There are not CTA (call to actions). No buttons, no client site JavaScript. So where to start. We could say: Let’s start FFUF or dirb to scann for hidden folders and files. But before doing it we have to check the URL were to place the FUZZ placeholder. So lets have a look:

https://hackyholidays.h1ctf.com/my-diary/?template=entries.html

This URL looks very interesting to me. Looks like the template parameter takes a filename to load the content from. This is a common vulnerability if the implementation of this logic is not done right.

I have received so many chat messages about this challenge because other hackers told me something like “I am fuzzing for hours now… but nothing works… everything is redirecting me to entries.html”. What are they doing wrong? Well, they tried to let the script do their work. To be smart and find the actual vulnerability. This is in most cases not the right approach. So let’s start manually step by step and find the vulnerability. On of my first test was to find the programming language used. Ok to be honest, all of the challenges are created with PHP so it was a easy guess.

So lets try this Url https://hackyholidays.h1ctf.com/my-diary/index.php?template=entries.html. Same result. Which is good! That means there is a index.php taking care of the overall logic. The webserver (nginx/1.18.0 (Ubuntu)) is configured to use the index.php as the index file of the given webroot directory. Thats why there is no need to use is explicitly but we can.

So what if we try to load this index.php as template: https://hackyholidays.h1ctf.com/my-diary/?template=index.php

Bingo!

<?php
if( isset($_GET["template"])  ){
    $page = $_GET["template"];
    //remove non allowed characters
    $page = preg_replace('/([^a-zA-Z0-9.])/','',$page);
    //protect admin.php from being read
    $page = str_replace("admin.php","",$page);
    //I've changed the admin file to secretadmin.php for more security!
    $page = str_replace("secretadmin.php","",$page);
    //check file exists
    if( file_exists($page) ){
       echo file_get_contents($page);
    }else{
        //redirect to home
        header("Location: /my-diary/?template=entries.html");
        exit();
    }
}else{
    //redirect to home
    header("Location: /my-diary/?template=entries.html");
    exit();
}

There is the PHP Code of the index.php file! That turned the page! Now we are Whitebox testing instead of black box! We have the sources and therefore the logic. Let’s have a look on it and understand whats happening here.

The index.php file takes the template URI parameter and applies some checks to it. The checks are chained! That means its doing check one, check two, check three. This is very important to understand!

Check 1 - Remove not allowed characters based on a regular expression. So allowed characters are a-z A-Z 0-9 and a dot-symbol. Check 2 - replace admin.php in the template string with “” Check 3 - replace secretadmin.php in the template string with “” Check 4 - after all check if the file name stored in $page exists send it if not redirect to to /my-diary/?template=entries.html

So first of all, thats why the include of index.php worked. Lets walk through the logic one more time with index.php as template name.

Check 1 - No invalid character OK - $page = index.php Check 2 - remove admin.php from index.php OK - $page = index.php Check 3 - remove secretadmin.php from index.php OK - $page = index.php Check 4 - file index.php exists? OK

Okay now lets do the same with secretadmin.php as the Grinch renamed admin.php to secretadmin.php.

Check 1 - No invalid character OK - $page = secretadmin.php Check 2 - remove admin.php from secretadmin.php OK - $page = secret Check 3 - remove secretadmin.php from index.php OK - $page = secret Check 4 - file secret exists? Not-OK - Redirect.

Okay so that means we need to find a way the PHP script can safely remove admin.php as well as secretadmin.php ad the value of $page will still be secretadmin.php.

Check 1 - No invalid character OK - $page = secretadminsecretadminadmin.php.php.php Check 2 - remove admin.php from secretadminsecretadminadmin.php.php.php OK - $page = secretadminsecretadmin.php.php Check 3 - remove secretadmin.php from secretadminsecretadmin.php.php OK - $page = secretadmin.php Check 4 - file secretadmin.php exists? OK

https://hackyholidays.h1ctf.com/my-diary/index.php?template=secretadminsecretadminadmin.php.php.php

Flag6 1

So what do we learned from that challenge? In case we have source code read and understand the source code. Use tools like php -a on your system to test expressions and results like preg_replace('/([^a-zA-Z0-9.])/','','teststring'). This is very powerful. There was no need of any hacking-tool at all to solve this challenge. Using tools like dirb or ffuf for this challenge let other hackers stuck for hours on this one. So be smart and find the vulnerability first before using any other tools!

That was fun! Let’s see what Challenge 7 is about.