CVE-2026-39519

GeekyBot — AI Copilot, Chatbot, WooCommerce Lead Gen & Zero-Prompt Content <= 1.2.0 - Unauthenticated SQL Injection

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.2.1
Patched in
6d
Time to patch

Description

The GeekyBot — AI Copilot, Chatbot, WooCommerce Lead Gen & Zero-Prompt Content plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.2.0 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.

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.2.0
PublishedApril 8, 2026
Last updatedApril 13, 2026
Affected plugingeeky-bot

What Changed in the Fix

Changes introduced in v1.2.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit an unauthenticated SQL injection vulnerability in the **GeekyBot** plugin for WordPress (versions <= 1.2.0). ### 1. Vulnerability Summary The GeekyBot plugin is vulnerable to SQL injection because it uses the `geekybot_chat_id` cookie value directly …

Show full research plan

This research plan outlines the steps to exploit an unauthenticated SQL injection vulnerability in the GeekyBot plugin for WordPress (versions <= 1.2.0).

1. Vulnerability Summary

The GeekyBot plugin is vulnerable to SQL injection because it uses the geekybot_chat_id cookie value directly in SQL queries without sanitization or parameterization via $wpdb->prepare(). Specifically, the value is retrieved via geekybot_getchatid() and concatenated into queries in includes/classes/geekybotsessiondata.php. Since this cookie can be set by any unauthenticated user, it provides a direct path for SQL injection.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: geekybot_process_message (unauthenticated AJAX action)
  • Vulnerable Parameter: geekybot_chat_id Cookie
  • Authentication: Unauthenticated
  • Preconditions: None. The plugin just needs to be active.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a request to admin-ajax.php with the action geekybot_process_message.
  2. AJAX Handler: The handler (likely in geeky-bot.php) calls the chatbot logic to process the message.
  3. Session Initialization: The code attempts to load or save session data using GEEKYBOTgeekybotsessiondata::geekybot_addSessionVariablesDataToTable or geekybot_getVariablesDatabySessionId (found in includes/classes/geekybotsessiondata.php).
  4. Source: These functions call GEEKYBOTchathistoryModel::geekybot_getchatid() which retrieves the value of $_COOKIE['geekybot_chat_id'].
  5. Sink: The value is concatenated into a raw SQL query string:
    // includes/classes/geekybotsessiondata.php
    $query = "SELECT sessionmsgvalue FROM `" . geekybot::$_db->prefix . "geekybot_sessiondata` 
              WHERE sessionmsgkey = '" . $key . "' 
              AND usersessionid = '" . $chatid . "' 
              AND sessionexpire > '" . time() . "'";
    $data = geekybotdb::GEEKYBOT_get_row($query);
    
  6. Execution: geekybotdb::GEEKYBOT_get_row executes the unsanitized query, leading to SQL injection.

4. Nonce Acquisition Strategy

The chatbot typically requires a nonce for its AJAX requests. This nonce is usually localized into the page's JavaScript.

  1. Identify Shortcode: The chatbot is often site-wide but may require the [geeky-bot] or [geekybot] shortcode.
  2. Create Page:
    wp post create --post_type=page --post_status=publish --post_content='[geekybot]'
  3. Navigate and Extract:
    • Use browser_navigate to visit the new page.
    • Use browser_eval to extract the nonce:
      // Common variable name for this plugin's
      
Research Findings
Static analysis — not yet PoC-verified

Summary

The GeekyBot plugin for WordPress is vulnerable to unauthenticated SQL injection due to the use of unsanitized values from the 'geekybot_chat_id' cookie in database queries. Attackers can manipulate this cookie to append arbitrary SQL commands to existing queries, potentially allowing for the extraction of sensitive information from the database.

Vulnerable Code

// includes/classes/geekybotsessiondata.php

public function geekybot_addSessionVariablesDataToTable($messages){
    // ... (lines 21-23)
    if(isset($_COOKIE['geekybot_chat_id'])){
        $chatid = GEEKYBOTincluder::GEEKYBOT_getModel('chathistory')->geekybot_getchatid();
        foreach ($messages as $key => $value) {
            $value = addslashes($value);
            if ($key != 'chathistory') {
                $data = $this->geekybot_getVariablesDatabySessionId($chatid, $key);
                if($data != ""){
                    $update = true;
                } else {
                    $update = false;
                }
                if(!$update){
                    $query = "INSERT INTO `" . geekybot::$_db->prefix . "geekybot_sessiondata` (`usersessionid`, `sessionmsgkey`, `sessionmsgvalue`, `sessionexpire`) VALUES ('".$chatid."', '".$key."', '".$value."', '".geekybot::$_geekybotsession->sessionexpire."');";
                    geekybot::$_db->query($query);
                }else{
                    $query = "UPDATE `" . geekybot::$_db->prefix . "geekybot_sessiondata` SET `sessionmsgvalue` = '".$value."' WHERE `usersessionid`= '" . $chatid . "' AND `sessionmsgkey`= '" . $key . "' ";
                    geekybotdb::query($query);
                }
            }
        }
    }
    return false;
}

---

// includes/classes/geekybotsessiondata.php

public function geekybot_getVariablesDatabySessionId($usersessionid, $key = '' , $deldata = false){
    $query = "SELECT sessionmsgvalue
        FROM `" . geekybot::$_db->prefix . "geekybot_sessiondata`  WHERE sessionmsgkey = '" . $key . "' AND usersessionid = '" . $usersessionid . "' AND sessionexpire > '" . time() . "'";
    $data = geekybotdb::GEEKYBOT_get_row($query);
    if($deldata){
        $query = "DELETE FROM `".geekybot::$_db->prefix . "geekybot_sessiondata` WHERE usersessionid = '".$usersessionid."' ";
        geekybotdb::query($query);
    }
    return $data;
}

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/geeky-bot/1.2.0/includes/classes/geekybotsessiondata.php	2026-02-13 04:41:36.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/geeky-bot/1.2.1/includes/classes/geekybotsessiondata.php	2026-03-04 04:57:30.000000000 +0000
@@ -21,9 +21,13 @@
         $update = false;
         if(isset($_COOKIE['geekybot_chat_id'])){
             $chatid = GEEKYBOTincluder::GEEKYBOT_getModel('chathistory')->geekybot_getchatid();
+            $chatid = esc_sql( sanitize_text_field($chatid) );
             foreach ($messages as $key => $value) {
                 $value = addslashes($value);
                 if ($key != 'chathistory') {
+                    $key   = esc_sql( sanitize_text_field($key) );
+                    $value = esc_sql( sanitize_text_field($value) );
+
                     $data = $this->geekybot_getVariablesDatabySessionId($chatid, $key);
                     if($data != ""){
                         $update = true;
@@ -31,7 +35,8 @@
                         $update = false;
                     }
                     if(!$update){
-                        $query = "INSERT INTO `" . geekybot::$_db->prefix . "geekybot_sessiondata` (`usersessionid`, `sessionmsgkey`, `sessionmsgvalue`, `sessionexpire`) VALUES ('".$chatid."', '".$key."', '".$value."', '".geekybot::$_geekybotsession->sessionexpire."');";
+                        $sessionexpire = esc_sql( sanitize_text_field(geekybot::$_geekybotsession->sessionexpire) );
+                        $query = "INSERT INTO `" . geekybot::$_db->prefix . "geekybot_sessiondata` (`usersessionid`, `sessionmsgkey`, `sessionmsgvalue`, `sessionexpire`) VALUES ('".$chatid."', '".$key."', '".$value."', '".$sessionexpire."');";
                         geekybot::$_db->query($query);
                     }else{
                         $query = "UPDATE `" . geekybot::$_db->prefix . "geekybot_sessiondata` SET `sessionmsgvalue` = '".$value."' WHERE `usersessionid`= '" . $chatid . "' AND `sessionmsgkey`= '" . $key . "' ";
@@ -60,8 +76,14 @@
     }
 
     public function geekybot_getVariablesDatabySessionId($usersessionid, $key = '' , $deldata = false){
+        $usersessionid = esc_sql( sanitize_text_field($usersessionid) );
+        $key           = esc_sql( sanitize_text_field($key) );
+        $time          = time();
+
         $query = "SELECT sessionmsgvalue
-            FROM `" . geekybot::$_db->prefix . "geekybot_sessiondata`  WHERE sessionmsgkey = '" . $key . "' AND usersessionid = '" . $usersessionid . "' AND sessionexpire > '" . time() . "'";
+            FROM `" . geekybot::$_db->prefix . "geekybot_sessiondata`  WHERE sessionmsgkey = '" . $key . "' AND usersessionid = '" . $usersessionid . "' AND sessionexpire > '" . $time . "'";
+
         $data = geekybotdb::GEEKYBOT_get_row($query);
         if($deldata){
             $query = "DELETE FROM `".geekybot::$_db->prefix . "geekybot_sessiondata` WHERE usersessionid = '".$usersessionid."' ";

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker needs to follow these steps: 1. **Locate Interaction Point**: Identify a page on the target WordPress site where the GeekyBot chatbot is active. This is common if the site uses the `[geekybot]` shortcode or has the chatbot globally enabled. 2. **Craft Payload**: Prepare a malicious SQL payload designed to extract data or cause delays (e.g., using `UNION SELECT` or boolean-based techniques). 3. **Set Cookie**: Inject the payload into the `geekybot_chat_id` cookie. Since the plugin retrieves this cookie via `geekybot_getchatid()` and concatenates it directly into SQL queries within `includes/classes/geekybotsessiondata.php`, the payload will be executed. 4. **Trigger Execution**: Send an AJAX request to `/wp-admin/admin-ajax.php` with the action `geekybot_process_message`. This action triggers the chatbot logic, which subsequently calls session management functions that utilize the malicious cookie value in database queries. 5. **Data Extraction**: Observe the server's response or use time-based analysis (if using a sleep-based payload) to confirm the execution of the injected SQL and extract database information.

Check if your site is affected.

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