web安全-PHP反序列化漏洞

本文深入探讨PHP的序列化与反序列化,包括serialize()和unserialize()函数的使用,解析PHP中常用魔术方法的触发条件,如__construct()、__set()等,并详细阐述了PHP反序列化漏洞的各种利用姿势,如__wakeup()函数绕过、正则绕过、字符逃逸和POP链构造等实战技巧。
摘要由CSDN通过智能技术生成

一.PHP序列化与反序列化

序列化:把对象转换为字节序列,永久存到磁盘中。在网络中传输对象也要进行序列化。

反序列化:从磁盘中读取字节序列将它们反序列化成对象读出来。

PHP中的serialize()和unserialize()两个函数:

1.serialize()

serizlize()就是将变量、对象、数组等数据类型转换成字符串方便进行网络传输和存储。

<?php
class Person{
    //类的数据
    public $age = 18;
    public $name = 'lxy';
}
//创建一个对象
$usr = new Person();
//输出序列化后的数据
echo serialize($usr)
?>

打印其序列化结果: 

O:6:"Person":2:{s:3:"age";i:18;s:4:"name";s:3:"lxy";}

“O”表示对象,“6”表示对象的类名长度,“Person”为对象名,“2”表示对象中有2个变量

s:4:"name";s:3:"lxy"中,“s”表示变量类型,为string对象;s:4:"name"代表的是变量名长度和变量名,s:3:"lxy"代表的是变量的值,和值的长度。

注意:如果变量前是protected,则会在变量名前加上\x00*\x00,private则会在变量名前加上\x00类名\x00。其中:\x00表示空字符,但是还是占用一个字符位置(空格),如下例:

<?php
class test{
    protected  $a;
    private $b;
    function __construct(){
        $this->a="name";
        $this->b="sex";
    }
}
$a = new test();
echo serialize($a);
?>

输出:

O:4:"test":2:{s:4:" * a";s:4:"name";s:7:" test b";s:3:"sex";}

 序列化格式:

a - array 数组型
b - boolean 布尔型
d - double 浮点型
i - integer 整数型
o - common object 共同对象
r - objec reference 对象引用
s - non-escaped binary string 非转义的二进制字符串
S - escaped binary string 转义的二进制字符串
C - custom object 自定义对象
O - class 对象
N - null 空
R - pointer reference 指针引用
U - unicode string Unicode 编码的字符串

2.unserialize()

unserialize()将字符串进行转换成原来的数据。当存在反序列化函数及可利用魔术方法时,且unserialize()接受到的字符串对于用户是可控时,用户可针对使用的魔术方法来构造特定的语句,从而达到控制整个反序列化过程。

对上例进行反序列化:

<?php
class Person{
    //类的数据
    public $age = 18;
    public $name = 'lxy';
    //输出数据
    public function printdata()
    {
        echo 'Person '.$this->name.' is '.$this->age.' years old.<br />';
    }
}
//重建对象
$usr = unserialize('O:6:"Person":2:{s:3:"age";i:18;s:4:"name";s:3:"lxy";}');
//输出数据
$usr->printdata();
?>

输出结果:

Person lxy is 18 years old.

二.PHP中常用魔术方法及触发条件

PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods)

参考来源:常用魔术方法+PHP官网详解

__construct()            //类的构造函数,创建对象时触发

__destruct()             //类的析构函数,对象被销毁时触发

__call()                 //在对象上下文中调用不可访问的方法时触发

__callStatic()           //在静态上下文中调用不可访问的方法时触发

__get()                  //读取不可访问属性的值时,这里的不可访问包含私有属性或未定义

__set()                  //在给不可访问属性赋值时触发

__isset()                //当对不可访问属性调用 isset() 或 empty() 时触发

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

__invoke()               //当尝试以调用函数的方式调用一个对象时触发

__sleep()                //执行serialize()时,先会调用这个方法

__wakeup()               //执行unserialize()时,先会调用这个方法

__toString()             //当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值