PluginProbe
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… / 2.11.8
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… v2.11.8
3.0.0 2.11.12 2.11.11 2.11.10 2.11.9 2.11.7 2.11.8 2.11.6 2.11.5 2.11.4 2.11.3 2.11.1 2.11.2 2.11.0 2.10.5 2.10.4 2.10.3 2.10.2 2.10.1 2.10.0 2.9.9 2.9.8 2.9.6 2.9.7 2.9.5 All 88 releases
← All changes | includes/class-user-security.php +25 -10 2.11.32.11.8 View file →
@@ -2051,9 +2051,15 @@
2051 2051
2052 2052 // Honor both affected_roles AND the per-user exclusion list, and
2053 2053 // clear stale flags if the user no longer matches the rules.
2054 2054 if ( ! $this->is_password_expiration_applicable( $user_id ) ) {
2055 - if ( get_user_meta( $user_id, 'vigilante_must_change_password', true ) ) {
2055 + // Only on a single site, for the same reason as in
2056 + // force_password_change_redirect(): on a network the flag belongs to
2057 + // the account, and this site's policy says nothing about the site
2058 + // that set it. The 2.11.8 fix only covered that method, and this
2059 + // notice cleared the flag anyway on the next admin page; found by
2060 + // the cross review of 2.11.8.
2061 + if ( ! is_multisite() && get_user_meta( $user_id, 'vigilante_must_change_password', true ) ) {
2056 2062 delete_user_meta( $user_id, 'vigilante_must_change_password' );
2057 2063 }
2058 2064 return;
2059 2065 }
@@ -2146,9 +2152,16 @@
2146 2152 // excluded list after the flag was set. Without this check the flag
2147 2153 // outlives the configuration change and locks the user in a redirect
2148 2154 // loop into profile.php.
2149 2155 if ( ! $this->is_password_expiration_applicable( $user_id ) ) {
2150 - delete_user_meta( $user_id, 'vigilante_must_change_password' );
2156 + // On a network the flag is a user meta that every site shares, and the
2157 + // policy just checked is only this site's: another site may have set
2158 + // it, and clearing it here let a user skip that site's forced change
2159 + // by visiting any other dashboard. It is only cleared on a single
2160 + // site (2.11.8); on a network the user is just not redirected here.
2161 + if ( ! is_multisite() ) {
2162 + delete_user_meta( $user_id, 'vigilante_must_change_password' );
2163 + }
2151 2164 return;
2152 2165 }
2153 2166
2154 2167 wp_safe_redirect( admin_url( 'profile.php#password' ) );
@@ -2693,20 +2706,22 @@
2693 2706 wp_safe_redirect( add_query_arg( 'vigilante_message', 'invalid', wp_login_url() ) );
2694 2707 exit;
2695 2708 }
2696 2709
2697 - $stored_hash = get_user_meta( $user_id, 'vigilante_verification_token', true );
2698 - $expires = get_user_meta( $user_id, 'vigilante_verification_expires', true );
2710 + $stored_hash = (string) get_user_meta( $user_id, 'vigilante_verification_token', true );
2711 + $expires = (int) get_user_meta( $user_id, 'vigilante_verification_expires', true );
2699 2712
2700 - // Check expiration
2701 - if ( time() > $expires ) {
2702 - wp_safe_redirect( add_query_arg( 'vigilante_message', 'expired', wp_login_url() ) );
2713 + // The token first. Checking the expiry before it answered "expired" for
2714 + // any account with no verification pending and "invalid" for one waiting,
2715 + // so a wrong link revealed which user ids were waiting (2.11.8). Only the
2716 + // holder of the right token learns that it expired.
2717 + if ( '' === $stored_hash || ! hash_equals( $stored_hash, wp_hash( $token ) ) ) {
2718 + wp_safe_redirect( add_query_arg( 'vigilante_message', 'invalid', wp_login_url() ) );
2703 2719 exit;
2704 2720 }
2705 2721
2706 - // Verify token
2707 - if ( ! hash_equals( $stored_hash, wp_hash( $token ) ) ) {
2708 - wp_safe_redirect( add_query_arg( 'vigilante_message', 'invalid', wp_login_url() ) );
2722 + if ( time() > $expires ) {
2723 + wp_safe_redirect( add_query_arg( 'vigilante_message', 'expired', wp_login_url() ) );
2709 2724 exit;
2710 2725 }
2711 2726
2712 2727 // Mark as verified