反序列化漏洞
反序列化漏洞是一种安全漏洞,它存在于应用程序中使用序列化和反序列化技术的场景中。当应用程序接收到外部提供的序列化数据并进行反序列化处理时,如果没有适当的检查和验证机制,恶意攻击者可以通过构造恶意的序列化数据来触发漏洞,导致应用程序执行非预期的操作或受到攻击。
序列化和反序列化函数
serialize()将一个对象转换成一个字符串;
unserialize()将字符串还原为一个对象;
在PHP应用中,序列化和反序列化一般用做缓存,比如session缓存,cookie等。简单点讲序列化就是把一个对象变为可以传输的字符串,而反序列化就是把字符还原为对象。
序列化
字符串序列化
<?php
$a='serial';
echo '序列化结果:';
$b=serialize($a);
print($b);
?>
序列化结果:s:6:“serial”;
s表示字符串(string) , 6表示长度 ,serial是值。
数组序列化
<?php
$a=array('csdn'=>'mzqms','height'=>180);
echo '序列化结果:';
print(serialize($a));
?>
序列化结果:a:2:{s:4:“csdn”;s:5:“mzqms”;s:6:“height”;i:180;}
a表示数组, 2表示元素数
对象序列化
<?php
class csdn{
public $a ='csdn';
}
$class =new csdn;
echo '序列化结果:';
print(serialize($class));
?>
序列化结果:O:4:“csdn”:1:{s:1:“a”;s:4:“csdn”;}
O表示类 4表示类名长度 csdn是类名 1代表类中有一个属性 s 字符串 1 长度1位 a是属
性名 csdn 是属性的值。
序列化字符含义
a – array 数组
b – boolean 布尔型
d – double 双精度型
i – integer 整型
o – common object 一般对象
r – reference 引用
s – string 字符串
C – custom object 自定义对象
O – class N – null 表示类
R – pointer reference 引用传递
U – unicode string unicode编码的字符串
隐藏规则
public 直接变量名反序列化出来
private x00 类名 x00 变量名 在网页是不显示的:
protected 00* 00 变量名
<?php
class A1{
public $public = "public";
private $private="private";
Protected $Protected="Protected";
}
$c = new A1();
echo '序列化结果:';
echo serialize($c);
?>
查看网页源代码
反序列化
反序列化:顾名思义,就是 序列化过程的逆向操作,也就是将字符串转换为对象。
而反序列化漏洞就是因为在反序列化转换的过程中,触发代码执行,从而造成漏洞,关键点还是在于可
控或不可控。
<?php
class G{
var $test = "gongneng";
function __construct(){
echo $this->test;
}
}
echo '序列化结果:';
$g = new G();
echo serialize($g);
?>
反序列化后,如果=test 可控,类在实例化的时,值会传入this->test 因为是 echo 内容是直接输出会造
成 xss 漏洞。
生成 payload 代码:
<?php
class G{
var $test = "<script>alert(1);</script>";
function __construct(){
echo $this->test;
}
}
echo '序列化结果:';
$g = new G();
echo serialize($g);
?>
序列化结果:”;}
反序列化:
正常后面不跟请求参数是正常放回的,但是如果 $_GET[‘url’] 为可控的,那么,输入序列化后的
payload 同样会被执行;
<?php
class G{
var $test = "gongneng";
function __construct(){
echo $this->test;
}
}
$g = new G();
$u=unserialize($_GET['url']);
echo $u->test;
?>
将输入序列化后的payload通过url传入
利用成功
反序列化里的魔法函数
__construct() 当一个对象创建时被调用( 构造函数,当对象创建(new)时会自动调用。
unserialize()反序列化时是不会自动调用的。 );
__destruct() 当一个对象销毁前被调用 ;
__sleep() 在对象被序列化前被调用 ( 用于提交未提交的数据,或类似的清理操作 );
__wakeup 将在反序列化之后立即被调用(当使用unserialize()进行反序列化时,就会被调用,
unserialize()时会检查是否存在 __wakeup(),如果存在,则会优先调用 __wakeup()方法 );
__toString 当一个对象被当做字符串使用时被调用 ;
__get(),__set() 当调用或设置一个类及其父类方法中未定义的属性时 ;
__invoke() 调用函数的方式调用一个对象时的回应方法 ;
__call 和 __callStatic 前者是调用类不存在的方法时执行,而后者是调用类不存在的静态方式方法时
执行。