
良性のログインプローブを用いた挙動優先のWordPress CVE-2026-64638スキャナー。サニタイザーの動作を分類し、許可された用途向けにアラート専用のPoCを生成します。
ビヘイビアファーストのマススキャナー兼エビデンスグレードのPoCジェネレーター。5億以上のWebサイトに影響するWordPressの
認証前XSS-to-RCEチェーンに対応します。
検出のみ。武器化は一切行いません。バグバウンティプログラムとブルーチーム向けに作られています。
これは何か? • クイックスタート • Shodan ダークス • 使い方 • 判定マトリックス • 検出 • FAQ
スキャン前に、インターネット上で潜在的に脆弱なWordPressインスタンスを探しましょう:
http.component:"wordpress" -http.title:"Just a moment"
Cloudflareの「I'm Under Attack」モード / ボット保護ページ(自動リクエストをブロックまたはチャレンジする)を除外しつつ、WordPressサイトを発見します。
http.component:"wordpress" http.title:"Log In"
CVE-2026-64638のまさに攻撃対象となるWordPressログインページのみを返します。
http.component:"wordpress" "wp-content" "?ver=7.0" -"?ver=7.0.3"
アセットのバージョンフィンガープリントにより、7.0.3パッチを適用していないWordPress 7.0.xインスタンスを検出します。
http.component:"wordpress" http.html:"wp-login.php"
wp-login.php に到達可能だが現在のページではないサイトも捕捉します — より広範なカバレッジを実現します。
http.component:"wordpress" -http.title:"Just a moment" -http.title:"Attention Required" -org:"Cloudflare"
Cloudflareを前面に置いたほとんどのターゲットを除外する強力なフィルターです。--active を使用した大規模スキャン時に使用してください — Cloudflareはプローブリクエストをレート制限またはブロックします。
ヒント:
shodan downloadでShodanの結果をエクスポートし、ホスト名をパイプでそのままxss2shell_mass.py -iに渡してください。
2026年8月7日、pwn.aiはCVE-2026-64638 (XSS2Shell) を公開しました — これはWordPress Coreにおける重大な認証前クロスサイトスクリプティング (XSS) 脆弱性で、サーバー上でのリモートコード実行 (RCE) にまで連鎖します。[citation:pwn.ai blog]
このバグは、PHPの strip_tags() とWordPressの wp_kses_post() の間のパーサーの解釈の相違を悪用します:
strip_tags() は、< の直後に英字が続く場合にHTMLタグとして識別します。< area id=...> (スペース入り) はテキストとして扱われるため、除去されずに残ります。wp_kses_post() (KSES) は < area を有効な <area> 要素として認識します — そして <area> はKSESで許可リストに登録されています。[citation:pwn.ai blog]特別に細工されたユーザー名 < area id=ajaxurl href=/?rest_route=/&_method=GET&_jsonp=alert>... による1回のログイン失敗で両方のサニタイザーをバイパスし、ログインページにライブDOMとしてレンダリングされ、DOM clobberingを介してWordPress自身の user-profile.js スクリプトを乗っ取り、WordPressオリジン上で alert() を発火させます — クリック不要、認証不要、Cookie不要です。[citation:pwn.ai blog]
ログイン済み管理者への権限昇格は? 同じプリミティブで、Same Origin Method Execution (SOME) を介してApplication Passwordsを窃取し、悪意のあるプラグインをアップロードし、www-data としてPHPを実行できます。[citation:pwn.ai blog] [citation:hadrian.io blog]
影響を受けるバージョン: WordPress 6.4〜7.0.2 — 7.0.3でパッチ適用済み。4.7以降にもバックポート。
影響範囲: 公開時点で約5億のWebサイト。[citation:pwn.ai blog]
これは検出のみのツールキットです。この脆弱性を武器化することはありません — セキュリティ研究者、バグバウンティハンター、ブルーチームに必要なすべてを提供します:
「バージョン文字列は、コードがあるべきパッチレベルを示すだけです。
バグが実際に発火するかどうかを示すのは、ログインページのサニタイザーの挙動だけです。」
マネージドホストは、バージョン文字列を上げずにセキュリティパッチを静かにバックポートします。ログイン強化プラグインはエラーメッセージを完全に置き換えるため、脆弱なバージョンでも反射 (リフレクション) チャネルを無効化します。**バージョンだけで判定するスキャナーは、誤検知と検出漏れの両方を生み出します。**このスキャナーは単一の良性プローブを送信し、実際のサニタイザーの挙動を分類します。
git clone https://github.com/jakestone/xss2shell.git
cd xss2shell
pip install -r requirements.txt
# Passive — no probes sent to target, version + endpoint fingerprinting only
python3 xss2shell_mass.py -i domains.txt -o results
# Active — sends ONE benign failed-login per host (authorized assets only!)
python3 xss2shell_mass.py -i domains.txt -o results --active --workers 80
# Single target
python3 make_poc.py --target https://blog.example.com
# Batch from scanner output
python3 make_poc.py --from-results results.csv -o pocs/
生成された .poc.html を録画しながらブラウザで開きます → alert() が発火すれば、認証前XSSのエビデンスを捕捉できたことになります。
xss2shell_mass.py)usage: xss2shell_mass.py [-h] -i INPUT [-o OUTPUT]
[--active] [--workers WORKERS]
[--timeout TIMEOUT] [--quiet]
?ver= パラメータ、wp-content 参照)user-profile.js ガジェットのエンキュー、コアアセットのバージョン/?rest_route=/&_method=GET&_jsonp=<random> への無害なGET — JSONP経路は開いているか?--active フラグ)ユーザー名 < area id=<RANDOM> href=/x2s> で1回のログイン失敗を送信し、HTMLレスポンスを分類します:
bypass — マーカー付きの実際の <area> 要素が残存 → strip_tags/KSESの不一致を確認escaped — マーカーは存在するがエンティティエンコードされている → パッチまたは強化が適用済みstripped — デフォルトのWPエラーが表示され、タグが除去された → acevomod またはパッチ適用済みclosed — ユーザー名の反射が一切ない → ログイン強化プラグインが導入済みmake_poc.py)usage: make_poc.py [-h] [--target TARGET] [--from-results FROM_RESULTS]
[-o OUTDIR]
各ターゲットについて、公開されているpwn.aiのPoCページを生成します — パッチ未適用のWordPressで alert() を発火させる正確なHTMLフォームです。コメント内に3つのペイロードバリアントが含まれています:
スキャナーの判定エンジンは、バージョン分類 (WordPress.orgのstable-check APIによる) とビヘイビアのエビデンスを組み合わせ、10種類の明確な判定を出力します:
CSVの列: host、url、status、checker_status、wp_version、branch_status、evidence、http、ms、error
checker_status 列は、直接的な照合のために pwn.aiの公開チェッカーの語彙 (vulnerable / patched / not_wordpress / unreachable / inconclusive / error) に対応しています。
防御側の立場であれば、この脆弱性が残すフォレンジック上のシグナルは以下のとおりです:
# Primary signal: encoded '<' in the log parameter
POST /wp-login.php → log=%3C... (URL-encoded < in username field)
# Higher confidence: paired with REST pivoting
GET /?rest_route=/&_method=GET&_jsonp=... # JSONP callback
GET /wp-json/wp/v2/statuses/publish?_jsonp=... # WAF-bypass variant
# Escalation stage indicators
GET /wp-admin/authorize-application.php?success_url=<off-origin>
POST /wp-admin/update.php?action=upload-plugin
GET /wp-content/plugins/<random>/shell.php
log パラメータに %3C (URLエンコードされた <) が含まれる POST /wp-login.php をブロックしてください。正規のWordPressユーザー名に山括弧が含まれることは決してありません。特定のタグに絞り込まないでください — KSESは < の後にタブ、改行、復帰、および任意の許可リスト登録タグを許可するため、タグ固有のルールは簡単に回避されます。[citation:hadrian.io blog]
昇格段階の _jsonp= コールバックは、プロパティの走査にドットを使用します (例: window.opener.approve.click)。ドット付きJSONPコールバックを含むRESTリクエストは、悪用の強力な兆候としてフラグを立ててください。[citation:hadrian.io blog]
THIS TOOL IS DETECTION-ONLY. IT DOES NOT:
✗ Weaponize the JSONP callback beyond the public alert()
✗ Include admin-lure pages or Application Password capture
✗ Include REST abuse, plugin upload, or PHP shell code
✗ Execute more than one failed login per target per scan
YOU MUST:
✓ Only scan assets you own or have written authorization to test
✓ Only generate PoCs for your own browser on your own server
✓ Never send PoC links to site admins/users
✓ Never escalate past alert() without program written approval
✓ Follow the bug bounty program scope and rules
This toolkit exists for authorized security research, bug bounty
programs, and defensive detection engineering. Misuse is your
responsibility.
xss2shell/
├── README.md ← You are here
├── xss2shell_mass.py ← Behavior-first mass scanner (v1.1.0)
├── make_poc.py ← Evidence-grade PoC page generator
├── requirements.txt ← Python dependencies (just `requests`)
├── .gitignore ← Ignores scan outputs and cache
└── example/
├── domains.txt ← Example input file
└── example_output.csv ← Example scan output
Q: WordPressのバージョン文字列を確認するだけではなぜダメなのか?
A: マネージドホスト (WP Engine、Kinsta、Pantheonなど) は、バージョンを上げずにセキュリティパッチをバックポートすることがよくあります。ログイン強化プラグインはエラーメッセージを完全に置き換えます。どちらの場合も、バージョンだけで判定するスキャナーでは誤検知が発生し、非表示バージョンでは検出漏れが発生します。このスキャナーは実際のサニタイザーの挙動をテストします。
Q: --active プローブは危険ですか?
A: いいえ。良性のマーカーユーザー名で、正確に1回のログイン失敗を送信するだけです。JavaScriptの実行を試みず、有効なユーザー名の列挙も行わず、実際のエクスプロイトを発動させることもありません。標準的なログイン試行よりも侵襲性が低いです。
Q: このツールを不正なスキャンに使用できますか?
A: いいえ。アクティブプローブは /wp-login.php にHTTP POSTを送信します。これはターゲットサーバーへのリクエストです。自分が所有するアセット、またはテストの明示的な書面による許可を得たアセットに対してのみ使用してください。
Q: vulnerable と confirmed_vulnerable の違いは何ですか?
A: vulnerable は、WordPress.org APIがそのバージョンを不安全と判断しているが、strip_tags/KSESの不一致をビヘイビア的に確認できていない状態を指します。confirmed_vulnerable は、プローブを送信し <area> 要素が両方のサニタイザーを生き残った状態を指します — 公開されている攻撃チェーンが発火可能です。
Q: バグバウンティプログラムのレポートに使用できますか?
A: はい!checker_status 列は、容易な照合のためにpwn.aiの公開チェッカーの語彙に直接対応しています。スキャン結果と make_poc.py で生成したPoCビデオのエビデンスを組み合わせることで、完全なレポートになります。
Q: RCEチェーンも検出しますか?
A: いいえ。このツールキットが検出するのは認証前XSSの入口です。完全なRCEチェーンには、ログイン済みの管理者、Application Passwordsの有効化、プラグインのアップロード権限が必要です — これらはこのスキャナーが評価しない条件です。スキャナーは外部から観測可能な部分、つまりサニタイザーバイパスに焦点を当てています。
作者: 0xlipon • 検出のみ • 許可された用途のみ
| リソース | リンク |
|---|
| 元の開示 (pwn.ai) | pwn.ai/blog/xss2shell |
| Hadrian 技術分析 | hadrian.io/blog/wordpress-xss2shell |
| WordPress アドバイザリ (GHSA) | GHSA-52p2-r8wf-jcrf |
| SOME攻撃の研究 (2022) | pwn.ai/blog/bypass-csp-using-wordpress |
| WordPress 7.0.3 リリース | wordpress.org/news/2026/08/wordpress-7-0-3-release |
| フラグ | 説明 |
|---|
-i, --input | 1行に1ホストを記述したファイル (ベアドメインまたは完全なURL) |
-o, --output | 出力ファイルのベースパス (.csv と .json を生成) |
--active | ビヘイビアプローブを有効化 — ホストごとに1回のログイン失敗を送信 |
--workers | スレッドプールサイズ (デフォルト: 50、接続が良ければ最大約200) |
--timeout | HTTPタイムアウト (秒) (デフォルト: 10) |
--quiet | confirmed_vulnerable、vulnerable、likely_vulnerable のみを表示 |
| バリアント | href の値 | 使用場面 |
|---|
| Default | /?rest_route=/&_method=GET&_jsonp=alert | 標準的なWordPress |
| Envelope | /?rest_route=/&_method=GET&_envelope=1&_jsonp=alert | RESTが401を返す場合 (200でラップ) |
| WAF Pivot | /wp-json/wp/v2/statuses/publish?_jsonp=alert&_method=GET | ?rest_route= がWAFでブロックされる場合 |
| 判定 | 条件 |
|---|
confirmed_vulnerable 🔴 | バージョンが不安全 かつ プローブマーカーが <area> 要素として残存 かつ user-profile.js ガジェットが存在 |
vulnerable 🔴 | wordpress.org によるとバージョンが不安全。ビヘイビアプローブ未実行 (--active で再実行) |
likely_vulnerable 🟠 | プローブマーカーは残存したが user-profile.js がエンキューされていない (公開されている自動発火ガジェットが存在しない) |
mitigated 🟣 | バージョンは不安全だが、プローブマーカーがエスケープ/除去/非表示化された (サイレントバックポートまたは強化) |
likely_patched 🟢 | バージョンが非表示/不明だが、プローブマーカーがエスケープ/除去された |
patched 🟢 | バージョンが latest または outdated (セキュリティバックポートあり) |
not_wordpress ⚫ | WordPressのフィンガープリントが検出されない |
unreachable ⚫ | 接続失敗 (タイムアウト、SSL、DNS) |
inconclusive 🟡 | WAFブロック、Cloudflareチャレンジ、プローブなしの非表示バージョン、またはログインページなし |
error 🟡 | スキャン中の予期しないエラー |