XMPP: geen rate-limit op inbound ops — vijandige autoriteit kan deck en MUC overstromen #1433

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

Bevinding

lib/collab/collab_session.dart — de _onRemoteOp-handler (regels 144–155) accepteert elke op die de transport binnenkomt en emit hem op _deckChanges. Er is geen rate-limit of cap op het aantal ops per tijdseenheid.

lib/xmpp/xmpp_transport.dart — de _emit-methode (regels 353–362) emit elke geopende op op _ops zonder snelheidsbegrenzing. De _maxDeferred = 256 cap beperkt alleen stanzas die niet direct geopend kunnen worden — een vijandige autoriteit met de epoch-sleutel stuurt ops die direct geopend worden en onbegrensd doorstromen.

Wat er gebeurt

Een vijandige autoriteit (of een gecompromitteerde autoriteit-sessie) stuurt duizenden ops per seconde. Elke op:

  1. Komt binnen als een <message type=groupchat> op de MUC
  2. Wordt verzegeld en geopend (de autoriteit heeft de epoch-sleutel)
  3. Wordt geëmit op _ops en verwerkt door CollabSession._onRemoteOp
  4. Muteert het deck (applyOp)
  5. Emit op _deckChanges (wat de UI triggert om te herrenderen)

De follower verwerkt elke op, muteert het deck, en herrendert de UI — duizenden keren per seconde. De UI bevriest, het geheugen groeit (elke op alloceert een nieuw Deck), en de MUC wordt overstroomd.

Trust boundary

MUC (companion room) → Applicatie (op-verwerking). De autoriteit is een vertrouwde partij, maar een gecompromitteerde autoriteit-sessie of een slecht geschreven autoriteit kan dit triggeren.

Impact

  • UI-bevriezing: de follower rendert duizenden keren per seconde.
  • Geheugen-exhaustie: elke op alloceert een nieuw Deck (immutable copy).
  • MUC-overstroming: duizenden stanzas per seconde belasten de MUC-server en alle deelnemers.
  • Geen fail-closed: er is geen mechanisme om een overstromende autoriteit te blokkeren.

Oplossingsrichting

  1. Rate-limit op inbound ops in de transport. Een eenvoudige token-bucket of sliding-window: als er meer dan N ops/seconde binnenkomen (bijv. 50), dropp de overvloed en log een warning. Bij aanhoudende overvloed (M seconden), sluit de sessie fail-closed.
  2. Aanvullend: overweeg een maximum op de deck-grootte (aantal slides). Een deck met 10.000 slides is waarschijnlijk een aanval, niet een presentatie.
  3. Aanvullend: overweeg een backpressure-mechanisme op _deckChanges — als de UI niet bij kan houden, coalesceer of dropp tussentijdse states.

Locatie

  • lib/collab/collab_session.dart regels 144–155 (_onRemoteOp — geen rate-limit)
  • lib/xmpp/xmpp_transport.dart regels 353–362 (_emit — geen rate-limit), 170–171 (_maxDeferred — beperkt alleen niet-openbare stanzas)

Severity

MEDIUM — vereist een gecompromitteerde autoriteit, maar de impact (UI-bevriezing, geheugen-exhaustie) is volledig.

## Bevinding `lib/collab/collab_session.dart` — de `_onRemoteOp`-handler (regels 144–155) accepteert elke op die de transport binnenkomt en emit hem op `_deckChanges`. Er is geen rate-limit of cap op het aantal ops per tijdseenheid. `lib/xmpp/xmpp_transport.dart` — de `_emit`-methode (regels 353–362) emit elke geopende op op `_ops` zonder snelheidsbegrenzing. De `_maxDeferred = 256` cap beperkt alleen stanzas die niet direct geopend kunnen worden — een vijandige autoriteit met de epoch-sleutel stuurt ops die direct geopend worden en onbegrensd doorstromen. ### Wat er gebeurt Een vijandige autoriteit (of een gecompromitteerde autoriteit-sessie) stuurt duizenden ops per seconde. Elke op: 1. Komt binnen als een `<message type=groupchat>` op de MUC 2. Wordt verzegeld en geopend (de autoriteit heeft de epoch-sleutel) 3. Wordt geëmit op `_ops` en verwerkt door `CollabSession._onRemoteOp` 4. Muteert het deck (`applyOp`) 5. Emit op `_deckChanges` (wat de UI triggert om te herrenderen) De follower verwerkt elke op, muteert het deck, en herrendert de UI — duizenden keren per seconde. De UI bevriest, het geheugen groeit (elke op alloceert een nieuw Deck), en de MUC wordt overstroomd. ### Trust boundary MUC (companion room) → Applicatie (op-verwerking). De autoriteit is een vertrouwde partij, maar een gecompromitteerde autoriteit-sessie of een slecht geschreven autoriteit kan dit triggeren. ### Impact - UI-bevriezing: de follower rendert duizenden keren per seconde. - Geheugen-exhaustie: elke op alloceert een nieuw Deck (immutable copy). - MUC-overstroming: duizenden stanzas per seconde belasten de MUC-server en alle deelnemers. - Geen fail-closed: er is geen mechanisme om een overstromende autoriteit te blokkeren. ### Oplossingsrichting 1. **Rate-limit op inbound ops in de transport.** Een eenvoudige token-bucket of sliding-window: als er meer dan N ops/seconde binnenkomen (bijv. 50), dropp de overvloed en log een warning. Bij aanhoudende overvloed (M seconden), sluit de sessie fail-closed. 2. **Aanvullend:** overweeg een maximum op de deck-grootte (aantal slides). Een deck met 10.000 slides is waarschijnlijk een aanval, niet een presentatie. 3. **Aanvullend:** overweeg een backpressure-mechanisme op `_deckChanges` — als de UI niet bij kan houden, coalesceer of dropp tussentijdse states. ### Locatie - `lib/collab/collab_session.dart` regels 144–155 (`_onRemoteOp` — geen rate-limit) - `lib/xmpp/xmpp_transport.dart` regels 353–362 (`_emit` — geen rate-limit), 170–171 (`_maxDeferred` — beperkt alleen niet-openbare stanzas) ### Severity MEDIUM — vereist een gecompromitteerde autoriteit, maar de impact (UI-bevriezing, geheugen-exhaustie) is volledig.
brenno 2026-08-09 20:56:41 +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#1433
No description provided.