From 582b17cd181ce322bb0fabf0b95f1f0e0de4326e Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Thu, 12 Mar 2026 14:35:08 +0700 Subject: [PATCH 1/3] Fix. Auth. Edits to the Password Leak functionality --- inc/spbc-auth.php | 60 +++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/inc/spbc-auth.php b/inc/spbc-auth.php index b72e06b0c..927f67526 100644 --- a/inc/spbc-auth.php +++ b/inc/spbc-auth.php @@ -3,7 +3,6 @@ use CleantalkSP\SpbctWP\Counters\SecurityCounter; use CleantalkSP\SpbctWP\Firewall\WafBlocker; use CleantalkSP\SpbctWP\G2FA\GoogleAuthenticator; -use CleantalkSP\SpbctWP\UsersPassCheckModule\UsersPassCheckModel; use CleantalkSP\SpbctWP\Variables\Cookie; use CleantalkSP\SpbctWP\Helpers\IP; use CleantalkSP\Variables\Get; @@ -231,10 +230,18 @@ function spbc_authenticate($user, $username) // Redirect if password is leaked if (UsersPassCheckHandler::isUserPassLeaked($user->ID)) { - wp_redirect( + // Set auth cookie before redirect to ensure user is logged in + wp_set_auth_cookie($user->ID); + spbc_authenticate__write_log_login($user); + if (spbc_authenticate__is_new_device($user)) { + spbc_authenticate__browser_sign__set($user); + } + spbc_authenticate__user_agent__set($user); + + wp_safe_redirect( wp_login_url() . ( strpos(wp_login_url(), '?') === false ? '?' : '&' ) - . 'spbc_passleak=' . rawurlencode($user->user_login) + . 'spbc_passleak=1' ); die(); } @@ -544,29 +551,33 @@ function spbc_passleak_change_password_form() { global $spbc; - $user = null; + // Check if spbc_passleak parameter is present + $has_passleak_param = false; if (isset($_GET['spbc_passleak'])) { - $user = $_GET['spbc_passleak']; + $has_passleak_param = true; } else { // Fallback to parsing REQUEST_URI if $_GET is empty because of .htaccess settings $request_uri = filter_input(INPUT_SERVER, 'REQUEST_URI', FILTER_SANITIZE_URL); if ($request_uri) { $params = []; parse_str(parse_url($request_uri, PHP_URL_QUERY) ?: '', $params); - $user = isset($params['spbc_passleak']) ? $params['spbc_passleak'] : null; + $has_passleak_param = isset($params['spbc_passleak']); } } - if (!$user) { + if (!$has_passleak_param) { return; } - $user_name = rawurldecode($user); - $user = spbc_get_user_by('login', $user_name); + // User must be logged in to see the password change form + $current_user = wp_get_current_user(); + if (!$current_user || !$current_user->ID) { + return; + } - if (!$user) { - wp_redirect(home_url()); - exit; + // Only show form if current user's password is actually leaked + if (!UsersPassCheckHandler::isUserPassLeaked($current_user->ID)) { + return; } // Error displaying @@ -596,7 +607,6 @@ function spbc_passleak_change_password_form() . '' . '' . '' - . '' . '

' . '

' . '

' @@ -620,7 +630,6 @@ function spbc_passleak_change_password_form() function spbc_passleak_change_password_handler() { - $user_name = Post::getString('spbc_passleak_user'); $password_new = Post::getString('pass1'); $password_confirm = Post::getString('pass2'); $password_current = Post::getString('spbc_passleak_current'); @@ -632,20 +641,25 @@ function spbc_passleak_change_password_handler() wp_die(__('Invalid nonce', 'security-malware-firewall')); } - $user = spbc_get_user_by('login', $user_name); - if (!$user) { - wp_die(__('User not found', 'security-malware-firewall')); + // User must be logged in + $user = wp_get_current_user(); + if (!$user || !$user->ID) { + wp_safe_redirect(wp_login_url()); + exit; } - if ( ! UsersPassCheckModel::isUserPassLeaked($user->ID)) { - wp_safe_redirect(wp_login_url()); + $user_name = $user->user_login; + + if (!UsersPassCheckHandler::isUserPassLeaked($user->ID)) { + wp_safe_redirect(admin_url()); + exit; } if ($password_new !== $password_confirm) { - wp_redirect( + wp_safe_redirect( wp_login_url() . ( strpos(wp_login_url(), '?') === false ? '?' : '&' ) - . 'spbc_passleak=' . rawurlencode($user_name) + . 'spbc_passleak=1' . '&spbc_passleak_error=1' ); die(); @@ -653,10 +667,10 @@ function spbc_passleak_change_password_handler() // check if current password is correct if (!wp_check_password($password_current, $user->user_pass)) { - wp_redirect( + wp_safe_redirect( wp_login_url() . ( strpos(wp_login_url(), '?') === false ? '?' : '&' ) - . 'spbc_passleak=' . rawurlencode($user_name) + . 'spbc_passleak=1' . '&spbc_passleak_error=2' ); die(); From b360f58824ae0e3467ff95f7cebfe109396e0a4a Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Fri, 13 Mar 2026 15:07:10 +0700 Subject: [PATCH 2/3] Fix. Auth. Accounting for 2FA when setting authorization cookies --- inc/spbc-auth.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/inc/spbc-auth.php b/inc/spbc-auth.php index 927f67526..8e76c5fe7 100644 --- a/inc/spbc-auth.php +++ b/inc/spbc-auth.php @@ -125,10 +125,11 @@ function spbc_login_form_notification() * * @param WP_User|WP_Error $user * @param string $username + * @param string $password * * @return WP_Error|WP_User */ -function spbc_authenticate($user, $username) +function spbc_authenticate($user, $username, $password = '') { global $spbc; @@ -230,8 +231,11 @@ function spbc_authenticate($user, $username) // Redirect if password is leaked if (UsersPassCheckHandler::isUserPassLeaked($user->ID)) { - // Set auth cookie before redirect to ensure user is logged in - wp_set_auth_cookie($user->ID); + // Use wp_signon to ensure proper authentication flow (including 2FA) + wp_signon([ + 'user_login' => $user->user_login, + 'user_password' => $password + ]); spbc_authenticate__write_log_login($user); if (spbc_authenticate__is_new_device($user)) { spbc_authenticate__browser_sign__set($user); From 9028b37b3409b8295852e631e6c3139a8e6dd14d Mon Sep 17 00:00:00 2001 From: AntonV1211 Date: Sat, 21 Mar 2026 02:37:24 +0700 Subject: [PATCH 3/3] Mod. Auth. Mandatory password change, rate limit --- inc/spbc-auth.php | 210 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 190 insertions(+), 20 deletions(-) diff --git a/inc/spbc-auth.php b/inc/spbc-auth.php index 8e76c5fe7..ad3fff8ce 100644 --- a/inc/spbc-auth.php +++ b/inc/spbc-auth.php @@ -17,7 +17,7 @@ die('Not allowed!'); } -add_filter('authenticate', 'spbc_authenticate', 20, 3); // Hooks for authentificate +add_filter('authenticate', 'spbc_authenticate', 20, 2); // Hooks for authentificate // Hook for token-based logins (plugins like "Temporary Login Without Password") add_action('set_logged_in_cookie', 'spbc_detect_token_login', 10, 6); @@ -29,6 +29,10 @@ add_action('profile_update', [UsersPassCheckHandler::class, 'removeUserPassOnPasswordChange'], 10, 1); add_action('login_form', 'spbc_passleak_change_password_form', 10); add_action('login_form_login', 'spbc_passleak_change_password_handler', 3); + // Clear flag on standard password reset + add_action('after_password_reset', 'spbc_passleak__clear_flag_on_reset', 10, 1); + // Global guards for forced password change + add_action('admin_init', 'spbc_passleak__force_password_change_guard', 1); } add_action('login_errors', 'spbc_fix_error_messages', 99999); // Filters error message @@ -129,7 +133,7 @@ function spbc_login_form_notification() * * @return WP_Error|WP_User */ -function spbc_authenticate($user, $username, $password = '') +function spbc_authenticate($user, $username) { global $spbc; @@ -229,25 +233,10 @@ function spbc_authenticate($user, $username, $password = '') die(); } - // Redirect if password is leaked + // Set force password change flag if password is leaked + // Guard (spbc_passleak__force_password_change_guard) will redirect to password change form if (UsersPassCheckHandler::isUserPassLeaked($user->ID)) { - // Use wp_signon to ensure proper authentication flow (including 2FA) - wp_signon([ - 'user_login' => $user->user_login, - 'user_password' => $password - ]); - spbc_authenticate__write_log_login($user); - if (spbc_authenticate__is_new_device($user)) { - spbc_authenticate__browser_sign__set($user); - } - spbc_authenticate__user_agent__set($user); - - wp_safe_redirect( - wp_login_url() - . ( strpos(wp_login_url(), '?') === false ? '?' : '&' ) - . 'spbc_passleak=1' - ); - die(); + update_user_meta($user->ID, 'spbc_force_password_change', 1); } spbc_authenticate__write_log_login($user); @@ -390,6 +379,12 @@ function spbc_detect_token_login($_logged_in_cookie, $_expire, $_expiration, $us // Mark as logged to prevent any further duplicate logging $spbc_login_logged = true; + // Check if password is leaked for token-based logins + if (UsersPassCheckHandler::isUserPassLeaked($user->ID)) { + // Set force password change flag + update_user_meta($user->ID, 'spbc_force_password_change', 1); + } + // Sends logs to get notify about superuser login. $result = spbc_send_logs(); if (empty($result['error'])) { @@ -593,6 +588,9 @@ function spbc_passleak_change_password_form() if ($_GET['spbc_passleak_error'] == '2') { $err .= __('Current password is incorrect.', 'security-malware-firewall'); } + if ($_GET['spbc_passleak_error'] == '3') { + $err .= __('Too many attempts. Please, try again later.', 'security-malware-firewall'); + } echo sprintf( '