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:
2026-10-08 10:21:08 +02:00
co-authored by Claude Sonnet 5.5
parent 506c88a5bd
commit 643f5fd9a7
7 changed files with 188 additions and 1 deletions
+4 -1
View File
@@ -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
+23
View File
@@ -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(),
]);
}
}
+13
View File
@@ -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;
}
}