PHP反序列化漏洞简介及相关技巧小结

要学习PHP反序列漏洞,先了解下PHP序列化和反序列化是什么东西。

php程序为了保存和转储对象,提供了序列化的方法,php序列化是为了在程序运行的过程中对对象进行转储而产生的。序列化可以将对象转换成字符串,但仅保留对象里的成员变量,不保留函数方法。

php序列化的函数为serialize。反序列化的函数为unserialize。

序列化

举个栗子:

?phpclassTest{public$a=ThisA;protected$b=ThisB;private$c=ThisC;publicfunctiontest1(){returnthisistest1;}}$test=newTest();var_dump(serialize($test));?

输出:

解释一下:

O代表是对象;:4表示改对象名称有4个字符;:”Test”表示改对象的名称;:3表示改对象里有3个成员。

接着是括号里面的。我们这个类的三个成员变量由于变量前的修饰不同,在序列化出来后显示的也不同。

第一个变量a序列化后为s:1:”a”;s:5:”ThisA”;

由于变量是有变量名和值的。所以序列化需要把这两个都进行转换。序列化后的字符串以分号分割每一个变量的特性。

这个要根据分号来分开看,分号左边的是变量名,分号右边的是变量的值。

先看左边的。其实都是同理的。s表示是字符串,1表示该字符串中只有一个字符,”a”表示该字符串为a。右边的同理可得。

第二个变量和第一个变量有所不同,多了个乱码和号。这是因为第一个变量a是public属性,而第二个变量b是protected属性,php为了区别这些属性所以进行了一些修饰。这个乱码查了下资料,其实是%00(url编码,hex也就是0x00)。表示的是NULL。所以protected属性的表示方式是在变量名前加个%00%00

第三个变量的属性是private。表示方式是在变量名前加上%00类名%00

可以看到虽然Test类中有test1这个方法,但是序列化后的字符串中并没有包含这个方法的信息。所以序列化不保存方法。

反序列化

?phpclassTest{public$a=ThisA;protected$b=ThisB;private$c=ThisC;publicfunctiontest1(){returnthisistest1;}}$test=newTest();$sTest=serialize($test);$usTest=unserialize($sTest);var_dump($usTest);?

输出:

可以看到类的成员变量被还原了,但是类方法没有被还原,因为序列化的时候就没保存方法。

魔术方法

大概了解了php序列化和序列化的过程,那么就来介绍一下相关的魔术方法。

__construct当一个对象创建时被调用

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

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

__sleep在对象被序列化之前运行

__wakeup在对象被反序列化之后被调用

直接举栗子吧:

?phpclassTest{publicfunction__construct(){echoconstructrun;}publicfunction__destruct(){echodestructrun;}publicfunction__toString(){echotoStringrun;}publicfunction__sleep(){echosleeprun;}publicfunction__wakeup(){echowakeuprun;}}/**/echonew了一个对象,对象被创建,执行__construct/br;$test=newTest();/**/echo/brserialize了一个对象,对象被序列化,先执行__sleep,再序列化/br;$sTest=serialize($test);/**/echo/brunserialize了一个序列化字符串,对象被反序列化,先反序列化,再执行__wakeup/br;$usTest=unserialize($sTest);/**/echo/br把Test这个对象当做字符串使用了,执行__toString/br;$string=helloclass.$test;/**/echo/br程序运行完毕,对象自动销毁,执行__destruct/br;?

输出:

可以看到有一个警告一个报错,是因为sleep函数期望能return一个数组,而toString函数则必须返回一个字符串。由于我们都是echo的没有写return,所以引发了这些报错,那么我们就按照报错的来,要什么加什么。

输出:

现在只需要明白这5个魔法函数的执行顺序即可,至于里面的代码就要看程序员或者出题人怎么写了。。。对于__construct函数的话我个人认为好像莫有多大用。。也许是我菜吧。。感觉没有什么地方能在反序列化的时候用上。欢迎大佬指点。

一道题目引发的技巧小结

了解了反序列化的基础和一些魔法函数后,我们来看到题吧。该题不仅考了反序列化,还简单考察了一下变量覆盖和命令注入的正则绕过。其中有一些坑我们可以看一下。

该题出处:


转载请注明:http://www.jiaju1314.com/zytd/zytd/14573.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了