Pentest R102: contractNumber-Whitelist nachgezogen

INFO-Finding: die interne CRM-Vertragsnummer war im Update-Path
nicht durch validateContractIdentifier abgedeckt. <script>… →
stripHtml → leerer String → Vertragsnummer silent überschrieben
(R87.1-Pattern auf einem sechsten Feld).

Fix: contractNumber zu CONTRACT_IDENTIFIER_FIELDS hinzugefügt.
Bestehende Whitelist (^[A-Za-z0-9_\-/. ]{0,100}$) und Raw-Input-
Validierung greifen automatisch. Legitime generierte Nummern
(GAS-MPVJ4P10FE8) bleiben OK, <script>/Overflow/CRLF/Tags → 400.

Kein Migration- oder Frontend-Change – der Fix nutzt den
bestehenden R86-Mechanismus.

Doku in SECURITY-HARDENING.md § Runde 102 und docs/todo.md.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 00:40:08 +02:00
parent 57959cd782
commit 3c190e43fb
3 changed files with 47 additions and 0 deletions
+29
View File
@@ -654,6 +654,35 @@ Modus hängt sowieso an einer schon validierten Email-Stammdate
---
## 🔒 Runde 102 Interne Vertragsnummer nachziehen
**Finding (INFO, kein Security-Impact ohne Admin-Login):**
`contractNumber` die interne CRM-Vertragsnummer hatte im
Update-Path keine Whitelist-Validierung. Sie wird beim Create
serverseitig via `generateContractNumber` erzeugt, aber
`updateContract` reicht den ganzen Body per `...contractData`
an Prisma durch. Ein Admin (oder Angreifer mit gestohlenem
`users:update`+`contracts:update`-JWT) konnte einen `<script>`-
Payload im `contractNumber`-Feld senden `stripHtml` machte
daraus stille einen leeren String, die `@unique`-Constraint
akzeptierte den ersten leeren Eintrag → Vertragsnummer silent
überschrieben (R87.1-Pattern auf neuem Feld).
**Fix:** `contractNumber` zusätzlich in
`CONTRACT_IDENTIFIER_FIELDS` in
[`backend/src/utils/sanitize.ts`](../backend/src/utils/sanitize.ts).
Damit greift automatisch dieselbe Whitelist
`^[A-Za-z0-9_\-/. ]{0,100}$` gegen Raw-Input, die schon für die
fünf Anbieter-/Vertriebsplattform-Nummern läuft. Legitime
generierte Nummern (`GAS-MPVJ4P10FE8`) bleiben grün, `<script>`,
Overflow (>100), CRLF & Tag-Attribute → 400 mit klarer Meldung.
Kein separater Migration- oder Frontend-Change nötig der Fix
nutzt den bestehenden R86-Mechanismus.
---
## 🧭 Wann ist „dicht" dicht?
100 % gibt es nicht. Erreicht ist: