Time-Based-Side-Channel-Attack on secrets – WP 2FA <= 2.3.0

| in

Affected pluginWP 2FA
Active installs30.000+
Vulnerable version<= 2.3.0.
Audited version2.0.0
Fully patched version
Recommended remediationRemoval of the plugin


The plugin uses string comparison operators that don’t mitigate time-based attacks in almost all places where secret keys are compared to user input.
A skilled attacker, given enough requests, can abuse this to reverse secrets using time-based-side-channel attacks.

Proof of concept

Validation of TOTP codes:

foreach ( $ticks as $offset ) {
    $log_time    = $time + $offset;
    $calculdated = (string) self::calc_totp( $key, $log_time );
    if ( $calculdated === $authcode ) {
        return true;
return false;

Validation of 2FA codes sent over email:

if ( empty( $hashed_token ) || ( wp_hash( $token ) !== $hashed_token ) ) {
    self::get_login_attempts_instance()->increase_login_attempts( $user );
    return false;

Validation of login nonces:

if ( $nonce !== $login_nonce['key'] || time() > $login_nonce['expiration'] ) {
    self::delete_login_nonce( $user_id );
    return false;

Proposed patch

Exclusively use hash_equals to compare secrets.


Vendor contactedMay 30, 2022, (through WPScan)
First Response
Fully patched at
Publicly disclosedApril 24, 2023


  • WPScan assigned a CVE for this vulnerability but failed to verify that all instances of unsafe string comparison had been fixed (Only 1/3).
  • The vendor does not seem to see this as a security concern, as even after patching the relevant code, they left the below comment:

“This code is here just because people have no idea what is the difference between preaching and real life.”

Source code on github.com

Leave a Reply

Your email address will not be published. Required fields are marked *