updated:

PHP反序列化漏洞


一.序列化一个对象

使用函数serialize()来序列化一个对象时,该函数的返回值是一个包含字节流的字符串,以下面的代码为例:

用浏览器打开seria.php,结果如下:

可以看到,序列化函数的返回值是一个字符串,这个字符串包含了类名,和类中变量的值和属性。值得注意的是,序列化后的对象中不包含类的方法,因此对象被解序列化时需要提供类的定义,而这也正是在两个php文件中都包含了含有类A的定义的classa.inc的原因。

可以看到,这里的对象解序列化后依然拥有类中的方法

如果对象在解序列化时没有找到类的定义,那么这个对象的类就变成了__PHP_Incomplete_Class_Name,即一个没有方法的类,这时这个对象就没有用了。

二.序列化与反序列化中的魔术方法

研究一下代码:

"; } public function \_\_destruct() { echo "destructing...
"; } public function \_\_toString() { echo "It is transformed to string.
"; return " \_\_toString Done.
"; } /\* public function \_\_wakeup() { echo "Waking up...
"; } public function \_\_sleep() { echo "Sleeping...
"; return array(); } \*/ } $magic = new MagicWays(); $magic->

ini = 1; \(s = serialize(\)magic); var_dump($s); \(back = unserialize(\)s); var_dump(\(back); echo "</br>this is ".\)back;

运行结果如下:

从运行结果可以很简单的看出各个魔术方法的作用,应该注意两点:

1.序列化并没有像以前那样起到作用,这是因为我们修改了__sleep()和__wakeup()函数的内容,导致对象中的变量在序列化时并没有被提交。将这两个函数注释掉后可以看到输出恢复了正常。

2.输出的结尾有两个destructing...,这是因为序列化与反序列化起到的是在对象之间传递数据的作用。将反序列化后的变量s赋值给back的过程就相当于又根据类MagicWays创建了一个对象,只是这个对象中的变量初始值与magic相同。

三.反序列化漏洞

我们用几道ctftimu来熟悉序列化和反序列化

1.BugkuCTF flag.php

网站点进去之后果然login没有任何反应,根据提示URL传参?hint=得到源代码

只需要发送一个带cookies的get请求即可,其中ISecer的值为\(KEY序列化后的值,即s:0:"";。(注意这里\)KEY外面是双引号,表示引用变量,如果是单引号则单纯表示字符串。)

1
payload:curl --cookie 'ISecer=s%3A0%3A%22%22%3B' 123.206.87.240:8002/flagphp/

2.攻防世界 Web_php_unserialize

我们可以看到,为了得到flag,需要输出fl4g.php的内容,而这又需要确保变量file的内容是fl4g.php。

首先,我们需要创建一个Demo类的对象,这个并不难,已知$var要被反序列化,因此运行下面的代码,保证var的内容是文件output中的内容即可

1
O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}

再通过base64加密

1
file_put_contents('result', base64_encode(file_get_contents('input')));

传参得到flag。


← Prev ADWorldCTF-Web(4) | 浮点数的机器级表示 Next →