duffyduck
|
0cf3dd6a7b
|
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>
|
2026-05-01 09:25:47 +02:00 |
|
duffyduck
|
8aead8c2f6
|
Security-Hardening Runde 3: JWT, trust-proxy, weitere IDORs, Attachment-Härtung
- JWT-Algorithmus fest auf HS256 (Defense-in-Depth gegen alg-confusion)
- app.set('trust proxy', 1) – Rate-Limiter wirkt jetzt auch hinter Reverse-Proxy
- IDOR-Fix: Invoice-ECD-Endpoints + PDF-Template-Generierung (canAccessContract/ECD)
- Email-Anhang-Download: Content-Type-Safelist, SVG nie inline, nosniff, Filename-CRLF-Sanitize
- Provider/Tariff-GET-Routen: requirePermission('providers:read') (Portal-Kunden raus)
- SMTP-Header-Injection zentral in sendEmail blockiert (schützt alle Caller)
- bcrypt-Cost 10 → 12 (OWASP 2026)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
2026-04-24 09:38:25 +02:00 |
|
duffyduck
|
1c46d7345c
|
Security-Hardening: IDOR-Fixes, XSS-Sanitizer, CORS+Helmet, Data-Exposure
Umfassender Security-Review vor öffentlichem Deployment.
Detaillierter Report in docs/SECURITY-REVIEW.md.
🔴 KRITISCHE FIXES:
1. CORS offen → jetzt nur explizite Origins (via CORS_ORIGINS env),
in Production per default komplett aus (gleiche Origin erzwingt Browser).
2. Keine Security-Headers → helmet-Middleware hinzugefügt.
X-Frame-Options, X-Content-Type-Options, HSTS, Referrer-Policy, CORP.
3. JWT-Fallback-Secret entfernt. Beim Server-Start wird jetzt geprüft ob
JWT_SECRET (min 32 Zeichen) und ENCRYPTION_KEY (exakt 64 Hex) gesetzt sind,
sonst Fail-Fast mit klarer Fehlermeldung.
4. IDOR bei 7 Contract-Endpoints. Portal-Kunden mit 'contracts:read'
konnten über geratene IDs fremde Daten abrufen (Passwort, SIM-PIN/PUK,
Internet-Zugangsdaten, SIP-Credentials, Vertragsdokumente, Rechnungen).
Neuer Helper canAccessContract() in utils/accessControl.ts in allen
betroffenen Endpoints eingebaut. Prüft Vertrag-Besitzer + Vollmachten.
5. XSS via Email-Body. email.htmlBody wurde ungefiltert via
dangerouslySetInnerHTML gerendert. Angreifer konnte Mail mit <script>
schicken → Token-Diebstahl aus localStorage. Jetzt mit DOMPurify
sanitized: verbietet script/iframe/form/inline-handler, erlaubt
normale Formatierung + Bilder.
6. Customer-API leakte sensible Felder:
- portalPasswordHash (bcrypt-Hash)
- portalPasswordEncrypted (symmetrisch, mit ENCRYPTION_KEY entschlüsselbar)
- portalPasswordResetToken (gültig 2h)
Neuer Sanitizer in utils/sanitize.ts, angewendet in getCustomer/getCustomers.
Admin mit customers:update darf portalPasswordEncrypted sehen (für UI-Anzeige),
alle anderen Rollen nicht.
🟡 WICHTIGE FIXES:
7. Portal-JWT-Invalidation nach Passwort-Reset. Neues Feld
Customer.portalTokenInvalidatedAt, wird beim Reset auf now() gesetzt.
Auth-Middleware prüft Portal-Sessions dagegen. Alte Sessions werden
dadurch invalidiert.
8. express.json() mit 5 MB Size-Limit (statt Default 100 KB unklar).
Neue Files:
- backend/src/utils/accessControl.ts - IDOR-Schutz
- backend/src/utils/sanitize.ts - Response-Sanitizer
- docs/SECURITY-REVIEW.md - vollständiger Report + Deployment-Checkliste
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
2026-04-23 22:06:16 +02:00 |
|