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(
'