反序列化漏洞
0x00 序列化
序列化(seralize)是指将对象的状态信息转化为可存储和传输的字符串形式,并保存在存储区中,当以后需要这个对象时,可以通过序列化的字符串来恢复这个对象的状态信息。
可以简单理解为将 对象、类、数组、变量、匿名函数等信息转换成字符串形式,便于存储。
通过以下代码展示了一个序列化的过程:
1 | <?php |
运行结果:
0x01 反序列化漏洞
在序列化的基础上,将字符串信息恢复成状态信息的过程称为反序列化(uniseralize)。
反序列化漏洞是指在反序列化的过程中,反序列化的内容可以被控制,因此构造payload,调用魔术函数等,造成攻击的一种漏洞。
0x02 靶场复现
以一道CTF题为例
第1行说明了flag在同目录下的flag.php中,因此方向是利用反序列化漏洞读取flag.php的内容。
第4行定义了一个类readme,定义了一个方法 __toString()
当打印一个对象时,如果定义了__toString()方法,就能在测试时,通过echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。
第10行如果GET传参包含 source 就会代码高亮显示Readme.txt和本身,因此可以分析出Readme.txt的内容是第1行的 flag in ./flag.php,剩下的部分就是index.php的源码
第16行提示todos是一个数组
第17行判断如果Cookie中存在todos,首先将todos赋值给变量c,然后取变量c的前32位和32位以后的内容进行对比,如果32位以后内容的md5加密结果与前32位相等,那么就对32位以后的内容进行反序列化,并赋值给todos
第42、43行对todos的内容调用foreach进行输出,直接输出则会调用 __toString()方法,格式化输出todos这个对象所包含的内容。
因此只需用使todos反序列化后的内容为 ./flag.php ,就能看到flag.php的内容
根据题目,构造以下代码获取payload:
1 | <?php |
运行结果:
将这一串值url编码后添加到Cookie中(Cookie传参需要URL编码)
0x03 防御措施
避免反序列化内容可控,检查魔术函数的触发