反序列化
序列化与反序列化
基本内容
目的:解决 PHP 对象传递的问题,方便数据的传输与储存
因为 PHP 文件在执行结束以后就会将对象销毁,那么如果下次有一个页面恰好要用到刚刚销毁的对象就会束手无策,总不能你永远不让它销毁,等着你吧,于是人们就想出了一种能长久保存对象的方法,这就是 PHP 的序列化,那当我们下次要用的时候只要反序列化一下就 ok 啦
魔术方法
魔术方法的调用是自动进行的,不需要人工干预
因此只要魔法方法中出现了一些我们能利用的函数,我们就能通过反序列化中对其对象属性的操控来实现对这些函数的操控,进而达到我们发动攻击的目的。
1 | __construct() //创建对象时自动调用 |
调用(清晰可见!!!):
先创建新对象,调用__construct()
执行unserialize()时调用__wakeup()
反序列化之后调用__destruct()
1
2
3//但当程序抛出异常时,destruct方法不会执行,也就无法实现文件的写入:
unserialize($_GET[0]);
throw new Error("那么就从这里开始起航吧");程序结束时调用__destruct()
1 | 其他一些魔术方法调用举例: |
属性
类中变量一样的东西(不负责任的讲)
例如
1 | class K0rz3n { |
test、K0rz3n就是K0rz3n
类中的属性
private-私有变量
private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上\0的前缀。字符串长度也包括所加前缀的长度。其中 \0 字符也是计算长度的。
对于private变量,我们需要在类名和字段名前面加上\0的前缀(指 ASCII码为0的空字符)
但注意:python传入加 \0 ,浏览器直接传入加 %00(十六进制)
protected
序列化后需在类名和字段名前面加上%00*%00
攻击
攻击前提:
- 必须有 unserailize() 函数
- unserailize() 函数的参数必须可控(可能需要绕过一些魔法函数)
攻击思路:
首先,当前作用域中的类是我们能够用的,类中的魔术方法能够让我们调用类中的其他方法(function),所以反序列化对象的选取应该找这样的类。
之后,我们说反序列化攻击依托的是类的属性,关键属性自然是在魔术方法中用到的那些,属性的内容我们需要结合魔术方法中的描述进行思考,最终形成payload
其实这整个过程就像是在走迷宫,路径是一条线,线的两端点分别是unserailize() 和我们要获取的信息(flag),中间路上需要动力驱使我们行走,动力就是魔术方法(自动进行)。就是一点一点地调用,形成一条链串起来整个思路。
攻击步骤:
确定反序列化攻击可行性
寻找反序列化对象(目标),重点在有
__destruct()、__wakeup()
魔术方法的类寻找对象所属类中的重点攻击属性(一层一层地研究)
构造属性内容
单纯赋值(类里面/创建对象后)
file_put_content()函数
1
2
3$K0rz3n = new K0rz3n;
$data = serialize($K0rz3n);
file_put_contents("seria.txt"内容, $data序列化变量?);
4.注意补上%00…
注意:
- 反序列化时必须保证当前的作用域环境下有该类的存在
- 反序列化攻击是依托类的属性进行攻击
高级学习
POP链
面向属性编程,个人感觉是一种思路链
比如
1 | writer->shutdown()->render()->filter()->preg_replace(我们控制的属性)->代码执行 |
这就是一个POP链
phar反序列化
phar文件本质上是一种压缩文件,会以序列化的形式储存在meta-data里,在文件系统函数(file_exists()、is_dir()等)参数可控的情况下,配合phar://伪协议,可以不依赖unserialize()直接进行反序列化操作。
攻击条件:
不再局限于传统反序列化攻击条件(unserialize+参数可控),phar://拓展了php反序列化攻击面,降低了攻击起点
1 | 1、phar文件要能够上传到服务器端。 |
phar文件结构
stub
必须以
__HALT_COMPILER();?>
来结尾manifest
contents
signature
使用:
举例
1 |
|
1 |
|
执行输出结果
绕过
php识别phar文件是通过文件头的stub中的__HALT_COMPILER();?>
,对前面的内容和后缀名没有要求
所以我们就可以 添加任意文件文件头+修改成响应文件的后缀名 以绕过检查
1 | $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); |
其他
- $this指当前所在的class变量
- 序列化如果有private和protected属性注意补全空的字符串
- 序列化对象首字母代表参数类型
O:Objext S:String...
参考:反序列化初级介绍
- Title: 反序列化
- Author: dawn_r1sing
- Created at : 2023-11-16 22:43:15
- Updated at : 2023-11-16 22:52:43
- Link: https://dawnrisingdong.github.io/2023/11/16/反序列化/
- License: This work is licensed under CC BY-NC-SA 4.0.