PHP反序列化

PHP反序列化
EZL1NGPHP反序列化
序列化与反序列化
序列化:对象转换为数组或字符串等格式
反序列化:将数组或字符串等格式转换成对象
- serialize () // 将对象转换成一个字符串
- unserialize () // 将字符串还原成一个对象
PHP对象转换为字符串格式
魔术方法
1 |
|
第一组
- __construct (): // 当对象 new 的时候会自动调用,类似构造函数
- __destruct ():// 当对象被销毁时会被自动调用,包含主动销毁 (即手动销毁对象) 和被动销毁 (即程序运行结束),类似析构函数
第二组
- __sleep (): //serialize () 执行时被自动调用
- __wakeup (): //unserialize () 时会被自动调用
其他
- __invoke (): // 当尝试以调用函数的方法调用一个对象时会被自动调用
- __toString (): // 把类当作字符串使用时触发
- call (): // 调用某个方法,若方法存在,则调用;若不存在,则会去调用call 函数。
- get (): // 读取对象属性时,若存在,则返回属性值;若不存在,则会调用get 函数
- set (): // 设置对象的属性时,若属性存在,则赋值;若不存在,则调用set 函数。
- __isset (): // 在不可访问的属性上调用 isset () 或 empty () 触发
- __unset (): // 在不可访问的属性上使用 unset () 时触发
代码中未测试的函数
- __callStatic (): // 在静态上下文中调用不可访问的方法时触发
- __set_state (),调用 var_export () 导出类时,此静态方法会被调用
- __clone (),当对象复制完成时调用
- __autoload (),尝试加载未定义的类
- __debugInfo (),打印所需调试信息
反序列化漏洞产生
原理
- 未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL 注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
实例
1 |
|
利用
1 | //POP链构造 |
POP 链构造
什么是POP
- POP:面向属性编程(Property-Oriented Programing)常用于上层语言构造特定调用链的方法,序列化攻击都在 PHP 魔术方法中出现可利用的漏洞,因自动调用触发漏洞,但如关键代码没在魔术方法中,而是在一个类的普通方法中。这时候就可以通过构造 POP 链寻找相同的函数名将类的属性和敏感函数的属性联系起来。
反序列化常见起点
| 方法名 | 调用条件 |
|---|---|
| __wakeup | 一定会调用 |
| __destruct | 一定会调用 |
| __toString | 当一个对象被反序列化后又被当做字符串使用 |
反序列化常见跳板
| 方法名 | 调用条件 |
|---|---|
| __toString | 当一个对象被当作字符串使用 |
| __get | 读取不可访问或不存在属性时被调用 |
| __set | 当给不可访问或不存在属性赋值时被调用 |
| __isset | 对不可访问或不存在的属性调用isset()或empty()是被调用 |
反序列化常见终点
| 方法名 | 调用条件 |
|---|---|
| __call | 调用不可访问或不存在的方法时被调用 |
| call_user_func | 一般php代码执行都会选择这里 |
| call_user_func_array | 一般php代码执行都会选择这里 |
示例详见CTFshow
web254
web255
web256
web257
属性类型
对象变量属性
public(公共的):在本类内部、外部类、子类都可以访问
protect(受保护的):只有本类或子类或父类中可以访问
private(私人的):只有本类内部可以使用
序列化数据显示
public属性序列化的时候格式是正常成员名
private属性序列化的时候格式是%00类名%00成员名
protect属性序列化的时候格式是%00*%00成员名
示例
1 |
|
protect 修饰的属性
父类自己访问受保护属性:类内设置接口,类外创建对象访问接口从而访问属性
1 |
|
子类访问父类的受保护属性:子类内设置接口,类外子类创建对象访问接口从而访问属性
1 | class ParentClass { |
类外访问父类的受保护属性
1 | class ParentClass { |
类内访问就是在类内的方法访问,类外访问就是创建对象调用属性的方式
private 修饰的属性
父类访问自己的私有属性:类内设置接口,类外创建对象访问接口从而访问属性
1 | class ParentClass { |
子类无法直接访问父类的私有属性:子类内设置接口,类外子类创建对象也不能访问接口从而访问属性
1 | class ParentClass { |
类外无法直接访问父类的私有属性
1 | class ParentClass { |
protect 修饰的方法
父类自己访问受保护方法:类内设置接口,类外创建对象访问接口从而访问方法
1 | class ParentClass { |
子类访问父类的受保护方法:子类内设置接口,类外子类创建对象访问接口从而访问方法
1 | class ParentClass { |
类外无法直接访问父类的受保护方法:
1 | class ParentClass { |
private 修饰的方法
父类访问自己的私有方法:类内设置接口,类外创建对象访问接口调用方法
1 | class ParentClass { |
子类无法直接访问父类的私有方法
1 | class ParentClass { |
类外无法直接访问父类的私有方法
1 | class ParentClass { |
总结
概念约定:
- 什么是类内访问:通过类内的方法访问属性/方法。
- 什么是类外访问:类外创建对象,直接访问属性/方法
protect 访问权限:只有子类,父类自己可以类内访问到,类外不行
- protect 修饰的属性:类内设置访问属性的接口(public),类外的子类,本类创建对象调用接口从而访问属性
- protect 修饰的方法:类内设置访问属性的接口(public),类外的子类,本类创建对象调用接口从而调用方法
private 访问权限:只有父类自己可以类内访问,类外不行
- private 修饰的属性:类内设置接口,只有本类自己可以通过创建对象访问类内接口从而访问私有属性
- private 修饰的方法:类内设置接口,只有本类自己可以通过创建对象访问类内接口从而访问类内私有方法
示例
CVE-2016-7124(wakeup:unserialize()时会被自动调用)
漏洞编号:CVE-2016-7124
影响版本:PHP 5<5.6.25; PHP 7<7.0.10
漏洞危害:如存在wakeup方法,调用unserilize()方法前则先调用wakeup方法,但序列化字符串中表示对象属性个数的值大于真实属性个数时会跳过wakeup执行
极客大挑战 2019
1、下载源码分析,触发flag条件
2、分析会触发调用__wakeup 强制username值
3、利用语言漏洞绕过 CVE-2016-7124
4、构造payload后 修改满足漏洞条件触发
字符串逃逸
两种场景:
字符增多型
通过构造特殊字符串使序列化结构逃逸1
2// 原代码过滤机制:将'x'替换为'xx'
// 构造payload使s:5:"value"被篡改字符减少型
利用过滤机制缩短字符串长度
利用公式:
1 | 原结构:...s:10:"payload";... |
详见:
PHP反序列化——字符逃逸漏洞(肯定能看懂的!)_php {i:1;s:65:’’}-CSDN博客
反序列化链项目
NotSoSecure(综合类)
项目地址:https://github.com/NotSoSecure/SerializedPayloadGenerator
为了利用反序列化漏洞,需要设置不同的工具,如 YSoSerial(Java)、YSoSerial.NET、PHPGGC 和它的先决条件。DeserializationHelper 是包含对 YSoSerial(Java)、YSoSerial.Net、PHPGGC 和其他工具的支持的Web界面。使用Web界面,您可以为各种框架生成反序列化payload.
Java – YSoSerial
NET – YSoSerial.NET
PHP – PHPGGC
Python - 原生
PHPGGC(单项类)
项目地址:https://github.com/ambionics/phpggc
PHPGGC是一个包含unserialize()有效载荷的库以及一个从命令行或以编程方式生成它们的工具。当在您没有代码的网站上遇到反序列化时,或者只是在尝试构建漏洞时,此工具允许您生成有效负载,而无需执行查找小工具并将它们组合的繁琐步骤。 它可以看作是frohoff的ysoserial的等价物,但是对于PHP。目前该工具支持的小工具链包括:CodeIgniter4、Doctrine、Drupal7、Guzzle、Laravel、Magento、Monolog、Phalcon、Podio、ThinkPHP、Slim、SwiftMailer、Symfony、Wordpress、Yii和ZendFramework等。
使用方法:
从0到1掌握反序列化工具之PHPGGC_phpggc安装方法-CSDN博客
示例
[安洵杯 2019]iamthinking Thinkphp V6.0.X 反序列化
CTFSHOW 反序列化 267 Yii2反序列化
CTFSHOW 反序列化 271 Laravel反序列化












