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
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
Now we can go inside and find the flag and the end…