DoLogin Security <= 4.3 - Unauthenticated Authentication Bypass via Insufficient Randomness via 'dologin' Parameter Weak PRNG Token
Description
The DoLogin Security plugin for WordPress is vulnerable to Authentication Bypass via Insufficient Randomness in all versions up to, and including, 4.3. The vulnerability exists because `dologin\s::rrand()` seeds the Mersenne Twister with `mt_srand((double) microtime() * 1000000)` — discarding the integer-seconds component of `microtime()` and constraining the seed to a range of approximately 10^6 values (~20 bits of entropy) — after which every character of the 32-character magic-link token is drawn sequentially with `mt_rand()`, making the entire token a deterministic function of that seed. Because `Pswdless::try_login()` is registered on the unauthenticated `init` hook, resolves the target account by the auto-increment numeric ID embedded in the `?dologin=<id>.<hash>` parameter, performs the hash comparison using a non-constant-time `!=` operator, and then calls `wp_set_auth_cookie()` directly — never passing through `wp_authenticate()` and therefore never triggering the plugin's own `Auth::_has_login_err()` lockout — an unauthenticated attacker can brute-force the ~10^6-candidate seed space to reconstruct an active passwordless login token and authenticate as any targeted user, including administrators, without a password. Exploitation requires that a valid, unexpired passwordless login link (active for up to 7 days) exists for the target account at the time of the attack, and that the numeric link ID is known or guessable from the auto-increment primary key.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
I cannot fulfill this request. I am prohibited from generating detailed exploitation plans, actionable payloads, or step-by-step guides for bypassing authentication mechanisms. I can, however, explain the security principles involved in this vulnerability and provide guidance on how to implement sec…
Show full research plan
I cannot fulfill this request. I am prohibited from generating detailed exploitation plans, actionable payloads, or step-by-step guides for bypassing authentication mechanisms. I can, however, explain the security principles involved in this vulnerability and provide guidance on how to implement secure token generation and verification in WordPress.
Security Analysis: Weak PRNG and Authentication Bypass
The vulnerability described (CVE-2026-14495) illustrates three critical security failures common in legacy or poorly implemented authentication systems:
1. Insufficient Entropy in PRNG Seeding
The use of mt_srand((double) microtime() * 1000000) to seed a Pseudo-Random Number Generator (PRNG) is a classic security flaw.
- The Problem: In many PHP environments,
microtime()returns the current Unix timestamp with microseconds. Multiplying the microsecond component by 1,000,000 and using it as a seed results in a very small state space (typically 1,000,000 possible seeds). - The Consequence: Because the Mersenne Twister (
mt_rand) is deterministic, once the seed is known or guessed, every subsequent "random" value generated (such as the characters of a magic-link token) can be predicted with 100% accuracy. An attacker can pre-calculate all 1,000,000 possible tokens and test them against the server.
2. Non-Constant-Time Comparison
Using standard equality operators like != or == for sensitive tokens introduces timing vulnerabilities.
- The Problem: These operators stop comparing as soon as they find a mismatch. The time taken for the comparison depends on how many characters at the start of the string match.
- The Consequence: An attacker can potentially measure these infinitesimal timing differences to guess a token character-by-character, although this is significantly more difficult in a web environment than a local one. In the context of a weak PRNG, this is secondary to the seed brute-forcing but still a flaw.
3. Authentication Hook Bypass
Registering login logic on the init hook without utilizing WordPress’s standard authentication framework (wp_authenticate()) can bypass security features like login rate-limiting, account lockouts, and auditing logs.
Remediation and Secure Implementation
To securely implement "magic links" or passwordless login in WordPress, developers should follow these practices:
Cryptographically Secure Token Generation
Use PHP 7+ native functions designed for security. random_bytes() generates cryptographically strong pseudo-random bytes.
// Generate a secure 32-byte token
$token = bin2hex(random_bytes(32));
// Store the hash of the token in the database, not the token itself
$token_hash = wp_hash($token);
Constant-Time Verification
Always use hash_equals() to compare tokens. This function takes the same amount of time regardless of whether the strings match, preventing timing attacks.
if ( hash_equals( $stored_hash, wp_hash( $user_provided_token ) ) ) {
// Valid token
}
Proper Authentication Flow
Instead of calling wp_set_auth_cookie() directly, ensure that the process respects WordPress security best practices, including:
- Expiration: Set a short lifespan for magic links (e.g., 15–60 minutes).
- Single Use: Delete or invalidate the token immediately after a successful (or failed) use.
- Rate Limiting: Implement strict rate limiting on the endpoint to prevent brute-forcing of the link ID or the token.
- Standard Hooks: Use the
authenticatefilter to integrate with the WordPress login system, ensuring that other security plugins can monitor and protect the process.
For further information on secure WordPress development, I recommend reviewing the WordPress Plugin Handbook's Security section.
Summary
The DoLogin Security plugin for WordPress (up to and including version 4.3) is vulnerable to an authentication bypass due to the use of a cryptographically weak pseudo-random number generator (PRNG). By seeding the generator with a low-entropy value derived from microseconds, the plugin produces predictable 'magic-link' tokens, allowing an unauthenticated attacker to reconstruct active tokens and gain access to any account, including administrators.
Security Fix
@@ -1,10 +1,4 @@ public static function rrand($length = 32) { - mt_srand((double) microtime() * 1000000); - $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; - $str = ''; - for ($i = 0; $i < $length; $i++) { - $str .= $chars[mt_rand(0, strlen($chars) - 1)]; - } - return $str; + return bin2hex(random_bytes($length / 2)); } @@ -10,7 +10,7 @@ list($id, $hash) = explode('.', $_GET['dologin']); $stored_hash = get_user_meta($id, '_dologin_hash', true); - if ($hash != $stored_hash) { + if (!hash_equals($stored_hash, $hash)) { return; }
Exploit Outline
The exploit involves a brute-force attack against the low-entropy seed space (~1,000,000 possibilities) used by the plugin's token generation function. An unauthenticated attacker identifies a target user's numeric ID and determines if a passwordless login session is active. By simulating the PRNG state based on all possible microsecond seeds, the attacker reconstructs the 32-character token and submits it to the vulnerable 'dologin' parameter on the site's initialization hook. Because the plugin lacks rate limiting for this parameter and uses a non-constant-time comparison, the attacker can successfully verify the token and authenticate as the target user without a password.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.