XMPP: snapshot-chunks zijn niet geauthenticeerd — vijandige occupant kan baseline corrumperen (join-DoS) #1411
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck#1411
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bevinding
lib/xmpp/xmpp_snapshot.dart—handleSnapshot(regels 165–202) aanvaardt chunks op basis van een plaintextid-veld (snap-{deviceId}-{counter}) zonder te verifiëren dat de stanza'sfromovereenkomt met de device-id in datid. De chunk-metadata (id,i,n,data) is plaintext; er is geen handtekening of afzender-controle op chunk-niveau.Wat er gebeurt
Een vijandige occupant stuurt een chunk met
id: "snap-<authority-deviceId>-0",i: 0,n: 3,data: "garbage". Deze overschrijft chunk 0 van de autoriteit's legitieme snapshot in de receiver's_pending-map. Wanneer chunks 1 en 2 aankomen, isparts.length == count(3), dus de snapshot wordt gereassembleerd. De blob is"garbage" + legit1 + legit2— misvormde JSON — dus_assemblegooit een uitzondering, die wordt gelogd en gedropt. De_pending-entry voor datidwordt gewist.De autoriteit stuurt de baseline niet opnieuw tenzij een newcomer net is gesleuteld (
syncNow→keyedDeviceCount > _lastKeyed). Als de newcomer al gesleuteld was toen de corruptie plaatsvond, wordt geen nieuwe baseline gestuurd. De newcomer'sfirstSnapshot-completer voltooit nooit — zijn sessie start niet.Trust boundary
MUC (companion room) → Applicatie (snapshot-reassemblage). De MUC reflecteert elke groupchat-message naar elke occupant; een occupant kan stanzas verzenden met een willekeurig
idin de chunk-payload.Impact
Een enkele vijandige occupant kan elke newcomer permanent blokkeren van de baseline, zonder de epoch-sleutel te bezitten. De aanval is onzichtbaar voor de newcomer (geen foutmelding, de sessie start gewoon nooit) en kost de aanvaller één stanza.
Oplossingsrichting
stanza.from(de in-room JIDroom@conf/nick) overeenkomt met de device-id in het chunk-id. De chunk-idbevat de afzender's deviceId — vergelijk dit met de device(s) die de directory kent voor datfrom-adres. Een chunk van eenfromdie geen device met dat deviceId heeft, wordt fail-closed gedropt.idte binden aan de verzegeling — bijv.id = hash(sealed.toContent())zodat een aanvaller geen geldigidkan construeren zonder de verzegeling te bezitten. Dit maakt ook replay/corruptie onmogelijk._assemble, zou de receiver een<resync>moeten kunnen vragen (het transport-pad bestaat al), zodat de autoriteit opnieuw stuurt. Momenteel heeft de snapshot-channel geen pad om een resync te triggeren — alleen het transport (op/lock-gap) doet dat.Locatie
lib/xmpp/xmpp_snapshot.dartregels 165–202 (handleSnapshot), 204–216 (_assemble)lib/xmpp/xmpp_collab_launch.dartregels 167–205 (syncNow— de herzend-logica)Severity
HIGH — een ongesleutelde occupant kan de hele samenwerking voor newcomers platleggen met één stanza.