Security-Hardening Runde 14: Factory-Reset, Settings-Whitelist, Prisma-Leak, XSS-Strip
Pentest Runde 11:
C2 KRITISCH – Factory Reset ohne Bestätigung:
Eingeloggter Admin konnte mit leerem oder beliebigem Body die DB
plätten (3× in einer Pentest-Session passiert). Server erzwingt jetzt
confirm:"FACTORY-RESET-BESTAETIGT" als String. Frontend-API sendet
den Wert automatisch mit.
M1 – Settings Mass Assignment:
PUT /api/settings akzeptierte beliebige Keys (superAdminEmail,
debugMode, allowedOrigins). Neue Whitelist ALLOWED_SETTING_KEYS in
appSetting.service.ts; updateSetting + updateSettings prüfen jeden
Key, unbekannte → 400.
M3 – Prisma-Error-Leak:
Statt 30+ Controller einzeln zu fixen, globaler res.json()-Wrapper
unter /api: error/details-Strings werden durch Pattern-Filter
geschickt, der ORM-/Stack-Trace-Muster zu "Operation fehlgeschlagen"
ersetzt. Original bleibt im Server-Log.
M2 – Stored XSS in Customer/User-Strings:
Neuer stripHtml()-Helper. pickCustomerUpdate/Create + pickUserUpdate/
Create rufen ihn auf jeden String-Wert. Defense-in-Depth gegen PDF/
E-Mail-Template-XSS-Vektoren – React-Frontend ist eh auto-escaped.
Live-verifiziert:
- factory-reset {} / {confirm:true} / {confirm:false} → 400, DB ok
- PUT /settings {superAdminEmail,...} → 400 + Keys aufgezählt;
PUT /settings {customerSupportTicketsEnabled:"true"} → 200
- PUT /users/99999 → "Operation fehlgeschlagen" (vorher Prisma-Stack)
- PUT /customers/3 {companyName:"<script>...</script>EvilCorp"} →
gespeichert als "EvilCorp"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,44 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
|
||||
## ✅ Erledigt
|
||||
|
||||
- [x] **🚨 Pentest Runde 11 – Factory-Reset, Settings-Whitelist, Prisma-Leak, XSS-Strip**
|
||||
- **C2 KRITISCH – Factory Reset ohne Bestätigung**:
|
||||
Eingeloggter Admin konnte mit leerem oder beliebigem Body
|
||||
(`{confirm:true}`, `{confirm:false}`, `{}`) die komplette DB
|
||||
plätten (3× in einer Session passiert). Fix: server-side wird
|
||||
jetzt `confirm: "FACTORY-RESET-BESTAETIGT"` als String erzwungen,
|
||||
sonst HTTP 400. Frontend-API schickt den exakten String mit.
|
||||
- **M1 – Settings Mass Assignment**:
|
||||
`PUT /api/settings` und `PUT /api/settings/:key` nahmen JEDEN
|
||||
Key-Value-Pair an (`superAdminEmail`, `debugMode`,
|
||||
`allowedOrigins` etc. landeten direkt in der DB). Fix:
|
||||
Whitelist `ALLOWED_SETTING_KEYS` in `appSetting.service.ts`,
|
||||
Helper `isAllowedSettingKey()`. Unbekannte Keys → HTTP 400 mit
|
||||
expliziter Aufzählung der ungültigen Keys.
|
||||
- **M3 – Prisma-Error-Leak in jeder Response**:
|
||||
Statt 30+ Controller einzeln zu fixen: globaler `res.json()`-
|
||||
Wrapper unter `/api`, der `error`/`details`-Strings durch einen
|
||||
Pattern-Filter schickt. Bekannte ORM-/Stack-Trace-Muster
|
||||
(`Invalid \`prisma.`, `PrismaClient`, Stack-Frames) werden zu
|
||||
`"Operation fehlgeschlagen"` ersetzt. Original-Text bleibt im
|
||||
Server-Log via `[orm-leak-guard]`.
|
||||
- **M2 – Stored XSS in Customer/User-Strings**:
|
||||
`<script>alert(1)</script>` und ähnliche Payloads landeten
|
||||
ungefiltert in der DB. Fix: neuer `stripHtml()`-Helper, von
|
||||
`pickCustomerUpdate/Create` und `pickUserUpdate/Create` auf
|
||||
allen String-Werten angewandt (Defense-in-Depth – React
|
||||
auto-escaped schon, aber PDF-Generator/E-Mail-Templates
|
||||
könnten exec-Vektoren sein).
|
||||
- **Live-verifiziert (alle vier)**:
|
||||
* `/factory-reset` mit `{}`, `{confirm:true}`, `{confirm:false}`
|
||||
→ HTTP 400, DB unangetastet
|
||||
* `PUT /settings {superAdminEmail,debugMode,allowedOrigins}` →
|
||||
400 + Keys aufgezählt; gültige Keys → 200
|
||||
* `PUT /users/99999` → `"Operation fehlgeschlagen"` statt
|
||||
Prisma-Stack; Server-Log behält Original
|
||||
* `PUT /customers/3 {companyName:"<script>...</script>EvilCorp"}`
|
||||
→ gespeichert als `"EvilCorp"`; `<img onerror>` weg
|
||||
|
||||
- [x] **🚨 Pentest Runde 10 – Live-Vollmacht-Konsistenz + DTO-Leaks in embedded Objekten**
|
||||
- **MEDIUM – Stale Token nach Vollmacht-Widerruf**:
|
||||
Selbst ein FRISCHER Portal-Login lieferte JWT mit
|
||||
|
||||
Reference in New Issue
Block a user