CVE-2025-13587

Two Factor (2FA) Authentication via Email <= 1.9.8 - Two-Factor Authentication Bypass via token

mediumImproper Input Validation
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
1.9.9
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
High
Integrity
None
Availability

Technical Details

Affected versions<=1.9.8
PublishedFebruary 18, 2026
Last updatedFebruary 19, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# 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)

  1. Entry Point: A user submits credentials to wp-login.php.
  2. Hook Trigger: The plugin likely hooks into wp_login, authenticate, or login_form_login.
  3. Vulnerable Method: SS88_2FAVE::wp_login() is executed.
  4. 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
    }
    
  5. Bypass: By providing wp-login.php?token=anything, the isset check 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.

  1. Identify Target: Use a user account (e.g., subscriber_user) that has email 2FA enabled.
  2. Craft Login Request: Perform a POST request to wp-login.php with the token parameter in the URL.
  3. 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
  4. 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.

6. Test Data Setup

  1. Install Plugin: Ensure two-factor-2fa-via-email version 1.9.8 is installed.
  2. Create User:
    wp user create victim victim@example.com --user_pass=password123 --role=subscriber
    
  3. Enable 2FA:
    • Use wp option or wp user meta to enable 2FA for the user.
    • Based on the plugin slug, check for meta keys like _ss88_2fave_enabled or similar.
    • Alternative: Manually enable 2FA for the user in the WordPress dashboard under Users > Profile.
  4. 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 the token parameter) should result in a redirect or a page render asking for the 2FA code.

8. Verification Steps

  1. Check Cookies: After the http_request, verify that the returned cookies are valid for the victim user.
  2. 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]"
      }
    }
    
  3. 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 token in 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=1 triggers a bypass during the second stage of login.
Research Findings
Static analysis — not yet PoC-verified

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

--- a/includes/class-ss88-2fave.php
+++ b/includes/class-ss88-2fave.php
@@ -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.