反序列化漏洞

介绍

        (反)序列化

        序列化 :将对象转换为字符串以便存储传输的一种方式。

        反序列化:将字符串转换为对象供程序使用。

        在PHP中序列化和反序列化对应的函数分别为serialize()和unserialize()。

<?php
    class Stu{
        public $name;
        public $age;
        public $addr;

        public function demo(){
            echo "你好啊!\n";
        }
    }

    $stu=new Stu();     
    $stu->name="aaa";
    $stu->age=34;
    $stu->addr="上海";

    echo "对象初始值:\n";
    print_r($stu);

    $stus=serialize($stu);  //序列化
    echo "\n对象序列化后的值:\n";
    print_r($stus);

    $stb=unserialize($stus);    //反序列化
    echo "\n\n对象反序列化后的值:\n";
    print_r($stb);
?>

 运行结果

        PHP魔术方法 

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

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

        魔术方法的运用 

<?php
    class Stu{
        public $name;
        public $age;
        public $add;

        function __construct(){
            print "构造函数".PHP_EOL;   //换行符
        }

        function __destruct(){
            print "析构函数\n";
        }

        function __wakeup(){
            print "\n返序列化函数调用初始化函数wakeup()";
        }

        /*让应用程序能够将类作为一个字符串输出(echo $obj),而且
其他类也可能定义了一个类允许 __toString读取某个文件。*/
        function __toString(){
            return $this->name."toString字符串";
        }

        /*function __sleep(){
            print "序列化时调用该函数";
        }*/
    }

    //创建几次对象,执行几次构造函数
    $stu=new Stu();

    $stu->name="fpp";
    $stu->age=34;
    $stu->add="dfdgg";

    $stus=serialize($stu);  //序列化
    echo "\n对象序列化后的值:\n";
    print_r($stus);

    echo "\n\n执行反序列化";
    $stb=unserialize($stus);    //反序列化
    echo "\n\n对象反序列化后的值:\n";
    print_r($stb);

    print "\n输出对象值:\n$stu";

    //销毁几个对象,执行几次析构函数
?>

输出结果 

 

 原理

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

利用 

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

        删除文件 

<?php 
	class LogFile
	{
		//日志文件名
		public $filename = 'error.log';
		//存储日志文件
		function LogData($text)
		{
			//输出需要存储的内容
			echo 'log some data:'.$text.'<br>';
			file_put_contents($this->filename, $text,FILE_APPEND);
		}
		//删除日志文件
		function __destruct()
		{
			//输出删除的文件
			echo '析构函数__destruct 删除新建文件'.$this->filename;
			//绝对路径删除文件
			unlink(dirname(__FILE__).'/'.$this->filename);
		}
	} 


    $logfile = unserialize($_GET['logfile']);
	//O:7:"LogFile":1:{s:8:"filename";s:9:"error.log";}
	echo "<pre>";
	var_dump($logfile);
 ?>

执行结果 

         

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

        写入文件 

<?php
	class chybeta
	{
		public $test = '123';
		function __wakeup()
		{
			$fp = fopen("shell.php","w") ;
			fwrite($fp,$this->test);
			fclose($fp);
		}
	}
	$class = @$_GET['test'];
	print_r($class);
	echo "</br>";
	$class_unser = unserialize($class);
	
	// 为显示效果,把这个shell.php包含进来
    require "shell.php";
?>

 

防御

  1.  不要把用户的输入或者是用户可控的参数直接放进反序列化的操作中去。
  2. 在进入反序列化函数之前,对参数进行限制过滤。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值