目录
Ⅰ、PHP反序列化漏洞
一、序列化函数
反序列化漏洞是基于序列化和反序列化的操作,在反序列化——unserialize()时存在用户可控参数,而反序列化会自动调用一些魔术方法,如果魔术方法内存在一些敏感操作例如eval()函数,而且参数是通过反序列化产生的,那么用户就可以通过改变参数来执行敏感操作,这就是反序列化漏洞。
php 将数据序列化和反序列化会用到两个函数:(serializ:将对象格式化成有序的字符串-----
unserialize:将字符串还原成原来的对象)
二、序列化的目的
序列化的目的是方便数据的传输和存储,在 PHP 中,序列化和反序列化一般用做缓存,比如 session 缓存,cookie 等。
三、序列化的四种格式(了解即可)
- 二进制格式
- 字节数组
- json 字符串
- xml 字符串
四、常见的魔术方法
__construct()//名为构造函数,会在创建对象时调用一次
__destruct() //对象被销毁时触发
__wakeup() //执行 unserialize()时,先会调用这个函数
__sleep() //执行 serialize()时,先会调用这个函数
__get() :读取不可访问(protected 或 private)或不存在的属性的值时调用这个函数(比如类中没有b这个属性)
__set():在给不可访问(protected 或 private)或不存在的属性赋值时(不常用)
__call() : 在对象中调用一个不可访问或不存在的方法时,__call()会被调用
__callStatic() : 在静态上下文中调用一个不可访问或不存在的方法时,__callStatic会被调用(不常用)。
其实说白了和前面的__get()魔术方法类似,__get()是对变量而言,__call()是对函数而言
__toString() //把类当作字符串使用时触发
__invoke() //当尝试将对象调用为函数时触发
不常见:ctf不常见的魔术方法
__isset():当对不可访问属性调用isset()或empty()时调用
__unset():当对不可访问属性调用unset()时被调用。
__set_state():调用var_export()导出类时,此静态方法会被调用。
__clone():当对象复制完成时调用
魔术方法用法(在序列化、反序列化函数执行时会调用的方法)
- sleep()#serialize() 函数执行时会检查类中是否存在一个魔术方法 sleep()。如果存在,sleep()方法会先被调用,然后才执行序列化操作。可以在 sleep()方法里决定哪些属性可以被序列化。如果没有 sleep()方法则默认序列化所有属性。
- wakeup()#与序列化函数类似,unserialize()函数执行时会检查类中是否存在一个 wakeup 魔术方法如果存在则会先调用 wakeup()方法,再进行序列化。可以在 wakeup()方法中对属性进行初始化、赋值或者改变。
五、访问控制修饰符(了解即可)
根据访问控制修饰符的不同 序列化后的 属性长度和属性名的值会有所不同
public(公有)
protected(受保护) // %00*%00 属性名
private(私有的) // %00 类名%00 属性名
protected 属性被序列化的时候属性值会变成 %00*%00属性名
private 属性被序列化的时候属性值会变成 %00 类名%00属性名(%00 为空白符,空字符也有长度,一个空字符长度为 1)
六、反序列化漏洞的出现
- unserialize函数参数可控,比如通过GET传参。
- 用了magic魔术方法,比如dustruct、unlink函数
- 对象得有成员变量
七、利用
先把类给定义,之后再序列化一下,之后再对序列化后的内容进行修改,再进行利用。
八、防御
- 升级到最新版本
- 安装防火墙
Ⅱ、常见的反序列化框架漏洞
一、Apache shiro反序列化漏洞
略,
Ⅲ、CTF题目
一、类型
- PHP反序列化之POP链
- PHP反序列化之正则绕过
- PHP反序列化之字符串逃逸
- PHP反序列化之phar与条件间竞争