Product Filter for WooCommerce by WBW < 3.1.3 - Unauthenticated SQL Injection
Description
The Product Filter for WooCommerce by WBW plugin for WordPress is vulnerable to SQL Injection in versions up to 3.1.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
<3.1.3What Changed in the Fix
Changes introduced in v3.1.3
Source Code
WordPress.org SVNThis analysis targets an unauthenticated SQL injection vulnerability in the **Product Filter for WooCommerce by WBW** plugin (version < 3.1.3). The vulnerability stems from improper sanitization and lack of query preparation when processing filter parameters in the frontend AJAX request. ### 1. Vul…
Show full research plan
This analysis targets an unauthenticated SQL injection vulnerability in the Product Filter for WooCommerce by WBW plugin (version < 3.1.3). The vulnerability stems from improper sanitization and lack of query preparation when processing filter parameters in the frontend AJAX request.
1. Vulnerability Summary
The vulnerability exists in the WoofiltersControllerWpf class within the modules/woofilters/controller.php file. Specifically, the filtersFrontend() method processes user-supplied JSON data from the filtersDataBackend and queryvars parameters. This data is passed into SQL-building functions that utilize the _prepareTextLikeSearch() method, which performs direct string concatenation of user input into a SQL LIKE clause without using $wpdb->prepare() or sufficient escaping.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpf_ajax - Query Parameters:
pl=wpf,mod=woofilters,task=filtersFrontend - POST Parameters:
filtersDataBackend: A JSON-encoded array containing filter configurations.queryvars: A JSON-encoded object containing WooCommerce query arguments.
- Authentication: None required (Unauthenticated).
- Preconditions: At least one product must exist in WooCommerce for the filter logic to execute its database queries.
3. Code Flow
- Entry: A request is sent to
admin-ajax.phpwithaction=wpf_ajax. - Routing:
FrameWpf::parseRoute()(inclasses/frame.php) extractsmod=woofiltersandtask=filtersFrontend. - Execution:
FrameWpf::exec()callsWoofiltersControllerWpf::filtersFrontend(). - Processing:
filtersFrontend()decodes thefiltersDataBackendJSON. - Vulnerable Sink: The controller logic (via
createArgsForFiltering) processes search-type filters using_prepareTextLikeSearch($val)(line 15 ofmodules/woofilters/controller.php):protected function _prepareTextLikeSearch( $val ) { $query = '(title LIKE "%' . $val . '%"'; // <--- SQL INJECTION POINT if ( is_numeric($val) ) { $query .= ' OR id LIKE "%' . (int) $val . '%"'; } $query .= ')'; return $query; } - Query Execution: The resulting unescaped string is added to the model's
WHEREclause via$model->addWhere(array('additionalCondition' => $query))and executed against the database.
4. Nonce Acquisition Strategy
While filtersFrontend does not strictly enforce a nonce check (making it unauthenticated), the plugin often localizes a nonce for other frontend features. If an environment requires a nonce for all wpf_ajax actions, use the following:
- Shortcode: The plugin uses
[wpf-filters id=...]. - Setup: Create a filter and a page containing its shortcode.
wp post create --post_type=wpf_filters --post_title="Exploit Filter" --post_status=publish # Note the ID of the new post (e.g., 123) wp post create --post_type=page --post_title="Filter Page" --post_content="[wpf-filters id=123]" --post_status=publish - Extraction: Use
browser_navigateto the new page andbrowser_evalto extract the localized settings:// WBW typically localizes data into a variable named after the plugin/module // Look for 'wpfNonce' in the localized object window.wpfFrontendPage?.nonce || window.wpfMainWrapper?.wpfNonce
5. Exploitation Strategy
We will use a time-based blind SQL injection payload within the filtersDataBackend JSON structure, targeting the search filter logic.
**HTTP Request (via `http_
Summary
The Product Filter for WooCommerce by WBW plugin is vulnerable to unauthenticated SQL injection due to the improper concatenation of user-supplied data into SQL queries. Attackers can exploit this via the filtersFrontend AJAX action to extract sensitive database information or perform time-based blind attacks.
Vulnerable Code
// modules/woofilters/controller.php around line 15 protected function _prepareTextLikeSearch( $val ) { $query = '(title LIKE "%' . $val . '%"'; if ( is_numeric($val) ) { $query .= ' OR id LIKE "%' . (int) $val . '%"'; } $query .= ')'; return $query; }
Security Fix
@@ -406,14 +408,19 @@ /** * _doExec. + * + * @version 3.1.3 */ protected function _doExec() { $mod = $this->getModule($this->_mod); if ($mod && $this->checkPermissions($this->_mod, $this->_action)) { switch (ReqWpf::getVar('reqType')) { case 'ajax': - add_action('wp_ajax_' . $this->_action, array($mod->getController(), $this->_action)); - add_action('wp_ajax_nopriv_' . $this->_action, array($mod->getController(), $this->_action)); + add_action('wp_ajax_' . $this->_action, array($mod->getController(), $this->_action)); + $noprivActions = array( 'filtersFrontend', 'getTaxonomyTerms' ); + if ( in_array( $this->_action, $noprivActions ) ) { + add_action('wp_ajax_nopriv_' . $this->_action, array($mod->getController(), $this->_action)); + } break; default: $this->_res = $mod->exec($this->_action);
Exploit Outline
The exploit targets the unauthenticated AJAX endpoint 'wpf_ajax' with the 'filtersFrontend' task. An attacker sends a POST request to '/wp-admin/admin-ajax.php' with the parameter 'pl=wpf', 'mod=woofilters', and 'task=filtersFrontend'. The payload is embedded within the 'filtersDataBackend' JSON parameter, specifically within a search-type filter value. Because the plugin concatenates this value directly into a LIKE clause in the '_prepareTextLikeSearch' method without using $wpdb->prepare() or escaping, an attacker can use a payload like '") OR SLEEP(5)-- -' to trigger a time-based blind SQL injection.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.