Refresh-Fehlschlag: Detection-Gap geschlossen (Pentest R164-01)
Fehlgeschlagener /auth/refresh (Replay/Brute-Force auf geraubte Refresh-Tokens) wurde als TOKEN_REFRESH/LOW geloggt und entging der Alarmierung - ein Angreifer konnte von /login auf /refresh ausweichen, um unter der LOGIN_FAILED-Schwelle zu bleiben. Audit-Actions speisen die Alert-Engine nicht (die zaehlt SecurityEvent via emit). Fix daher an zwei Ebenen: - Detection: refresh()-Catch emittiert TOKEN_REJECTED -> greift die bestehende Schwelle (>=3 TOKEN_REJECTED/5min/IP -> CRITICAL). Severity wie Access-Token: abgelaufen/revoked = LOW (kein Sofort-Alert), ungueltige Signatur/Manipulation = HIGH. auth.service reicht dafuer err.code REFRESH_EXPIRED/REFRESH_INVALID durch. "Kein Cookie" emittiert bewusst nicht (normaler Erstbesuch). - Audit-Triage: fehlgeschlagener Refresh -> Sensitivitaet HIGH statt LOW + Label "Token-Refresh abgelehnt". Action bleibt TOKEN_REFRESH (semantisch ein Refresh, kein Login). Verifiziert: tsx-Test abgelaufen->LOW, manipuliert/garbage->HIGH; tsc gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -286,8 +286,12 @@ export async function refreshAccessToken(refreshToken: string): Promise<{
|
||||
decoded = jwt.verify(refreshToken, process.env.JWT_SECRET as string, {
|
||||
algorithms: ['HS256'],
|
||||
});
|
||||
} catch {
|
||||
throw new Error('Refresh-Token ungültig oder abgelaufen');
|
||||
} catch (e) {
|
||||
// Code erhalten, damit der Controller abgelaufen (benigne, LOW) von
|
||||
// manipuliert/ungültiger Signatur (verdächtig, HIGH) trennen kann.
|
||||
const err: any = new Error('Refresh-Token ungültig oder abgelaufen');
|
||||
err.code = e instanceof jwt.TokenExpiredError ? 'REFRESH_EXPIRED' : 'REFRESH_INVALID';
|
||||
throw err;
|
||||
}
|
||||
if (decoded.type !== 'refresh') {
|
||||
throw new Error('Falscher Token-Typ');
|
||||
|
||||
Reference in New Issue
Block a user