PHP序列化和反序列化

本文详细介绍了PHP中的序列化和反序列化过程,展示了不同类型的变量如何被转换和还原,以及序列化格式的详细解析。同时讨论了简单序列化漏洞的概念,通过实例演示了如何利用这一漏洞进行安全攻击。
摘要由CSDN通过智能技术生成

序列化

序列化是指将数据结构或对象转换为一串字节流的过程。使其可以在存储、传输或缓存时进行持久化。

反序列化

反序列化是指将序列化后的数据进行解码和还原,恢复为原始的数据结构或对象的过程。反序列化是序列化的逆过程。

在 PHP 中,使用 serialize() 函数可以将数据结构或对象进行序列化,得到一个表示序列化后数据的字符串。通过 unserialize() 函数可以将这个字符串进行反序列化,将其还原为原始的数据。

序列化格式

O:长度:“类名”:变量数:{变量类型:变量名长度:“变量名字”;变量的值;}

i

表示整数类型(integer)  

d

表示浮点数类型(double)

b

表示布尔类型(boolean)

a

表示数组类型(array)

O

表示对象类型(object)

N

表示 NULL 类型(null)

private属性序列化属性名称格式是0x00类名0x00成员名。

0x00代表16进制编码的空格,%00代表url编码的空格

private $age=18;      %00people%00age

protected属性序列化属性名称格式是0x000x2A0x00成员名

0x00代表16进制编码的空格,%00代表url编码的空格,0x2A代表16进制编码的 * 号

protected $height='156cm';    %00*%00height

数组和关联数组的序列化 

$arr=array('lili','girl');
$arr[8]='18';
echo serialize($arr);

 a:3:{i:0;s:4:"lili";i:1;s:4:"girl";i:8;s:2:"18";}

注意! 3是数组的有效值数量,不是最后一个下标,和对象序列化不一样。i:0代表下标为0

$person = array(
    'name' => 'xiaoming',
    'age' => 30,
    'city' => 'beijing'
);

a:3:{s:4:"name";s:8:"xiaoming";s:3:"age";i:30;s:4:"city";s:7:"beijing";}

echo、print_r、var_dump输出信息 

$lili=new people();
$lili->name='lili';
$lili->age=18;
$a=serialize($lili);
echo $a;
print_r(unserialize($a));
var_dump(unserialize($a));

O:6:"people":2:{s:4:"name";s:4:“oooo";s:3:"age";i:18;}
people Object ( [name] => lili [age] => 18 )
object(people)#2 (2) { ["name"]=> string(4) "lili" ["age"]=> int(18) }

不同方式输出的序列化信息也不同。

#2 php的对象标识符,表示该对象在 PHP 程序执行期间的唯一标识符。每创建一个新的对象时,PHP 会自动为该对象分配一个唯一的标识符,以便在程序中引用和识别该对象。它的值本身没有特殊意义,只是为了唯一标识一个对象而存在。

简单序列化漏洞

class people{
    public $name='lili';
    private $age=18;
    protected $height='160cm';
}
$lili=new people();
echo serialize($lili);

此时序列化的结果为:

O:6:"people":3:{s:4:"name";s:4:"oooo";s:11:"%00people%00age";i:18;s:9:"%00*%00height";s:5:"160cm";}

我们将这个序列化后的字符串修改:

//注意:age和height前的权限修饰符 %00
$a='O:6:"people":3:{s:4:"name";s:4:"lili";s:11:"%00people%00age";i:20;s:9:"%00*%00height";s:5:"150cm";}';
var_dump(unserialize(urldecode($a))); //因%00(0x00)代表空字符,直接写不出来,对其url解码再传入

此时反序列化输出的结果为:

object(people)#2 (3) { ["name"]=> string(4) "lili" ["age":"people":private]=> int(20) ["height":protected]=> string(5) "150cm" }

可以发现age和height属性值被修改,这说明 前一个对象只是为我们提供一个序列化的字符串,反序列化是根据当前传入的字符串。

简单演示

class User {
    public $username='lili';
    public $isAdmin=0;
}
$userData = $_GET['data'];
$user = unserialize($userData);
if($user->isAdmin===1 && $user->username==='admin'){
    echo '欢迎你管理员~';
}
else{
    echo '你是一个普通用户!';
}

这个漏洞代码通过get请求传入的参数进行反序列化,我们构造序列化字符串使isAdmin属性值为1并且 username属性值为admin。末尾的 ;} 不要忘记。

O:4:"User":2:{s:8:"username";s:5:"admin";s:7:"isAdmin";i:1;}

传入参数:

?data=O:4:"User":2:{s:8:"username";s:5:"admin";s:7:"isAdmin";i:1;}

网站输出结果:欢迎你管理员~

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值