PHP的序列化和反序列化

0x1 定义

php使用serialize()这个过程被称为序列化,使用unserialize()这个过程被称作反序列化。

0x2 serialize()

用于序列化对象或数组,并返回一个字符串。序列化会保存对象中的所有变量,不会保存对象的方法,只会保存类的名字。PHP序列化就是将内存的变量数据“保存”到文件的持久数据的过程

例子:

<?php
class User
{
    /*类的变量*/
    public $name = '';
    public $age = 0;
    /*方法:打印数据*/
    public function PrintData(){
        echo 'user'.' name:'.$this->name.' age:'.$this->age;
    }
}
//创建一个对象
$user = new User();
$user->name = 'iring';
$user->age = 18;

//输出数据
$user->PrintData();
echo "\n";

//输出序列化后的数据
echo serialize($user);

在这里插入图片描述

可以发现对于对象,序列化后的格式为:

O:strlen(类名):类名:类的变量个数:{类型:长度:值;类型:长度:值…}

注:对象中的常量在序列化后是不会保留的。如果存在类的继承,会保留父类中的变量

其他类型的数据序列化后的格式为:

String类型 : s:size:value;

Integer类型 : i:value;

Boolean类型 : b:value;(保存1或0)

Null型 : N;

Array : a:size:{key definition;value definition}

0x3 unserialize()

函数用于将通过serialize()函数序列化后的对象或者数组进行反序列化,并返回原始对象的结构。可以将反序列化理解为就是:将文件中的持久数据转变成内存中的变量数据

//输出序列化后的数据
$temp =  serialize($user);
echo $temp."\n";

//反序列化
$ans = unserialize($temp);
echo $ans->PrintData();

在这里插入图片描述

0x4 PHP反序列化漏洞

需要了解PHP的“魔法函数”:以__(两个下划线)开头的类方法被保留为魔法方法。这些方法会在特定的时候被调用。例子

__construct() 当一个对象被创建时候被调用(构造方法)

__destruct() 当一个对象被销毁的时候调用(析构方法)

__toString() 当一个对象被当做字符串时被调用

__wakeup() 当使用unserialize时候触发

__sleep() 当使用serialize时候触发

对象注入

因为PHP允许对象序列化,因此用户可以提交序列化的字符串,若没有对请求进行严格的过滤,在传递给unserialize()函数后就可能造成PHP对象注入漏洞。

对象漏洞需要满足的前提:

  • unserialize()的参数可控的。
  • 代码中含有一个包含魔法方法的类,并且该类方法里出现一些使用类成员变量作为参数的存在安全问题的函数。

例子:

<?php
error_reporting(0);
class Test
{
    var $test = "demo";
    function __destruct()
    {
        @eval($this->test);
    }
}
$a = $_POST['test'];//POST方法获得前端数据	
print_r($a); 
$b = unserialize($a);//对传入的字符串反序列化

程序结束时会销毁变量,会触发__destruct()函数,我们可以通过反序列化构造出变量的值,使得其中的内容被当做代码去执行。构造一个Payload测试一下:

test=O:4:"Test":1:{s:4:"test";s:10:"phpinfo();";}

在这里插入图片描述

绕过魔法函数的反序列化

wakeup()魔法函数绕过

PHP5<5.6.25

PHP7<7.0.10

当在反序列化字符串中,表示属性个数的值大于真实属性个数时,会绕过__wakeup()函数的执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值