Pentest 68.1 (LOW) + 68.2 (INFO): PDF-Active-Content-Filter + Modal-Limit
68.1: Magic-Byte-Check prüfte nur %PDF-. PDFs mit /JavaScript, /JS, /Launch, /EmbeddedFile, /RichMedia (Flash) kamen durch und wurden inline ausgeliefert – Browser-Viewer ignorieren JS, Adobe Acrobat nicht. - Neuer Helper assertSafePdf(buf) in utils/sanitize.ts mit case-sensitivem String-Scan auf die fünf Action-Patterns (\b-Word-Boundary verhindert False-Positives bei /JSXForm etc.). - Neue Middleware pdfUploadSafety.ts mit zwei Varianten: requireSafeUploadedPdf (PDF-only) und scanUploadedPdfIfPresent (durchwinkt JPG/PNG, scannt nur PDFs). - Eingehängt in: upload.routes (Magic-Byte-Validator erweitert), gdpr.routes Vollmacht-Upload, pdfTemplate.routes Template-Upload, contract.routes Vertragsdokumente, cachedEmail.controller (saveAttachmentTo, saveAttachmentAsInvoice, saveAttachmentAsContractDocument). - Inline-Vorschau bleibt – Pentester-Empfehlung "disposition=inline abschalten" wurde bewusst nicht umgesetzt (löst Acrobat-Risiko nicht, bricht aber ~20 UI-Stellen). - Smoke-Test: 5 Payload-Typen abgelehnt, clean PDF + Non-PDF + JSXForm durchgewinkt. 68.2: JpgToPdfModal-Self-DoS – MAX_IMAGES=50, MAX_IMAGE_BYTES=25MB.
This commit is contained in:
@@ -97,6 +97,37 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
|
||||
## ✅ Erledigt
|
||||
|
||||
- [x] **🔒 Pentest 68.1 (LOW) + 68.2 (INFO): PDF-Inhalts-Validierung + Modal-Limit**
|
||||
- **68.1 PDF-Active-Content-Filter:** Magic-Byte-Check prüfte bisher
|
||||
nur `%PDF-`. PDFs mit `/JavaScript`, `/JS`, `/Launch` (externes
|
||||
Programm), `/EmbeddedFile`, `/RichMedia` (Flash) wurden inline an
|
||||
den Viewer ausgeliefert – Browser-PDF-Viewer (Chrome/Firefox)
|
||||
ignorieren JS, Adobe Acrobat aber nicht.
|
||||
- Neuer Helper `assertSafePdf(buf)` in `utils/sanitize.ts`:
|
||||
String-Scan auf die fünf Action-Pattern (case-sensitive nach
|
||||
PDF 32000-1:2008 §7.3.5). Wirft `ApiError(415, ...)` bei Treffer.
|
||||
- Neue Middleware `pdfUploadSafety.ts` mit zwei Varianten:
|
||||
- `requireSafeUploadedPdf` – Datei MUSS PDF sein, sonst 415.
|
||||
- `scanUploadedPdfIfPresent` – durchwinkt JPG/PNG, scannt nur PDFs.
|
||||
- Eingehängt:
|
||||
- `upload.routes.ts` (Magic-Byte-Validator erweitert)
|
||||
- `gdpr.routes.ts` Vollmacht-Upload
|
||||
- `pdfTemplate.routes.ts` Template-Upload
|
||||
- `contract.routes.ts` Vertragsdokumente
|
||||
- `cachedEmail.controller.ts` Email-Anhang-Pfade (3 Stellen:
|
||||
saveAttachmentTo, saveAttachmentAsInvoice,
|
||||
saveAttachmentAsContractDocument)
|
||||
- **Inline-Vorschau bleibt erhalten** – das war die explizite
|
||||
Anforderung (Augen-Button öffnet PDF im neuen Tab). Pentester-
|
||||
Empfehlung „disposition=inline abschalten" wurde bewusst NICHT
|
||||
umgesetzt, weil sie das eigentliche Acrobat-Risiko nicht löst
|
||||
(PDF auf Disk + Doppelklick → Acrobat → JS läuft trotzdem).
|
||||
- Edge-Case-Test bestätigt: `/JSXForm` und `/JavaScriptFooter` werden
|
||||
NICHT als JavaScript-Action erkannt (word-boundary `\b` greift).
|
||||
- **68.2 Modal-Limit:** `JpgToPdfModal` hatte kein Bild-/Größen-Limit.
|
||||
Jetzt `MAX_IMAGES = 50` + `MAX_IMAGE_BYTES = 25 MB` pro Bild.
|
||||
UX-Schutz, kein Security-Bug (Self-DoS only).
|
||||
|
||||
- [x] **🆕 JPGs → PDF: Button überall bei PDF-Upload**
|
||||
- Neue Komponente `JpgToPdfModal` (lokal im Browser via `jspdf`,
|
||||
keine Backend-Round-Trip nötig). Mehrere Bilder hinzufügen per
|
||||
|
||||
Reference in New Issue
Block a user