0x01 什么是序列化?什么是反序列化?
序列化是将对象转换为字符串以便存储传输的一种方式。而反序列化恰好就是序列化的逆过程,反序列化会将字符串转换为对象供程序使用。在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。
|
|
0x02 那这个序列化跟反序列化到底怎么利用?
首先得科普一下,在php对象当中,有一类方法被称为魔术方法。这类方法以__
开头,在操作对象的某些过程中,这些方法会被自动执行。而反序列化漏洞利用思路,便是跟这个魔术方法有关。当对字符串进行unserialize
操作时,会自动调用对象中的wakeup
方法,这就让我们有了可乘之机。
|
|
我们在之前代码的Hello对象当中添加了一个__wakeup()
方法,里面调用了phpinfo()
输出服务器中php的相关信息。当我们反序列化$s
这个变量时,phpinfo()
被执行了。
0x03 可是说了一大堆,__wakeup()又不是你写的,该怎么利用呢?
这个时候我们就要跟踪函数,观察函数当中有没有作为用户可控的部分,进而进行注入。这里就拿我最近做的一个ctf题来举例。
首先,题目的主页是一个留言墙,我们可以随意在上面输入想要的值。
其次,题目给了我部分源码:
|
|
这里不需要去管highlightFile
这个函数,我们需要关注的是,这个__toString
中的source
是我们可以控制的。
这个时候我们打开php手册查找__toString
这个方法,发现如果echo
某个该对象的实例,则会返回__toString
返回的值。
因此,可以精心构造一下序列
|
|
为什么要让$b->source=$a
呢,因为如果$b
的source
是一个字符串,那么就不会触发__toString()
方法。而当指向$a
时,则会试图通__toString()
打开source
,最后通过这个序列成功读取服务器上的隐藏文件。