我是靠谱客的博主 年轻路灯,最近开发中收集的这篇文章主要介绍php浅析反序列化结构知识点,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

本篇文章主要给大家介绍了关于PHP的相关知识,序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize 将对象格式化成有序的字符串、unserialize 将字符串还原成原来的对象,希望对大家有帮助。

(推荐教程:PHP视频教程)

简介

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

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

  • __wakeup() //执行unserialize()时,先会调用这个函数

  • __sleep() //执行serialize()时,先会调用这个函数

  • __destruct() //对象被销毁时触发

  • __call() //在对象上下文中调用不可访问的方法时触发

  • __callStatic() //在静态上下文中调用不可访问的方法时触发

  • __get() //用于从不可访问的属性读取数据或者不存在这个键都会调用此方法

  • __set() //用于将数据写入不可访问的属性

  • __isset() //在不可访问的属性上调用isset()或empty()触发

  • __unset() //在不可访问的属性上使用unset()时触发

  • __toString() //把类当作字符串使用时触发

  • __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:“0*061”;s:3:“abc”;s:7:“%00test%00b”;s:3:“def”;}

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

(推荐教程:PHP视频教程)

以上就是php浅析反序列化结构知识点的详细内容,更多请关注靠谱客其它相关文章!

最后

以上就是年轻路灯为你收集整理的php浅析反序列化结构知识点的全部内容,希望文章能够帮你解决php浅析反序列化结构知识点所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(74)

评论列表共有 0 条评论

立即
投稿
返回
顶部