• 反序列化漏洞详解


    目录

    一、什么是序列化和反序列化

    二、什么是反序列化漏洞

    三、序列化函数(serialize)

    四、反序列化(unserialize)

    ?五、什么是PHP魔术方法

    六、一些常见的魔术方法

    七、魔术方法的利用

    ?八、反序列化漏洞的利用

    1.__destruct()函数

    2.__wakeup()

    3.toString()

    ?九、反序列化漏洞的防御


    一、什么是序列化和反序列化

    序列化是将对象转换为字符串以便存储传输的一种方式。而反序列化恰好就是序列化的逆过程,反序列化会将字符串转换为对象供程序使用。在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。

    二、什么是反序列化漏洞

    当程序在进行反序列化时,会自动调用一些函数,例如__wakeup(),__destruct()等函数,但是如果传入函数的参数可以被用户控制的话,用户可以输入一些恶意代码到函数中,从而导致反序列化漏洞。

    三、序列化函数(serialize)

    当我们在php中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,用于保存对象的值方便之后的传递与使用。

    测试代码

    ";
    print_r($stu);
    //进行序列化
    $stus = serialize($stu);
    print_r($stus);
    }
    
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    查看结果:

    四、反序列化(unserialize)

    unserialize()可以从序列化后的结果中恢复对象(object)为了使用这个对象,在下列代码中用unserialize重建对象.

    测试代码:

    ";
    	//进行反序列化
    	print_r(unserialize($stus));
     ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    查看结果:

    五、什么是PHP魔术方法

    魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,利用魔术方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。 问题就出现在重载过程中,执行了相关代码。

    六、一些常见的魔术方法

    • __construct() :构造函数,当创建对象时自动调用。
    • __destruct():析构函数,在对象的所有引用都被删除时或者对象被显式销毁时调用,当对象被销毁时自动调用。
    • __wakeup():进行unserialize时会查看是否有该函数,有的话有限调用。会进行初始化对象。
    • __ toString():当一个类被当成字符串时会被调用。
    • __sleep():当一个对象被序列化时调用,可与设定序列化时保存的属性。

    七、魔术方法的利用

    测试代码:

    ";
       //序列化
        $stu_ser = serialize($stu);
        print_r($stu_ser);
        //当成字符串输出
        echo "$stu";
       //反序列化
        $stu_unser = unserialize($stu_ser);
        print_r($stu_unser);
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    测试结果:

    八、反序列化漏洞的利用

    由于反序列化时unserialize()函数会自动调用wakeup(),destruct(),函数,当有一些漏洞或者恶意代码在这些函数中,当我们控制序列化的字符串时会去触发他们,从而达到攻击。

    1.__destruct()函数

    个网站内正常页面使用logfile.php文件,代码中使用unserialize()进行了反序列化,且反序列化的值是用户输入可控 。正常重构Stu对象

    测试代码:

    name.'
    '; echo '年龄:'.$this->age; } } //实例化对象 $stu = new Stu(); //重构用户输入的数据 $newstu = unserialize($_GET['stu']); //O:3:"Stu":2:{s:4:"name";s:25:"";s:3:"age";i:120;} echo "
    ";
    	var_dump($newstu) ;
     ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    logfile.php 代码:

    ';
    			file_put_contents($this->filename, $text,FILE_APPEND);
    		}
    		//删除日志文件
    		function __destruct()
    		{
    			//输出删除的文件
    			echo '析构函数__destruct 删除新建文件'.$this->filename;
    			//绝对路径删除文件
    			unlink(dirname(__FILE__).'/'.$this->filename);
    		}
    	} 
     ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    正常输入参数:O:3:“Stu”:2:{s:4:“name”;s:2:“aa”;s:3:“age”;i:20;}

    重构logfile.php文件包含的对象进行文件删除

    • 正常重构:O:7:“LogFile”:1:{s:8:“filename”;s:9:“error.log”;}

    发现正常删除,但如果我们修改参数,让其删除其他的文件呢?

    • 异常重构:O:7:“LogFile”:1:{s:8:“filename”;s:10:“…/ljh.php”;}
    • 执行该代码

    2.__wakeup()

    例如有一个代码为index.php,源码如下

    test);
    			fclose($fp);
    		}
    	}
    	$class = @$_GET['test'];
    	print_r($class);
    	echo "
    "; $class_unser = unserialize($class); // 为显示效果,把这个shell.php包含进来 require "shell.php"; ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    传入参数:test=O:7:“chybeta”:1:{s:4:“test”;s:19:“”;}

    查看shell.php文件

    也可以传入:O:7:“chybeta”:1:{s:4:“test”;s:25:“”;}

    3.toString()

    举个例子,某用户类定义了一个__toString为了让应用程序能够将类作为一个字符串输出(echo $obj),而且其他类也可能定义了一个类允许 __toString读取某个文件。把下面这段代码保存为fileread.php

    fileread.php代码

    filename);
    		}
    	}
     ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    个网站内正常页面应引用fileread.php文件,代码中使用unserialize()进行了反序列化,且反序列化的值是用户输入可控 。

    测试代码:

    name.';'.'年龄:'.$this->age;
    		}
    	}
    	//O:4:"User":2:{s:4:"name";s:2:"aa";s:3:"age";i:18;}
    	//反序列化
    	$obj = unserialize($_GET['user']);
    	//当成字符串输出触发toString
    	echo $obj;
     ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    正常重构:O:4:“User”:2:{s:4:“name”;s:2:“aa”;s:3:“age”;i:18;}

    重构fileread.php文件包含的类进行读取password.txt文件内容

    重构:O:8:“FileRead”:1:{s:8:“filename”;s:12:“password.txt”;}

    九、反序列化漏洞的防御

    和大多数漏洞一样,反序列化的问题也是用户参数的控制问题引起的,所以最好的预防措施:

    1. 不要把用户的输入或者是用户可控的参数直接放进反序列化的操作中去。
    2. 在进入反序列化函数之前,对参数进行限制过滤。

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    map中常见的方法
    回收站永久删除了如何恢复正常?
    pikachu ssrf
    跳跃游戏 II
    Qt多线程之QThreadData::current()理解
    形式化定义软件动态更新
    Java学习——Servlet服务器请求响应程序
    《计算机组成与系统结构(第二版) 裘雪红 李伯成 西安电子科技大学出版社》课后习题答案(带解析)(八)
    nodejs 内置模块fs 常用api
    力扣:153. 寻找旋转排序数组中的最小值(Python3)
  • 原文地址:https://blog.csdn.net/m0_54864585/article/details/126081013