WEB漏洞——PHP反序列化

2021年09月16日 阅读数:2
这篇文章主要向大家介绍WEB漏洞——PHP反序列化,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

序列化

首先说说什么是序列化php

序列化给咱们传递对象提供了一种简单的方法。serialize()将一个对象转换成一个字符串,而且在转换的过程当中能够保存当前变量的值数组

而反序列化unserialize()将字符串还原为一个对象缓存

通俗来讲:经过反序列化在特定条件下能够重建php对象并执行php对象中某些magic函数。安全

在PHP应用中,序列化和反序列化通常用作缓存,好比session缓存,cookie等。cookie

举一个简单的例子session

<?php
class people{
 public $name;
 public $age;
 public $sex;
 
 function __construct($name,$age,$sex){   //_construct:建立对象时初始化
  $this->name = $name;
  $this->age = $age;
  $this->sex = $sex;
 }
}
$people=new people("hhy",20,"boy");
echo serialize($people);
?>

输出结果:O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}app

“O”表示对象,6表示对象名长度为6xss

“people”为对象名,3表示有3个参数函数

“s”表示string对象this

“i”表示int对象

 

反序列化输出

$unpeople='O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}';
var_dump(unserialize($unpeople)); //输出用var_dump函数

或者 $u=unserialize('O:6:"people":3:{s:4:"name";s:3:"hhy";s:3:"age";i:20;s:3:"sex";s:3:"boy";}'); echo $u->name,$u->age,$u->sex;

输出结果:object(people)#2 (3) { ["name"]=> string(3) "hhy" ["age"]=> int(20) ["sex"]=> string(3) "boy" }

输出结果:hhy20boy

反序列化

序列化和反序列化自己没有问题,可是若是反序列化的内容是用户能够控制的,且后台不正当的使用了PHP中的魔法函数,就会致使安全问题

  1. unserialize()函数的参数可控
  2. php中有能够利用的类而且类中有魔术方法

常见的魔术方法

__construct(): 在建立对象时候初始化对象,通常用于对变量赋初值。

__destruct(): 和构造函数相反,当对象所在函数调用完毕后执行。

__toString():当对象被当作一个字符串使用时调用。

__sleep():序列化对象以前就调用此方法(其返回须要一个数组)

__wakeup():反序列化恢复对象以前调用该方法

__call():当调用对象中不存在的方法会自动调用该方法。

__get():在调用私有属性的时候会自动执行

__isset()在不可访问的属性上调用isset()或empty()触发

__unset()在不可访问的属性上使用unset()时触发

<head>
<meta charset="UTF-8">
</head>
<?php 
class T{
    public $test=1;
    function __construct(){
        echo '调用了_construct<br>';
    }
    function __destruct(){
        echo '调用了_destruct<br>';
    }
    //function __sleep(){
    //    echo '调用了_sleep<br>'
    //}
    function __wakeup(){
        echo '调用了_wakeup<br>';
    }
}
$t=new T();
echo $t->test;
echo "<br/>";
$t1=serialize($t);
echo $t1;
echo "<br/>";
$t2=unserialize($t1);
echo $t->test;
echo "<br/>";

 

当程序执行前,serialize() 函数会首先检查是否存在一个魔术方法__sleep.若是存在,__sleep()方法会先被调用,而后才执行序列化操做。这个功能能够用于清理对象,并返回一个包含对象中全部变量名称的数组。若是该方法不返回任何内容,则NULL被序列化,致使一个E_NOTICE错误。

unserialize()会检查是否存在一个__wakeup方法。若是存在,则会先调用 __wakeup方法,预先准备对象数据。

 

 

漏洞举例:
        class S{
            var $test = "pikachu";
            function __destruct(){
                echo $this->test;
            }
        }
        $s = $_GET['test'];
        @$unser = unserialize($a);

        payload:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

防护

反序列化的问题是用户参数的控制问题引发的,因此好的预防措施就是不要把用户的输入或者是用户可控的参数直接放进反序列化的操做中去。