php反序列化
程序开发:面向过程&面向对象
面向过程
面向过程是一种以“整体事件”为中心的编程思想,编程的时候把解
决问题的步骤分析出来,然后用函数把这些步骤实现,在一步一步
的具体步骤中再按顺序调用函数。
面向对象
面向对象是一种以“对象”为中心的编程思想,把要解决的问题分解
成各个“对象”;
对象是一个由信息及对信息进行处理的描述所组成的整体,是对现
实世界的抽象。
对象的三个特征:对象的行为,对象的形态,对象的表示
类的定义

类的结构
类:定义类名、定义成员变量(属性)、定义成员函数(方法)
1 class Class_Name{
2 //成员变量声明
3 //成员函数声明
4 }
类的内容
1 class hero{ 定义类(类名){
2 var $name; //声明成员变量
3 var $sex; var为一种修饰符
4 function jineng($var1){ //声明成员函数(方法)
5 echo $this->name; 使用预定义$this调用成员变量
6 echo $var1; 成员函数传参$var1可直接调用
7 }
8 }




1.反序列化之后的内容为一个对象;
2.反序列化生成的对象里的值,由反序列化里的值提供;与原有类预定义的值无关;
3.反序列化不触发类的成员方法;需要调用方法后才能触发;
反序列化的作用
将序列化后的参数还原成实例化的对象。
魔术方法
什么是魔术方法
一个预定义好的,在特定情况下自动触发的行为方法。
魔术方法的作用
反序列化漏洞的成因:反序列化过程中,unserialize()接收的值(字符串)可控;
通过更改这个值(字符串),得到所需要的代码;
通过调用方法,触发代码执行。
魔术方法在特定条件下自动调用相关方法,最终导致触发代码。
_construct()
构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法;
实例化对象时触发构造函数construct()
触发时机:实例化对象
功能:提前清理不必要内容
参数:非必要
返回值:
__destruct()
析构函数,在对象的所有引用被删除或者当对象被显式销毁时执行的魔术方法。
实例化对象结束后,代码运行完会销毁,触发析构函数destruct()
在序列化过程中不会触发,
在反序列化过程中会触发;
反序列化得到的是对象,用完后会销毁,触发析构函数destruct()
触发时机:对象引用完成,
或对象被销毁
功能
参数:
返回值:
__sleep()
序列化serialize()函数会检查类中是否存在一个魔术方法sleep(0。
如果存在,该方法会先被调用,然后才执行序列化操作。
此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。
如果该方法未返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误。
触发时机:序列化serialize()之前
功能:对象被序列化之前触发,返回需要被序列化存储的成员属性,删除不必要的属性。
参数:成员属性
返回值:需要被序列化存储的成员属性

__wakeup()
unserialize()会检查是否存在一个wakeup()方法。如果存在,则会先调用、
wakeup()方法,预先准备对象需要的资源。
预先准备对象资源,返回od,常用于反序列化操作中重新建立数据库连接或执行其他初始化操作。
触发时机:反序列化unserialize()之前
功能:
参数:
返回值:
_wakeup(0在反序列化unserialize()之前
destruct(()在反序列化unserialize()之后
__toString()
表达方式错误导致魔术方法触发
常用于pop链构造
触发时机:把对象被当成字符串调用
功能:
参数:
返回值:
调用对象可以使用print_r或者var_dump
如果使用echo或者print.只能调用字符串的方式去调用对象
即把对象当成字符串使用,此时自动触发toString()

__invoke()
格式表达错误导致魔术方法触发
触发时机:把对象当成函数调用
功能:
参数:
返回值:

__call()
[触发时机:调用一个不存在的方法
功能:
参数:2个参数传参$arg1,$arg2
返回值:调用的不存在的方法的名称和参数]()
$arg1,调用的不存在的方法的名称,
$arg2,调用的不存在的方法的参数,

callStatic()
触发时机:静态调用或调用成员常量时使用
的方法不存在
功能:
参数:2个参数传参Sarg1,5arg2
返回值:调用的不存在的方法的名称和参数

get()
触发时机:调用的成员属性不存在
功能
参数:传参Sarg1
返回值:不存在的成员属性的名称

set()
触发时机:给不存在的成员属性赋值
功能
参数:传参$arg1,$arg2
返回值:不存在的成员属性的名称和赋的值

isset()
触发时机:对不可访问属性使用isset()或empty()时,_isset()会被调用。
功能:
参数:传参$arg1
返回值:不存在的成员属性的名称

unset()
触发时机:对不可访问属性使用unset()时
功能:
参数:传参$arg1
返回值:不存在的成员属性的名称

clone()
触发时机:当使用clone关键字拷贝完成一个对象后,新对象会自动调用定义的魔术方法clone()
功能
参数:
返回值:



魔术方法触发前提:魔术方法所在类(或对象)被调用
POP链
在反序列化中,我们能控制的数据就是对象中的属性值(成员变量)所以在PHP反序列化中有一种漏洞利用方法叫"面向属性编程",即POP(Property Oriented Programming).
POP链就是利用魔法方法在里面进行多次跳转然后获取敏感数据的一种payload。
POC编写
POC(全称:Proof of concept)中文译作慨念验证。在安全界可以理解成漏洞验证程序。PoC是一段不完整的程序,仅仅是为了证明提出者的观点的一段代码。
字符串逃逸基础
反序列化分隔符
反序列化以;}结束,后面的字符串不影响正常的反序列化
属性逃逸
一般在数据先经过一次serialize再经过unserialize,在这个中间反序列化的字符串变多或者变少的时候有可能存在反序列化属性逃逸。
"是字符还是格式符号,是由字符串长度来判断的
在前面字符串没有问题的情况下,;}是反序列化结束符后面的字符串不影响反序列化结果
成员属性数量一致,成员属性名称长度一致,内容长度一致

反序列化字符串减少逃逸:多逃逸出一个成员属性第一个字符串减少,吃掉有效代码,在第二个字符串构造代码

反序列化字符串增多逃逸:构造出一个逃逸成员属性第一个字符串增多,吐出多余代码,把多余位代码构造成逃逸的成员属性
反序列化漏洞
CVE-2016-7124(PHP5<5.6.25;PHP7<7.0.10)
漏洞产生原因
如果存在wakeup方法,调用unserilize()方法前则先调用wakeup方法,但是序列化字符串中表示对象属性个数的值大于真实的属性个数时,会跳过wakeup()的执行
序列化引用
构造序列化字符串,让$enter的值引用$secret的值


session反序列化漏洞
当session start()被调用或者php.ini中session.auto start为1时PHP内部调用会话管理器,访问用户session被序列化以后,存储到指定目录(默认为/tmp)。
存取数据的格式有多种,常用的有三种
漏洞产生:写入格式和读取格式不一致
存储数据的常用三种格式
| 处理器 | 对应的储存格式 |
|---|---|
php |
键名+竖线+经过serialize()函数序列化处理的值 |
php_seialize(php>=5.54) |
经过serialize()函数序列化处理的数组 |
php_binary |
键名的长度对应的ASCII字符+键名+经过serialize()函数反序列处理的值 |
PHP session反序列化漏洞
当网站序列化并存储Session,与反序列化并读取Session的方式不同,就可能导致session反序列化漏洞的产生。
phar反序列化漏洞
JAR是开发Java程序一个应用,包括所有的可执行、可访问的文件,都打包进了一个JAR文件里,使得部署过程十分简单。而PHAR("Php ARchive")是PHP里类似于JAR的一种打包文件。对于PHP5.3或更高版本,Phar后缀文件是默认开启支持的,可以直接使用它。

phar结构
stub phar文件标识,格式为Xxx<?php xxx;HALT_COMPiLER0;?>;(头部信息)
manifest压缩文件的属性等信息,以序列化存储;
contents压缩文件的内容;
signature签名,放在文件末尾;
Phar协议解析文件时,会自动触发对manifest字段的序列化字符串进行反序列化



浙公网安备 33010602011771号