XMPP: snapshot chunk-data niet lengte-gevalideerd bij ontvangst — vijandige server kan oversized chunks sturen #1419

Closed
opened 2026-08-09 18:25:15 +00:00 by brenno · 0 comments
Owner

Bevinding

lib/xmpp/xmpp_snapshot.darthandleSnapshot (regels 165–202) valideert de chunk-velden (id, i, n, data) op type en bereik, maar niet op grootte van het data-veld. De maxChunkChars-constante (48000) wordt alleen gebruikt op de zender-kant (_split, regel 139) om chunks te splitsen; de ontvanger accepteert elk string-grootte.

Wat er gebeurt

Een vijandige server (of een occupant die groupchat-messages reflecteert krijgt) kan een chunk sturen met data: "<multi-MB string>". De chunk wordt gevalideerd (data is String → true), in _pending geplaatst, en bij reassemblage in de StringBuffer geschreven. De totale gereassembleerde blob kan veel groter zijn dan de 512 KiB frame-cap die op _FrameReader-niveau geldt — want de chunk-data kan base64-geëncodeerde ciphertext bevatten die binnen één frame past, maar bij reassemblage met andere chunks een blob van meerdere MB vormt.

Wait — eigenlijk is het frame al cap'd op 512 KiB door _FrameReader._maxFrameBytes. Dus een enkele chunk-data kan maximaal ~512 KiB zijn. Maar maxChunks is 512, dus de totale gereassembleerde blob kan oplopen tot 512 × 512 KiB = 256 MiB. Dat is ruim voldoende voor geheugen-exhaustie.

Trust boundary

MUC (companion room) → Applicatie (snapshot-reassemblage).

Impact

Geheugen-exhaustie: een vijandige server stuurt 512 chunks van elk ~512 KiB, die worden gereassembleerd tot een ~256 MiB blob in een StringBuffer, die vervolgens wordt geparsed als JSON (wat mislukt, maar de blob is al in het geheugen geladen).

Oplossingsrichting

  1. Valideer chunk-data grootte bij ontvangst: weiger een chunk waarvan data.length > maxChunkChars (dezelfde cap als de zender). Dit is een één-regel check in handleSnapshot na de bestaande validatie.
  2. Aanvullend: overweeg een totale-blob-cap — als de gereassembleerde blob groter wordt dan een redelijke limiet (bijv. 4 MiB), stop de reassemblage en drop de snapshot fail-closed.

Locatie

  • lib/xmpp/xmpp_snapshot.dart regels 165–202 (handleSnapshot — validatie), 204–216 (_assembleStringBuffer), 62–63 (maxChunkChars, maxChunks)

Severity

MEDIUM — geheugen-DoS, maar beperkt door de frame-cap van 512 KiB per chunk.

## Bevinding `lib/xmpp/xmpp_snapshot.dart` — `handleSnapshot` (regels 165–202) valideert de chunk-velden (`id`, `i`, `n`, `data`) op type en bereik, maar **niet op grootte** van het `data`-veld. De `maxChunkChars`-constante (48000) wordt alleen gebruikt op de *zender*-kant (`_split`, regel 139) om chunks te splitsen; de *ontvanger* accepteert elk string-grootte. ### Wat er gebeurt Een vijandige server (of een occupant die groupchat-messages reflecteert krijgt) kan een chunk sturen met `data: "<multi-MB string>"`. De chunk wordt gevalideerd (`data is String` → true), in `_pending` geplaatst, en bij reassemblage in de `StringBuffer` geschreven. De totale gereassembleerde blob kan veel groter zijn dan de 512 KiB frame-cap die op `_FrameReader`-niveau geldt — want de chunk-`data` kan base64-geëncodeerde ciphertext bevatten die binnen één frame past, maar bij reassemblage met andere chunks een blob van meerdere MB vormt. Wait — eigenlijk is het frame al cap'd op 512 KiB door `_FrameReader._maxFrameBytes`. Dus een enkele chunk-`data` kan maximaal ~512 KiB zijn. Maar `maxChunks` is 512, dus de totale gereassembleerde blob kan oplopen tot 512 × 512 KiB = 256 MiB. Dat is ruim voldoende voor geheugen-exhaustie. ### Trust boundary MUC (companion room) → Applicatie (snapshot-reassemblage). ### Impact Geheugen-exhaustie: een vijandige server stuurt 512 chunks van elk ~512 KiB, die worden gereassembleerd tot een ~256 MiB blob in een `StringBuffer`, die vervolgens wordt geparsed als JSON (wat mislukt, maar de blob is al in het geheugen geladen). ### Oplossingsrichting 1. **Valideer chunk-`data` grootte bij ontvangst:** weiger een chunk waarvan `data.length > maxChunkChars` (dezelfde cap als de zender). Dit is een één-regel check in `handleSnapshot` na de bestaande validatie. 2. **Aanvullend:** overweeg een totale-blob-cap — als de gereassembleerde blob groter wordt dan een redelijke limiet (bijv. 4 MiB), stop de reassemblage en drop de snapshot fail-closed. ### Locatie - `lib/xmpp/xmpp_snapshot.dart` regels 165–202 (`handleSnapshot` — validatie), 204–216 (`_assemble` — `StringBuffer`), 62–63 (`maxChunkChars`, `maxChunks`) ### Severity MEDIUM — geheugen-DoS, maar beperkt door de frame-cap van 512 KiB per chunk.
brenno 2026-08-09 20:56:28 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#1419
No description provided.