Post SMTP <= 3.8.0 - Missing Authorization to Authenticated (Subscriber+) Office 365 OAuth Configuration Overwrite
Description
The Post SMTP plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the `handle_office365_oauth_redirect()` function in all versions up to, and including, 3.8.0. This is due to the function being hooked to `admin_init` without any `current_user_can()` check or nonce verification. This makes it possible for authenticated attackers, with Subscriber-level access and above, to overwrite the site's Office 365 OAuth mail configuration (access token, refresh token, and user email) via a crafted URL. The configuration option is used during wizard setup of Microsoft365 SMTP, only available in the Pro option of the plugin. This could cause an Administrator to believe an attacker-controlled Azure app is their own, and lead them to connect the plugin to the attacker's account during configuration after upgrading to Pro.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:NTechnical Details
What Changed in the Fix
Changes introduced in v3.9.0
Source Code
WordPress.org SVNThis research plan focuses on exploiting a missing authorization vulnerability in the **Post SMTP** plugin, specifically in the OAuth configuration handling for Microsoft 365. ### 1. Vulnerability Summary The vulnerability exists in the `handle_office365_oauth_redirect()` function (inferred to be l…
Show full research plan
This research plan focuses on exploiting a missing authorization vulnerability in the Post SMTP plugin, specifically in the OAuth configuration handling for Microsoft 365.
1. Vulnerability Summary
The vulnerability exists in the handle_office365_oauth_redirect() function (inferred to be located in the Office 365 transport module). This function is hooked to admin_init, a hook that runs whenever a user (including a Subscriber) accesses a page in the /wp-admin/ directory. The function fails to implement any current_user_can( 'manage_options' ) capability check or nonce verification. Consequently, any authenticated user can trigger the function by visiting a crafted URL, allowing them to overwrite the site's email configuration with attacker-controlled Azure/Office 365 OAuth tokens.
2. Attack Vector Analysis
- Entry Point:
admin_inithook. - Vulnerable Function:
handle_office365_oauth_redirect()(called on every admin page load). - Authentication: Authenticated (Subscriber or higher).
- Payload Location: GET parameters.
- Preconditions: The site must have the Office 365 transport mechanism available (typically part of the Pro/Premium features, but the hook registration often exists in the core code).
3. Code Flow
- Initialization: The plugin initializes and registers various hooks.
- Hook Registration: The function
handle_office365_oauth_redirectis hooked toadmin_init.- Note: In
Postman/Dashboard/NewDashboard.php, we see standard dashboard initialization, but the vulnerable hook typically resides in the transport-specific logic.
- Note: In
- Trigger: A Subscriber-level user logs in and navigates to
/wp-admin/index.php?page=postman&action=office365_auth_callback&.... - Execution:
admin_initfires. The plugin checks if the relevant GET parameters (likeactionorcode) are present. - Sink: The function processes the tokens provided in the URL and calls
update_option( 'postman_options', ... )to save the new (malicious)access_token,refresh_token, anduser_emailwithout verifying the user's authority.
4. Nonce Acquisition Strategy
According to the vulnerability description, this specific function missing nonce verification. Therefore, no nonce is required to trigger the overwrite.
However, if a researcher needs to verify other parts of the dashboard or REST API (as seen in NewDashboard.php):
- The plugin localizes the nonce in
NewDashboard.phpinside theadmin_enqueue_scriptsmethod. - JS Variable:
window.postSmtpNewDashboard - Nonce Key:
nonce - Acquisition:
- Create a page with a Subscriber user.
- Access the Post SMTP dashboard (if Subscriber has access) or the main admin dashboard where scripts are enqueued.
- Execute:
browser_eval("window.postSmtpNewDashboard?.nonce").
5. Exploitation Strategy
The goal is to overwrite the Microsoft 365 SMTP configuration with attacker-controlled tokens.
Step-by-Step:
- Log in as Subscriber: Use the
http_requesttool to authenticate. - Craft the Request: The URL must include the trigger parameters for the Office 365 OAuth callback. Based on the vulnerability description and common Post SMTP patterns:
- Endpoint:
/wp-admin/index.php - Parameters:
page:postmanaction:postman_office365_oauth_callback(inferred)access_token:EVIL_ACCESS_TOKENrefresh_token:EVIL_REFRESH_TOKENuser_email:attacker@evil-domain.com
- Endpoint:
- Execute the Overwrite:
# Payload GET /wp-admin/index.php?page=postman&action=postman_office365_oauth_callback&access_token=AT-999&refresh_token=RT-999&user_email=attacker@evil.com
6. Test Data Setup
- Install Plugin: Post SMTP <= 3.8.0.
- Create User: A user with the
subscriberrole. - Initial State: Configure the plugin to use any transport (e.g., PHPMailer) so that
postman_optionsexists in the database. - Enable Pro (Optional/Simulated): If the code path is restricted to Pro users, ensure
is_plugin_active( 'post-smtp-pro/post-smtp-pro.php' )returns true viawp plugin activateif available, or simply verify theadmin_inithook is registered in the core.
7. Expected Results
- HTTP Response: A
200 OKor a302 Redirectback to the settings page. - Data Change: The
postman_optionsentry in thewp_optionstable will now contain theaccess_token,refresh_token, anduser_emailprovided in the GET request.
8. Verification Steps
After sending the request, use WP-CLI to inspect the plugin's settings:
# Check the postman_options for the injected values
wp option get postman_options --format=json | jq .
Verify that the user_email is attacker@evil.com and tokens match the payload.
9. Alternative Approaches
If the action parameter postman_office365_oauth_callback does not trigger the function, try alternative triggers discovered by searching the source for the handle_office365_oauth_redirect string:
?office365_auth_callback=1...?page=postman&state=office365...
The key is that admin_init handlers often look for a specific flag in $_GET to determine if they should process an OAuth return. Once the flag is found, the missing capability check allows the overwrite.
Summary
The Post SMTP plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the handle_office365_oauth_redirect() function. This function is hooked to admin_init without any capability or nonce verification, allowing authenticated users with Subscriber-level access or higher to overwrite the site's Office 365 OAuth email configuration via a crafted URL.
Security Fix
@@ -1,34 +1,43 @@ +/*!***************************************************************!*\ + !*** css ./node_modules/css-loader/dist/cjs.js!./src/app.css ***!\ + \***************************************************************/ @import url(https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap); +/*!**************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/vue-loader/dist/stylePostLoader.js!./node_modules/vue-loader/dist/index.js??ruleSet[1].rules[6].use[0]!./src/components/post-smtp-app-wrapper.vue?vue&type=style&index=0&id=7c6051c6&scoped=true&lang=css ***!\ + \**************************************************************************************************************************************************************************************************************************************************************************/
Exploit Outline
To exploit this vulnerability, an attacker must first authenticate with Subscriber-level privileges or higher. The attacker then crafts a URL targeting any administrative page (like /wp-admin/index.php) to trigger the 'admin_init' hook. The URL must include specific GET parameters that the plugin's OAuth redirect handler looks for (inferred as 'page=postman' and an action like 'postman_office365_oauth_callback'), along with malicious 'access_token', 'refresh_token', and 'user_email' values. Because the handler lacks nonce verification and capability checks (e.g., current_user_can('manage_options')), the plugin will process the request and overwrite the site's global 'postman_options' configuration with the attacker-supplied tokens.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.