todo.md: Passwort-Komplexität + Real-IP-Fix dokumentiert
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,46 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
|||||||
|
|
||||||
## ✅ Erledigt
|
## ✅ Erledigt
|
||||||
|
|
||||||
|
- [x] **🔐 Passwort-Komplexität + Portal-Credentials-UX**
|
||||||
|
- **Problem**: Bisher reichten 6 Zeichen für gesetzte Passwörter
|
||||||
|
(Portal-Login, User-Reset, Registrierung, User-Anlage). Das hat
|
||||||
|
der Pentest bemängelt, und es entsprach auch nicht dem, was wir
|
||||||
|
selbst von Endkunden erwarten würden.
|
||||||
|
- **Lösung**:
|
||||||
|
* `validatePasswordComplexity()` in `passwordGenerator.ts`:
|
||||||
|
mind. 12 Zeichen + Großbuchstaben + Kleinbuchstaben + Ziffer
|
||||||
|
+ Sonderzeichen, mit detaillierter Fehlerliste auf deutsch.
|
||||||
|
* Erzwungen in **5 Endpoints**: `setPortalPassword`,
|
||||||
|
`confirmPasswordReset`, `register`, `createUser`, `updateUser`.
|
||||||
|
- **Neue UX im Kunden-Portal-Block (CustomerDetail)**:
|
||||||
|
* **Generate-Button**: erzeugt 16-Zeichen-Zufallspasswort, das
|
||||||
|
garantiert allen Komplexitätsregeln entspricht, und füllt
|
||||||
|
das Eingabefeld direkt aus.
|
||||||
|
* **Send-Credentials-Button**: schickt Login-URL + Username +
|
||||||
|
Klartext-Passwort an die Kunden-E-Mail. Funktioniert nur,
|
||||||
|
wenn "Portal aktiviert" tatsächlich aktiviert ist.
|
||||||
|
* **Live-Komplexitäts-Hint** beim Tippen: ✓/○-Liste zeigt
|
||||||
|
sofort, welche Regeln noch fehlen.
|
||||||
|
* `alert()`-Boxen durch Toast-Notifications ersetzt.
|
||||||
|
- **Live-verifiziert**: schwaches Passwort `hallo123` → HTTP 400
|
||||||
|
mit Fehlerliste, komplexes Passwort `Hallo123!Test` → HTTP 200,
|
||||||
|
Generator-Endpoint liefert 16-Zeichen-Passwort, Send-Credentials
|
||||||
|
versendet Mail nur bei portalEnabled=true.
|
||||||
|
|
||||||
|
- [x] **🌐 Real-IP hinter Nginx-Proxy-Manager**
|
||||||
|
- **Problem**: Rate-Limiter und Security-Monitor haben statt der
|
||||||
|
echten Client-IP nur die NPM-IP (`172.0.2.12`) geloggt. Damit
|
||||||
|
wären alle Threshold-basierten Blockings nutzlos – ein Brute-
|
||||||
|
Force von 100 verschiedenen Clients wäre für uns 1 Quelle.
|
||||||
|
- **Root Cause**: `app.set('trust proxy', 'loopback')` – das passt
|
||||||
|
nur, wenn der Proxy auf 127.0.0.1 läuft. NPM läuft aber auf
|
||||||
|
einem anderen Host, also wurde X-Forwarded-For ignoriert.
|
||||||
|
- **Fix**: trust-proxy abhängig von `HTTPS_ENABLED`:
|
||||||
|
`HTTPS_ENABLED=true` → `1` (genau 1 Hop, der NPM), sonst
|
||||||
|
`loopback` (Direkt-Verbindungen lokal).
|
||||||
|
- **Live-verifiziert**: req.ip zeigt jetzt die echte Browser-IP
|
||||||
|
statt der NPM-IP, Threshold-Events triggern korrekt.
|
||||||
|
|
||||||
- [x] **🚨 KRITISCH: IDOR auf Stressfrei-Email-Sub-Routes (Pentest-Fund)**
|
- [x] **🚨 KRITISCH: IDOR auf Stressfrei-Email-Sub-Routes (Pentest-Fund)**
|
||||||
- **Realer Angriff erfolgreich durchgespielt**: Portal-User konnte über
|
- **Realer Angriff erfolgreich durchgespielt**: Portal-User konnte über
|
||||||
`/api/stressfrei-emails/{id}/credentials` die kompletten Klartext-
|
`/api/stressfrei-emails/{id}/credentials` die kompletten Klartext-
|
||||||
|
|||||||
Reference in New Issue
Block a user