Mitarbeiter-Passwörter auf 25 Zeichen (BSI-Empfehlung)
Portal-Customer-Schwellwert bleibt 12 (Handy-Eingabe → längere PWs
erhöhen Reuse-Risiko). Mitarbeiter/Admin nutzen Passwort-Manager,
für die kostet die Länge nichts.
passwordGenerator.ts:
- STAFF_MIN_PASSWORD_LENGTH = 25, PORTAL_MIN_PASSWORD_LENGTH = 12
- validatePasswordComplexity({ minLength }) parametrisiert
Mitarbeiter-Pfade auf 25:
- createUser, register, setUserPassword
- confirmPasswordReset: Audience aus Token bestimmen
(getPasswordResetAudience), User → 25, Customer → 12. Kein
Body-Hint, damit kein Downgrade-Trick möglich.
Portal-Pfade unverändert (default 12):
- setPortalPassword, changeInitialPortalPassword
Seed-Admin:
- 28-char Zufallspasswort (statt 16) mit allen 4 Klassen garantiert
- SEED_ADMIN_PASSWORD-ENV nur akzeptiert wenn ≥ 25 Zeichen,
sonst Log-Warnung + Random-Fallback
Frontend:
- UserList: Hinweis "Mind. 25 Zeichen". Update + PW gleichzeitig →
zwei API-Calls (PUT + POST /users/:id/password) statt
Password im Body durchzuschmuggeln (Backend strippt es eh)
- PasswordResetConfirm: Hinweis "Mind. 12 (Mitarbeiter: 25)"
- userApi.setPassword(id, password) neu
Live-verifiziert:
- POST /users/6/password "Hallo123!Test" (12) → 400 "mindestens 25"
- POST /users/6/password "MeinExtremLangesPW2026!Test" → 200,
Login mit neuem PW → success
- POST /customers/3/portal/password "Hallo123!Test" (12) → 200
- POST /users createUser mit 12-char-PW → 400 "mindestens 25"
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,42 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
|
||||
## ✅ Erledigt
|
||||
|
||||
- [x] **🔐 Mitarbeiter-Passwörter auf 25 Zeichen (BSI-Empfehlung)**
|
||||
- 12 Zeichen sind heute der untere akzeptable Rand. NIST/OWASP/BSI
|
||||
empfehlen 14-25+ Zeichen. Mitarbeiter/Admin nutzen Passwort-Manager
|
||||
→ Länge kostet nichts, Sicherheitsgewinn ist real.
|
||||
- **Schwellwerte**: `STAFF_MIN_PASSWORD_LENGTH = 25`,
|
||||
`PORTAL_MIN_PASSWORD_LENGTH = 12` (Endkunden tippen das auch auf
|
||||
dem Handy ein).
|
||||
- **Backend-Pfade**:
|
||||
* `createUser` + `register` + `setUserPassword` → 25 Zeichen
|
||||
* `setPortalPassword` + `changeInitialPortalPassword` → bleibt 12
|
||||
* `confirmPasswordReset`: Server bestimmt Audience anhand des
|
||||
Tokens (`getPasswordResetAudience`) → User-Token = 25, Customer-
|
||||
Token = 12. Damit kann ein Angreifer nicht durch Body-Hint
|
||||
auf den schwächeren Schwellwert ausweichen.
|
||||
- **Seed-Admin**: Default-Passwort jetzt 28-char Zufallspasswort
|
||||
(alle 4 Klassen garantiert), via `SEED_ADMIN_PASSWORD`-ENV
|
||||
überschreibbar – aber nur wenn ≥ 25 Zeichen, sonst ignoriert
|
||||
mit Log-Warnung.
|
||||
- **Frontend**:
|
||||
* UserList: Hinweis-Text "Mind. 25 Zeichen". Update + Passwort
|
||||
gleichzeitig → Frontend macht jetzt zwei Calls (PUT + neuer
|
||||
`POST /users/:id/password`) statt Passwort durch Update-Body
|
||||
durchzuschmuggeln.
|
||||
* PasswordResetConfirm: Hinweis "Mind. 12 Zeichen (Mitarbeiter:
|
||||
25)", Server entscheidet endgültig.
|
||||
* `userApi.setPassword(id, password)` neu in api.ts.
|
||||
- **Live-verifiziert**:
|
||||
* `POST /users/6/password "Hallo123!Test"` (12 chars) → 400
|
||||
"mindestens 25 Zeichen"
|
||||
* `POST /users/6/password "MeinExtremLangesPW2026!Test"` → 200,
|
||||
Login mit dem neuen PW → success
|
||||
* `POST /customers/3/portal/password "Hallo123!Test"` (12) → 200
|
||||
* `POST /users {…,password:"Hallo123!Test"}` → 400 (25-char-Floor)
|
||||
- **Nächster größerer Sprung** wäre **MFA für Mitarbeiter-Login**
|
||||
(TOTP via Authenticator). Eigenes Thema, separate Aufgabe.
|
||||
|
||||
- [x] **🚨 Pentest Runde 12 – Folge-Fixes: XSS-Reste, User-PW-Endpoint, JS-Error-Leak, Seed-PW**
|
||||
- **M2-Reste (XSS-Strings noch in DB)**: neues idempotentes Script
|
||||
`prisma/cleanup-xss-and-mass-assignment.ts` läuft beim
|
||||
|
||||
Reference in New Issue
Block a user