Dienstkonto-Anmeldungen als Routine statt CRITICAL (Pentest R182)

Das Gegenbuch meldet sich stuendlich an - protokolliert wurde das als
Authentication/CRITICAL. Damit stand das vorhersagbarste Ereignis im System auf
der hoechsten Stufe: Jeder legitime Lauf trainiert den Betreiber darauf,
CRITICAL wegzuklicken, und der erste echte Vorfall erbt diesen Reflex. Dieselbe
Alarm-Muedigkeits-Klasse wie R162, diesmal von uns selbst erzeugt.

Nicht unterdrueckt, sondern eingestuft: Neues Kennzeichen isServiceAccount am
Benutzer (Migration 20260822100000). Anmeldungen solcher Konten erscheinen
weiterhin im Log - man soll sehen, dass das Gegenbuch arbeitet - aber als
Routine (LOW) mit eigenem Label 'Dienstkonto ... angemeldet (planmaessig)'.
Alle anderen Anmeldungen bleiben CRITICAL.

Offen und dem Pentester so benannt: Der eigentliche Tripwire waere der
AUSBLEIBENDE Heartbeat (Dienstkonto meldet sich N Intervalle nicht mehr) sowie
Anmeldungen ausserhalb der Kadenz oder von fremder Quell-IP. Das braucht einen
Zeitgeber und ist noch nicht gebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 20:18:54 +02:00
co-authored by Claude Opus 5
parent 1f53a3304b
commit 41671cbb96
4 changed files with 38 additions and 1 deletions
@@ -0,0 +1,9 @@
-- Dienstkonto-Kennzeichen (Pentest R182).
--
-- Das Gegenbuch meldet sich stuendlich an. Diese Anmeldung wurde bisher als
-- Authentication/CRITICAL protokolliert - also das vorhersagbarste Ereignis im
-- System auf der hoechsten Stufe. Damit trainiert die Routine den Betreiber
-- darauf, CRITICAL wegzuklicken, und der erste ECHTE Vorfall erbt diesen
-- Reflex. Mit dem Kennzeichen werden solche Anmeldungen als Routine gefuehrt.
ALTER TABLE `User`
ADD COLUMN IF NOT EXISTS `isServiceAccount` BOOLEAN NOT NULL DEFAULT false;
+5
View File
@@ -76,6 +76,11 @@ model User {
firstName String
lastName String
isActive Boolean @default(true)
/// Dienstkonto (z. B. das Gegenbuch). Meldet sich planmaessig und haeufig an.
/// Solche Anmeldungen werden im Audit-Log als Routine gefuehrt statt als
/// CRITICAL - sonst trainiert das vorhersagbarste Ereignis im System den
/// Betreiber darauf, die hoechste Stufe wegzuklicken (Pentest R182).
isServiceAccount Boolean @default(false)
tokenInvalidatedAt DateTime? // Zeitpunkt ab dem alle Tokens ungültig sind (für Zwangslogout bei Rechteänderung)
// Passwort-Reset
+20
View File
@@ -167,6 +167,21 @@ const ACTION_LABELS: Record<string, string> = {
TOKEN_REFRESH: 'Sitzung verlängert',
};
/**
* Ist das die planmaessige Anmeldung eines Dienstkontos? (Pentest R182)
*
* Vorhersagbare Ereignisse sind miserable Alarme und exzellente Grundlinien.
* Das Gegenbuch meldet sich stuendlich an als CRITICAL gefuehrt trainiert
* genau diese Routine den Betreiber darauf, die hoechste Stufe wegzuklicken,
* und der erste ECHTE Vorfall erbt den Reflex. Der Eintrag bleibt (man soll
* sehen, dass das Gegenbuch arbeitet), aber als Routine.
*/
function istDienstkontoAnmeldung(responseBody: unknown, success: boolean): boolean {
if (!success || !responseBody || typeof responseBody !== 'object') return false;
const data = (responseBody as { data?: { user?: { isServiceAccount?: boolean } } }).data;
return data?.user?.isServiceAccount === true;
}
/**
* Unterscheidet die drei Ausgaenge von POST /auth/refresh (Pentest R166-03).
*
@@ -219,6 +234,9 @@ function generateHumanLabel(
// Auth
if (path.includes('/auth/login') || path.includes('/auth/customer-login')) {
const email = req.body?.email || '';
if (action === 'LOGIN' && istDienstkontoAnmeldung(responseBody, true)) {
return `Dienstkonto ${email} angemeldet (planmäßig)`;
}
return action === 'LOGIN'
? `Benutzer ${email} hat sich angemeldet`
: `Anmeldung fehlgeschlagen für ${email}`;
@@ -486,6 +504,8 @@ export function auditMiddleware(req: AuthRequest, res: Response, next: NextFunct
// Andere Auth-Events behalten ihre Default-Sensitivität (Authentication → CRITICAL).
sensitivity: action === 'TOKEN_REFRESH'
? (refreshOutcome(responseBody, responseSuccess) === 'rejected' ? 'HIGH' : 'LOW')
: action === 'LOGIN' && istDienstkontoAnmeldung(responseBody, responseSuccess)
? 'LOW'
: undefined,
resourceType: mapping.type,
resourceId,
+3
View File
@@ -333,6 +333,9 @@ export async function login(email: string, password: string) {
permissions: Array.from(permissions),
customerId: user.customerId,
isCustomerPortal: false,
// Wird von der Audit-Middleware gelesen, um planmaessige
// Dienstkonto-Anmeldungen als Routine einzustufen (R182).
isServiceAccount: user.isServiceAccount,
},
};
}