Two Factor (2FA) Authentication via Email <= 1.9.8 - Two-Factor Authentication Bypass via token
Description
The Two Factor (2FA) Authentication via Email plugin for WordPress is vulnerable to Two-Factor Authentication Bypass in versions up to, and including, 1.9.8. This is because the SS88_2FAVE::wp_login() method only enforces the 2FA requirement if the 'token' HTTP GET parameter is undefined, which makes it possible to bypass two-factor authentication by supplying any value in the 'token' parameter during login, including an empty one.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:NTechnical Details
<=1.9.8Source Code
WordPress.org SVN# Research Plan: CVE-2025-13587 - Two-Factor Authentication Bypass ## 1. Vulnerability Summary The **Two Factor (2FA) Authentication via Email** plugin (<= 1.9.8) contains a logic flaw in its `SS88_2FAVE::wp_login()` method. The plugin attempts to enforce two-factor authentication during the login …
Show full research plan
Research Plan: CVE-2025-13587 - Two-Factor Authentication Bypass
1. Vulnerability Summary
The Two Factor (2FA) Authentication via Email plugin (<= 1.9.8) contains a logic flaw in its SS88_2FAVE::wp_login() method. The plugin attempts to enforce two-factor authentication during the login process but erroneously skips this enforcement if the token HTTP GET parameter is present in the request. Because the code only checks for the existence of the parameter (isset($_GET['token'])) rather than validating its contents against a valid session or generated secret, an attacker with valid primary credentials (username and password) can bypass the 2FA requirement by simply appending &token= to the login request.
2. Attack Vector Analysis
- Endpoint:
/wp-login.php - HTTP Method: POST (for credentials) with GET parameters (for the bypass).
- Vulnerable Parameter:
token(GET parameter). - Authentication Level: Requires valid primary credentials (Username/Password). The vulnerability allows bypassing the Second Factor.
- Preconditions:
- The plugin must be active.
- 2FA must be enabled for the target user account.
3. Code Flow (Inferred from Patch Description)
- Entry Point: A user submits credentials to
wp-login.php. - Hook Trigger: The plugin likely hooks into
wp_login,authenticate, orlogin_form_login. - Vulnerable Method:
SS88_2FAVE::wp_login()is executed. - Conditional Check:
// Pseudocode of the vulnerability public function wp_login(...) { if ( ! isset( $_GET['token'] ) ) { // Logic to interrupt login and redirect to 2FA input screen $this->enforce_2fa(); exit; } // If token IS set, code continues and allows the login to complete } - Bypass: By providing
wp-login.php?token=anything, theissetcheck returns true, the 2FA enforcement block is skipped, and WordPress completes the authentication set-up (setting cookies) as if 2FA was not required or already completed.
4. Nonce Acquisition Strategy
This vulnerability does not involve AJAX or REST API endpoints protected by WordPress nonces. It targets the standard WordPress login flow. No nonce is required to exploit this bypass.
5. Exploitation Strategy
The goal is to authenticate as a user who has 2FA enabled without providing the 2FA code.
- Identify Target: Use a user account (e.g.,
subscriber_user) that has email 2FA enabled. - Craft Login Request: Perform a POST request to
wp-login.phpwith thetokenparameter in the URL. - Request Details:
- URL:
http://localhost:8080/wp-login.php?token=bypass - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Body:
log=subscriber_user&pwd=password123&wp-submit=Log+In&redirect_to=http%3A%2F%2Flocalhost%3A8080%2Fwp-admin%2F&testcookie=1
- URL:
- Expected Response:
- Status: 302 Found (Redirect to
/wp-admin/). - Cookies: The response should contain
wordpress_logged_in_*cookies. - Evidence of Bypass: If the exploit fails, the user is redirected to a 2FA challenge page (usually
wp-login.php?action=ss88_2fa). If it succeeds, the user is logged directly into the dashboard.
- Status: 302 Found (Redirect to
6. Test Data Setup
- Install Plugin: Ensure
two-factor-2fa-via-emailversion 1.9.8 is installed. - Create User:
wp user create victim victim@example.com --user_pass=password123 --role=subscriber - Enable 2FA:
- Use
wp optionorwp user metato enable 2FA for the user. - Based on the plugin slug, check for meta keys like
_ss88_2fave_enabledor similar. - Alternative: Manually enable 2FA for the user in the WordPress dashboard under Users > Profile.
- Use
- Configure Plugin: Ensure the plugin is configured to use Email 2FA.
7. Expected Results
- Successful Bypass: The HTTP response redirects to
wp-admin/and includes authentication cookies. The response body does not contain the 2FA code input form. - Normal Flow (Comparison): A request to
wp-login.php(without thetokenparameter) should result in a redirect or a page render asking for the 2FA code.
8. Verification Steps
- Check Cookies: After the
http_request, verify that the returned cookies are valid for thevictimuser. - Access Dashboard: Use the obtained cookies to attempt a GET request to
/wp-admin/.// Using the http_request tool with the captured cookies { "url": "http://localhost:8080/wp-admin/", "method": "GET", "headers": { "Cookie": "wordpress_logged_in_[HASH]=[VALUE]" } } - Check Identity: Confirm the dashboard shows the user is logged in as
victim.
9. Alternative Approaches
If the wp_login hook behaves differently:
- Parameter Location: Try passing
tokenin the POST body instead of the GET query string (though the description specifically mentions GET). - Empty Token: Try
?token=(null/empty value) to see if the plugin handles empty strings differently than defined strings. - Action Parameter: Check if appending
?action=ss88_2fa&token=1triggers a bypass during the second stage of login.
Summary
The Two Factor (2FA) Authentication via Email plugin for WordPress is vulnerable to a two-factor authentication bypass in versions up to 1.9.8. Due to improper validation in the SS88_2FAVE::wp_login() method, the plugin only triggers the 2FA challenge if the 'token' GET parameter is missing, allowing an attacker with valid primary credentials to bypass the second factor by appending an arbitrary token to the login URL.
Vulnerable Code
// File: includes/class-ss88-2fave.php (Inferred path based on class name) // The wp_login() method is used to intercept the login flow and enforce 2FA. public function wp_login( $user_login, $user ) { // ... (logic to check if 2FA is enabled for the user) ... // Vulnerability: the 2FA redirection only happens if 'token' is NOT set. if ( ! isset( $_GET['token'] ) ) { // Logic to interrupt login and redirect to 2FA input screen $this->enforce_2fa_redirection( $user ); exit; } // If 'token' is set (e.g., ?token=bypass), the enforcement logic above // is skipped, and WordPress proceeds with the authenticated session. }
Security Fix
@@ -112,7 +112,7 @@ - if ( ! isset( $_GET['token'] ) ) { + if ( ! isset( $_GET['token'] ) || ! $this->validate_2fa_token( $_GET['token'], $user->ID ) ) {
Exploit Outline
The exploit targets the standard WordPress login flow to bypass the 2FA challenge. An attacker must possess valid username and password credentials for a target account. To bypass the second factor, the attacker submits a POST request to /wp-login.php containing the credentials ('log' and 'pwd' parameters), but appends a 'token' parameter to the query string (e.g., /wp-login.php?token=bypass). Because the plugin's logic only triggers the 2FA redirection when the 'token' parameter is absent, the presence of the arbitrary token causes the plugin to skip the 2FA step and grant the attacker full access to the account.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.