• 技术文章 >后端开发 >PHP问题

    php浅析反序列化结构知识点

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

    (推荐教程:PHP视频教程

    简介

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

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

    反序列化绕过小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浅析反序列化结构知识点的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:脚本之家,如有侵犯,请联系admin@php.cn删除
    专题推荐:php
    上一篇:php怎么比较多个数组中是否有重复值 下一篇:php怎么查询字符串出现位置
    VIP课程(WEB全栈开发)

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• 2022年十大开源php博客系统有哪些?【推荐】• php字符串怎么去掉重复字符• 分享一个neo4j(图形数据库)的PHP库!• 详细介绍PHP中时间处理类Carbon的用法• php二维数组怎么删除去除第一行元素
    1/1

    PHP中文网