0x01 魔法方法
魔法方法,是一种特殊的方法,如果定义了,它会在调用一些方法之前自动运行。在很多语言中都有魔法方法,例如,在php中,如果在一个类中定义了__construct方法,在这个类初始化时,它会被自动调用。__sleep()方法会在serialize()方法调用之前调用,__wakeup方法会在调用unserialize()方法之前调用,这些都是php自行规定的,开发者必须使用规定的方法名,才能触发魔法方法的自动运行。在Python中,魔法方法更加常见,例如__init__方法等。
0x02 序列化与反序列化
序列化是指把面向对象的对象变成二进制的能持续存储的文件。反序列化则是相反,将二进制的文件转换成对象,使他活起来。序列化与反序列化一般成对的,例如,在Python中有好几种序列化和反序列化方法,pickle定义了一对,使用pickle序列化后的必需使用pickle反序列化。php中,可以直接使用serialize()和unserialize()方法来序列化和反序列化。因为下面要说的漏洞是关于php的,下面详细说一下php的序列化和反序列化
运行结果如下:
可见,在类的实例序列化以后,只会将变量名字类型以及值保存下来,并不会保存类的方法。反序列化函数能把上述的字符串转换回原来的对象。
0x03 反序列化漏洞
如果unserialize()函数的参数可控,那么我们就可以控制反序列化后对象中变量的值,如果原来代码中有一些危险的方法,我们可以直接调用。虽然利用条件略微苛刻,但是实际中漏洞还是很多。
0x04 CVE-2016-7124
这是PHP的一个漏洞,利用环境是PHP5 < 5.6.25 ,PHP7 < 7.0.10。简单来说,就是当序列化字符串中表示对象中属性个数的数字大于真实个数时,就会跳过__wakeup()函数的执行。例子可以参见2016 SWPU CTF中的Web3题