启动机器,给的IP和端口为143.110.169.131:32543

直接浏览器打开。

image-20230716163655704

这个机器给了源码,下载下来看看

源码的结构为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.
├── assets
│   ├── cyberpunk.gif
│   └── favicon.png
├── controllers
│   └── TimeController.php
├── index.php
├── models
│   └── TimeModel.php
├── Router.php
├── static
│   ├── css
│   │   └── main.css
│   ├── js
│   │   ├── koulis.js
│   │   └── main.js
│   └── koulis.gif
└── views
└── index.php

index.php中调用了Router,通过Router中的new函数构造TimeController中的index函数。

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

TimeController.php代码如下

1
2
3
4
5
6
7
8
9
10
<?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()]);
}
}

通过get请求接受format参数,并赋值给$format。如果获取不成功则默认赋值字符”r”。

然后传递给TimeModel。

TimeModel.php代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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';
}
}

查看TimeModel.php的代码,对传入的$format使用addslashes进行转义。随后拼接到eval函数中。所以这里形成了一条污点流,source是$_GET[‘format’],sink是eval。

但是由于addslashes会转义双引号,因此无法直接闭合eval中的双引号,这里要想办法绕过。