Security-Hardening Runde 10: Security-Monitoring + Alerting
Defense-in-Depth für alles, was in den ersten 9 Runden nicht durch Code verhindert wurde: zumindest gesehen + alarmiert werden. 📊 SecurityEvent-Tabelle (Prisma) - Type/Severity/IP/User/Endpoint + Indexen für Filter+Threshold-Detection - Trennt sich vom AuditLog: AuditLog ist forensisch + hash-gekettet, SecurityEvent ist optimiert für Realtime-Alerting + Aggregation. 🪝 Hooks an kritischen Stellen - Login (Success/Failed) – auth.controller - Logout, Password-Reset (Request + Confirm) – auth.controller - Rate-Limit-Hit – middleware/rateLimit - IDOR-403 – utils/accessControl (canAccessCustomer / canAccessContract) - SSRF-Block – emailProvider.controller (test-connection + test-mail-access) - JWT-Reject (alg=none, expired, manipuliert) – middleware/auth 🚨 Threshold-Detection + Alerting (securityAlert.service.ts) - Cron jede Minute: prüft Brute-Force-Patterns je IP - 10× LOGIN_FAILED in 60 min → CRITICAL Brute-Force-Verdacht - 5× ACCESS_DENIED in 5 min → CRITICAL IDOR-Probing-Verdacht - 3× SSRF_BLOCKED in 60 min → CRITICAL SSRF-Probing - 3× TOKEN_REJECTED HIGH in 5 min → CRITICAL JWT-Manipulation - CRITICAL-Events: Sofort-Alert per E-Mail (debounced) - Cron stündlich: Digest mit HIGH+MEDIUM-Events (wenn aktiviert) - Sofort-Alert + Digest laufen über System-E-Mail-Provider (gleicher Pfad wie Geburtstagsgrüße, Passwort-Reset) 🖥 Frontend: Settings → "Sicherheits-Monitoring" - Alert-E-Mail-Adresse + Digest-Toggle - Test-Alert-Button + Digest-jetzt-Button - Stats-Cards pro Severity (CRITICAL/HIGH/MEDIUM/LOW/INFO) - Filter (Type/Severity/Search/IP) + Pagination - Auto-Refresh alle 30 s - Verlinkt aus Settings-Übersicht (settings:read Permission) 🧪 Live-verifiziert - Login-Fehlversuch → LOGIN_FAILED Event - Portal probt 4× fremde Customer-IDs → 4× ACCESS_DENIED - SSRF-Probe (169.254.169.254) → SSRF_BLOCKED Event - 12× LOGIN_FAILED simuliert → Cron erzeugt CRITICAL nach ≤60s - CRITICAL-Sofort-Alert binnen 30s zugestellt - Test-Alert-Button: E-Mail zugestellt - Hourly-Digest mit 5 Events: E-Mail mit Tabelle zugestellt Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -175,6 +175,45 @@ Plus Error-Handler: `err.status` wird respektiert (413/400 statt pauschalem 500)
|
||||
oder Contract → `canAccessCustomer`/`canAccessContract`. Backwards-
|
||||
Compat-Shim für `/api/uploads/*` ruft denselben Owner-Check.
|
||||
|
||||
### Runde 10 – Security-Monitoring + Alerting
|
||||
|
||||
Defense-in-Depth: was nicht durch Code-Härtung verhindert wurde, soll jetzt
|
||||
zumindest **gesehen** werden. Ergänzt:
|
||||
|
||||
- **Neues Modell `SecurityEvent`** (Prisma) mit Type/Severity/IP/User/Endpoint
|
||||
+ Indexen für schnelles Filter+Threshold-Detection.
|
||||
- **Service `securityMonitor.service.ts`** mit zentraler `emit()`-Funktion.
|
||||
Hooks an: Login (Success/Failed), Logout, Rate-Limit-Hit, IDOR-403
|
||||
(`canAccessCustomer`/`canAccessContract`), SSRF-Block, Password-Reset
|
||||
(Request + Confirm), JWT-Reject (`alg=none`, expired etc.).
|
||||
- **Service `securityAlert.service.ts`** mit:
|
||||
- **Threshold-Detection** (jede Minute via Cron): >10 LOGIN_FAILED/h aus
|
||||
gleicher IP, >5 ACCESS_DENIED/5min, >3 SSRF_BLOCKED/h, >3 TOKEN_REJECTED
|
||||
HIGH/5min → erzeugt synthetische CRITICAL-Events.
|
||||
- **Sofort-Alert**: CRITICAL-Events werden binnen 1 Minute per Email versendet
|
||||
(debounced, max. 1× pro Stunde + IP).
|
||||
- **Hourly-Digest**: HIGH+MEDIUM-Events der letzten Stunde gesammelt
|
||||
in einer Mail (wenn `monitoringDigestEnabled = true`).
|
||||
- **Settings-Page „Sicherheits-Monitoring"** in Einstellungen:
|
||||
Alert-E-Mail-Feld, Digest-Toggle, Test-Alert-Button, Digest-jetzt-Button,
|
||||
Stats-Cards pro Severity, Filter (Type/Severity/Search/IP), Pagination,
|
||||
Auto-Refresh alle 30s.
|
||||
- **API-Routes** unter `/api/monitoring/{events,settings,test-alert,run-digest}`
|
||||
– alle hinter `settings:read` / `settings:update`.
|
||||
|
||||
Live-verifiziert (1. Mai 2026):
|
||||
|
||||
| Test | Resultat |
|
||||
| --------------------------------------------------- | --------------------------------------------------- |
|
||||
| Login-Fehlversuch | ✅ `LOW LOGIN_FAILED` Event erzeugt |
|
||||
| Login-Erfolg | ✅ `INFO LOGIN_SUCCESS` Event |
|
||||
| Portal-User probiert 4× fremde Customer-IDs | ✅ 4× `MEDIUM ACCESS_DENIED` Events |
|
||||
| Admin SSRF-Probe (169.254.169.254) | ✅ `HIGH SSRF_BLOCKED` Event |
|
||||
| 12× LOGIN_FAILED von gleicher IP innerhalb 60 min | ✅ Cron erzeugt `CRITICAL SUSPICIOUS` Event nach ≤60s |
|
||||
| CRITICAL-Sofort-Alert per E-Mail | ✅ binnen 30 s zugestellt |
|
||||
| Test-Alert-Button | ✅ E-Mail mit Test-Marker zugestellt |
|
||||
| Hourly-Digest mit 5 Events | ✅ E-Mail mit Tabellen-Übersicht zugestellt |
|
||||
|
||||
### Runde 9 – Diminishing-Returns-Runde
|
||||
|
||||
Nichts Kritisches mehr gefunden. Liefert noch:
|
||||
@@ -289,7 +328,8 @@ Vor jedem Launch mit echten Tokens probieren.
|
||||
| `4e91d96` | 6 | Customer-List-Leak + XFF-Bypass + Auth-Toggle |
|
||||
| `12b9abe` | 7 | SSRF-Schutz + Logout |
|
||||
| `d063d67` | 8 | DNS-Rebinding + Per-File-Ownership |
|
||||
| (folgt) | 9 | `npm audit fix` + Audit-Chain-Rehash + Doku |
|
||||
| `c9a2b9f` | 9 | `npm audit fix` + Audit-Chain-Rehash + Doku |
|
||||
| (folgt) | 10 | Security-Monitoring (SecurityEvent + Hooks + Alerts + UI) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+4
-1
@@ -116,7 +116,7 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
`cancellationConfirmationDate` genügen, um "gesendet vs. bestätigt"
|
||||
abzubilden. `ACTIVE` bleibt bis zur Bestätigung.
|
||||
|
||||
- [x] **🛡️ Security-Hardening vor Production-Deployment (9 Runden)**
|
||||
- [x] **🛡️ Security-Hardening vor Production-Deployment (10 Runden)**
|
||||
- Vollständige Story inkl. aller Live-Test-Tabellen + Trade-offs:
|
||||
**[SECURITY-HARDENING.md](./SECURITY-HARDENING.md)**
|
||||
- Erste 2 Runden zusätzlich ausführlich in
|
||||
@@ -133,6 +133,9 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
- Runde 8: DNS-Rebinding-Schutz, Per-File-Ownership-Check
|
||||
- Runde 9: `npm audit fix` (8 Vulns weg), Audit-Chain-Rehash, keine
|
||||
neuen Critical-Findings → diminishing returns erreicht
|
||||
- Runde 10: Security-Monitoring (SecurityEvent-Tabelle + Hooks an
|
||||
Login/IDOR/SSRF/Reset/Logout/JWT-Reject + Threshold-Detection +
|
||||
Sofort-Alert für CRITICAL + Hourly-Digest + UI in Einstellungen)
|
||||
- Deployment-Checkliste komplett (in HARDENING.md)
|
||||
|
||||
- [x] **🎉 Version 1.0.0 Feinschliff: Passwort-Reset + Rate-Limiting + Auto-Geburtstagsgrüße**
|
||||
|
||||
Reference in New Issue
Block a user