php浅析反序列化结构

目录
  • 简介
  • 反序列化中常见的魔术方法
  • 反序列化绕过小Trick
  • 绕过_wakeup(CVE-2016-7124)
  • 绕过部分正则
  • 利用引用
  • 16进制绕过字符的过滤

简介

序列化的目的是方便数据的传输和存储,在PHP中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。

反序列化中常见的魔术方法

  1. __wakeup() //执行unserialize()时,先会调用这个函数
  2. __sleep() //执行serialize()时,先会调用这个函数
  3. __destruct() //对象被销毁时触发
  4. __call() //在对象上下文中调用不可访问的方法时触发
  5. __callStatic() //在静态上下文中调用不可访问的方法时触发
  6. __get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法
  7. __set() //用于将数据写入不可访问的属性
  8. __isset() //在不可访问的属性上调用isset()或empty()触发
  9. __unset() //在不可访问的属性上使用unset()时触发
  10. __toString() //把类当作字符串使用时触发
  11. __invoke() //当尝试将对象调用为函数时触发

反序列化绕过小Trick

php7.1+反序列化对类属性不敏感

我们前面说了如果变量前是protected,序列化结果会在变量名前加上\x00*\x00

但在特定版本7.1以上则对于类属性不敏感,比如下面的例子即使没有\x00*\x00也依然会输出abc

<?php
class test{
    protected $a;
    public function __construct(){
        $this->a = 'abc';
    }
    public function  __destruct(){
        echo $this->a;
    }
}
unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');

绕过_wakeup(CVE-2016-7124)

版本:

​ PHP5 < 5.6.25

​ PHP7 < 7.0.10

利用方式:序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

对于下面这样一个自定义类

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = 'abc';
    }
    public function __wakeup(){
        $this->a='666';
    }
    public function  __destruct(){
        echo $this->a;
    }
}

如果执行unserialize('O:4:"test":1:{s:1:"a";s:3:"abc";}');输出结果为666

而把对象属性个数的值增大执行unserialize('O:4:"test":2:{s:1:"a";s:3:"abc";}');输出结果为abc

绕过部分正则

preg_match('/^O:\d+/')匹配序列化字符串是否是对象字符串开头,这在曾经的CTF中也出过类似的考点

利用加号绕过(注意在url里传参时+要编码为%2B)

serialize(array(a ) ) ; / / a));//a));//a为要反序列化的对象(序列化结果开头是a,不影响作为数组元素的$a的析构)

<?php
class test{
    public $a;
    public function __construct(){
        $this->a = 'abc';
    }
    public function  __destruct(){
        echo $this->a.PHP_EOL;
    }
}
function match($data){
    if (preg_match('/^O:\d+/',$data)){
        die('you lose!');
    }else{
        return $data;
    }
}
$a = 'O:4:"test":1:{s:1:"a";s:3:"abc";}';
// +号绕过
$b = str_replace('O:4','O:+4', $a);
unserialize(match($b));
// serialize(array($a));
unserialize('a:1:{i:0;O:4:"test":1:{s:1:"a";s:3:"abc";}}');

利用引用

<?php
class test{
    public $a;
    public $b;
    public function __construct(){
        $this->a = 'abc';
        $this->b= &$this->a;
    }
    public function  __destruct(){

        if($this->a===$this->b){
            echo 666;
        }
    }
}
$a = serialize(new test());

上面这个例子将$b设置为$a的引用,可以使$a永远与$b相等

16进制绕过字符的过滤

O:4:“test”:2:{s:4:“%00*%00a”;s:3:“abc”;s:7:“%00test%00b”;s:3:“def”;}

可以写成

O:4:“test”:2:{S:4:“\00*\00\61”;s:3:“abc”;s:7:“%00test%00b”;s:3:“def”;}

表示字符类型的s大写时,会被当成16进制解析。

到此这篇关于php浅析反序列化结构的文章就介绍到这了,更多相关php反序列化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅析PHP反序列化中过滤函数使用不当导致的对象注入问题

    1.漏洞产生的原因 #### 正常的反序列化语句是这样的 $a='a:2:{s:8:"username";s:7:"dimpl3s";s:8:"password";s:6:"abcdef";}'; 但是如果写成这样 $b='a:2:{s:8:"username";s:7:"dimpl3s";s:8:"password";s:6:"123456";}

  • PHP序列化和反序列化深度剖析实例讲解

    序列化 序列化格式 在PHP中,序列化用于存储或传递 PHP 的值的过程中,同时不丢失其类型和结构. 序列化函数原型如下: string serialize ( mixed $value ) 先看下面的例子: class CC { public $data; private $pass; public function __construct($data, $pass) { $this->data = $data; $this->pass = $pass; } } $number = 34;

  • PHP常见的序列化与反序列化操作实例分析

    本文实例讲述了PHP常见的序列化与反序列化操作.分享给大家供大家参考,具体如下: 1.概念 serialize() 把变量和它们的值编码成文本形式 unserialize() 恢复原先变量 2.序列化例子 输入输出 $arr=array(); $arr['name']='张三'; $arr['age']='22'; $arr['sex']='男'; $arr['phone']='123456789'; $arr['address']='上海市浦东新区'; var_dump($arr); arra

  • PHP反序列化字符串逃逸实例详解

    通过CTF比赛了解PHP反序列化,记录自己的学习. 借用哈大佬们的名言 任何具有一定结构的数据,如果经过了某些处理而把结构体本身的结构给打乱了,则有可能会产生漏洞. 0CTF 2016piapiapia-----反序列化后长度递增 安询杯2019-easy_serialize_php-----反序列化后长度递减 0CTF 2016piapiapia 由于是代码审计,直接访问www.zip发现备份的源码,有一下文件,flag就在config.php,因此读取即可 class.php        

  • 详解PHP序列化和反序列化原理

    0.前言 对象的序列化和反序列化作用就不再赘述,php中序列化的结果是一个php自定义的字符串格式,有点类似json. 我们在任何语言中设计对象的序列化和反序列化都需要解决几个问题 把某个对象序列化之后,序列化的结果有自描述的功能(从序列化的结果中知道这个对象的具体类型, 知道类型还不够,当然还需要知道这个类型所对应具体的值). 序列化时的权限控制,可以自定义序列化字段等,例如golang中的做的就非常方便. 时间性能问题:在某些性能敏感的场景下,对象序列化就不能拖后腿,例如:高性能服务(我经常

  • 详解PHP反序列化漏洞的原理及示例

    目录 PHP反序列化 序列化与反序列化 PHP魔法函数 反序列化漏洞 简介 原理 触发条件 示例 PHP反序列化 序列化与反序列化 序列化说通俗点就是把一个对象变成可以传输的字符串.序列化过程中还会对不同属性的变量进行不同方式的变化 public的属性在序列化时,直接显示属性名 protected的属性在序列化时,会在属性名前增加0x00*0x00,其长度会增加3 private的属性在序列化时,会在属性名前增加0x00classname0x00,其长度会增加类名长度+2 反序列化就是把被序列化

  • 详解php反序列化之字符逃逸法

    目录 1.先说关键字符变多 例题1 例题2 2.关键字符减少 总结 按我的理解,反序列化的过程就是碰到;}与最前面的{配对后,便停止反序列化.如下序列化: <?php class Test { public $a = "aa"; public $b = "bbb"; public $c = "cccc"; } $qwe = new Test(); echo serialize($qwe); 输出序列化结果为:O:4:"Test&q

  • php反序列化之字符串逃逸详解

    目录 php反序列化–字符串逃逸 过滤后字符串变多 字符串变多原理详解 过滤后字符串变少 总结 php反序列化–字符串逃逸 PHP反序列化的字符串逃逸,一共分有两种情况,情况一:过滤后字符串变多,情况二:过滤后字符变少(本篇文章默认已有反序列化相关知识基础) 过滤后字符串变多 以ctfshow-web262为例讲解: error_reporting(0); class message{ public $from; public $msg; public $to; public $token='u

  • 详解php反序列化

    1  前言 最近也是在复习之前学过的内容,感觉对PHP反序列化的理解更加深了,所以在此总结一下 2  serialize()函数 "所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示.序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字." 一开始看这个概念可能有些懵,但之后也是慢慢理解了 在程序执行结束时,内存数据便会立即销毁,变量所储存的数据便是内存数据,而文件.数据库是"持久数据",因此PHP序列

  • php浅析反序列化结构

    目录 简介 反序列化中常见的魔术方法 反序列化绕过小Trick 绕过_wakeup(CVE-2016-7124) 绕过部分正则 利用引用 16进制绕过字符的过滤 简介 序列化的目的是方便数据的传输和存储,在PHP中,序列化和反序列化一般用做缓存,比如session缓存,cookie等. 反序列化中常见的魔术方法 __wakeup() //执行unserialize()时,先会调用这个函数 __sleep() //执行serialize()时,先会调用这个函数 __destruct() //对象被

  • 浅析C# 结构体struct

    结构体 有时候我们仅需要一个小的数据结构,类提供的功能多于我们需要的功能:考虑到性能原因,最好使用结构体. 结构体是值类型,存储在栈中或存储为内联(如果结构体是存储在堆中的另一个对象的一部分). 例如类class: public class Dimensions { public Dimensions(double length, double width) { Length = length; Width = width; } public double Length { get; set;

  • 浅析顺序结构存储的栈

    栈定义:仅限在表尾进行插入和删除的线性表 栈的特点: 1)一般来说能在表尾进行进栈和出栈的数据 2)先进后出(last in first out ) 3)栈会有栈顶,栈底,通常栈底为高地址,栈顶为高地址,如下图所示 操作系统一般会在内存划出一块,专门用于栈操作,当然这个跟普通的操作有些区别:比如存放数组,地址是增加的:但是在存入数据到栈,地址则是不断减小的 栈的存储结构: 复制代码 代码如下: typedef struct _SQSTACK{ SElemType* base; SElemType

  • kotlin android extensions 插件实现示例详解

    目录 前言 原理浅析 总体结构 源码分析 插件入口 配置编译器插件传参 编译器插件接收参数 注册各种Extension IrGenerationExtension ExpressionCodegenExtension StorageComponentContainerContributor ClassBuilderInterceptorExtension PackageFragmentProviderExtension 总结 前言 kotlin-android-extensions 插件是 Ko

  • 浅析JAVA 循环结构

    顺序结构的程序语句只能被执行一次.如果您想要同样的操作执行多次,,就需要使用循环结构. Java中有三种主要的循环结构: while 循环 do-while 循环 for 循环 在Java5中引入了一种主要用于数组的增强型for循环. while 循环 while是最基本的循环,它的结构为: while( 布尔表达式 ) { //循环内容 } 只要布尔表达式为 true,循环就会一直执行下去. public class Test { public static void main(String

  • 浅析Python 序列化与反序列化

    序列化是将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态(存在内存中)写入到临时或持久性存储区(硬盘).以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象. 实现对象的序列化和反序列化在python中有两种方式:json 和 pickle. 其中json用于字符串 和 python数据类型间进行转换,pickle用于python特有的类型 和 python的数据类型间进行转换,pickle是python特有的. 1.JSON序列化:json.dump

  • 浅析JAVA中的内存结构、重载、this与继承

    一.对象在JVM的内存结构 JAVA内存管理由JVM来管理. 1)堆,所有new出来的对象(包括成员变量) 2)栈,所有局部变量(包括方法的参数) 3)方法区,class字节码文件(包括方法,静态数据) 1.引用变量指向null时,会发生空指针异常 public class student { int age; String name; public student(int age,String name){ this.age=age; this.name=name; } public stat

  • 浅析MySQL索引结构采用B+树的问题

    目录 1.B树和B+树 2.原因分析 3.总结 一位6年经验的小伙伴去字节面试的时候被问到这样一个问题,为什么MySQL索引结构要采用B+树?这位小伙伴从来就没有思考过这个问题.只因为现在都这么卷,后面还特意查了很多资料,他也希望听听我的见解. 另外,我花了1个多星期把往期的面试题解析配套文档准备好了,一共有10万字,想获取的小伙伴可以在我的煮叶简介中找到. 1.B树和B+树 一般来说,数据库的存储引擎都是采用B树或者B+树来实现索引的存储.首先来看B树,如图所示. B树是一种多路平衡树,用这种

  • 浅析JSON序列化与反序列化

    方法一:引入System.Web.Script.Serialization命名空间使用 JavaScriptSerializer类实现简单的序列化序列化类:Personnel 复制代码 代码如下: public class Personnel        {            public int Id { get; set; }            public string Name { get; set; }        } 执行序列化反序列化: 复制代码 代码如下: prote

  • 浅析C++中结构体的定义、初始化和引用

    定义:结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构. 声明一个结构体类型的形式是: 复制代码 代码如下: struct Student{      //声明一个结构体类型Student  int num;         //声明一个整形变量num  char name[20];   //声明一个字符型数组name  char sex;        //声明一个字符型变量sex  int age;         //声明一个整形变量age  float

随机推荐