Log mislukte logins als LOGIN_FAILED (fail2ban/rapportage), logger-threshold naar 5
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,9 +10,12 @@ class Logger extends BaseConfig
|
||||
/**
|
||||
* Error Logging Threshold
|
||||
*
|
||||
* 4 = emergency..error, 5 = also warning. 5 is required for the
|
||||
* LOGIN_FAILED lines (fail2ban jail app-login / security report).
|
||||
*
|
||||
* @var int|list<int>
|
||||
*/
|
||||
public $threshold = 4;
|
||||
public $threshold = 5;
|
||||
|
||||
/**
|
||||
* Date Format for Logs
|
||||
|
||||
@@ -24,6 +24,8 @@ class Login extends BaseController
|
||||
$user = \User::where('username', $username)->first();
|
||||
|
||||
if (!$user) {
|
||||
$this->logLoginFailed($username);
|
||||
|
||||
return $this->json(false);
|
||||
}
|
||||
|
||||
@@ -69,6 +71,8 @@ class Login extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
$this->logLoginFailed($username);
|
||||
|
||||
return $this->json($passwordCheck);
|
||||
}
|
||||
|
||||
@@ -169,6 +173,8 @@ class Login extends BaseController
|
||||
'message' => 'Succesvol geverifieerd'
|
||||
]);
|
||||
} else {
|
||||
$this->logLoginFailed($user->username ?: $userId . ':2fa');
|
||||
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'Ongeldige verificatiecode'
|
||||
@@ -308,4 +314,21 @@ class Login extends BaseController
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a rejected password or 2FA code in the format parsed by the
|
||||
* fail2ban jail `app-login` and the security report collector:
|
||||
* "LOGIN_FAILED user=<name> ip=<ip>". Never log the password or OTP.
|
||||
*
|
||||
* The IP is the real client IP only while the app runs directly behind
|
||||
* Apache. If Config\App::$proxyIPs is ever set, getIPAddress() resolves
|
||||
* the forwarded client IP and keeps this correct.
|
||||
*/
|
||||
private function logLoginFailed(string $user): void
|
||||
{
|
||||
log_message('warning', 'LOGIN_FAILED user={user} ip={ip}', [
|
||||
'user' => sanitize_log_user($user),
|
||||
'ip' => $this->request->getIPAddress(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,3 +329,16 @@ if (!function_exists('get_password_requirements_nl')) {
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!function_exists('sanitize_log_user')) {
|
||||
/**
|
||||
* Make a username safe for use in a log line (prevents log injection):
|
||||
* only [A-Za-z0-9_@.-+] is kept, everything else becomes "_", max 64 chars.
|
||||
*/
|
||||
function sanitize_log_user(string $user): string
|
||||
{
|
||||
$user = substr(preg_replace('/[^A-Za-z0-9_@.\-+]/', '_', $user), 0, 64);
|
||||
|
||||
return $user === '' ? '-' : $user;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user