Bladeren bron

Verify that Converse is not susceptible to CVE-2015-8688

https://gultsch.de/gajim_roster_push_and_message_interception.html
JC Brand 5 jaren geleden
bovenliggende
commit
37d052ad9e
3 gewijzigde bestanden met toevoegingen van 46 en 1 verwijderingen
  1. 41 0
      spec/roster.js
  2. 4 0
      src/headless/converse-roster.js
  3. 1 1
      tests/mock.js

+ 41 - 0
spec/roster.js

@@ -29,6 +29,47 @@
 
     describe("The Contacts Roster", function () {
 
+        it("verifies the origin of roster pushes",
+            mock.initConverse(
+                null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
+                async function (done, _converse) {
+
+            // See: https://gultsch.de/gajim_roster_push_and_message_interception.html
+            const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
+            await test_utils.waitForRoster(_converse, 'current', 1);
+            expect(_converse.roster.models.length).toBe(1);
+            expect(_converse.roster.at(0).get('jid')).toBe(contact_jid);
+
+            spyOn(_converse, 'log');
+            let roster_push = u.toStanza(`
+                <iq type="set" to="${_converse.jid}" from="eve@siacs.eu">
+                    <query xmlns='jabber:iq:roster'>
+                        <item subscription="remove" jid="${contact_jid}"/>
+                    </query>
+                </iq>`);
+            _converse.connection._dataRecv(test_utils.createRequest(roster_push));
+            expect(_converse.log.calls.count()).toBe(2);
+            expect(_converse.log).toHaveBeenCalledWith(
+                `Ignoring roster illegitimate roster push message from ${roster_push.getAttribute('from')}`,
+                Strophe.LogLevel.WARN
+            );
+            roster_push = u.toStanza(`
+                <iq type="set" to="${_converse.jid}" from="eve@siacs.eu">
+                    <query xmlns='jabber:iq:roster'>
+                        <item subscription="both" jid="eve@siacs.eu" name="${mock.cur_names[0]}" />
+                    </query>
+                </iq>`);
+            _converse.connection._dataRecv(test_utils.createRequest(roster_push));
+            expect(_converse.log.calls.count()).toBe(4);
+            expect(_converse.log).toHaveBeenCalledWith(
+                `Ignoring roster illegitimate roster push message from ${roster_push.getAttribute('from')}`,
+                Strophe.LogLevel.WARN
+            );
+            expect(_converse.roster.models.length).toBe(1);
+            expect(_converse.roster.at(0).get('jid')).toBe(contact_jid);
+            done();
+        }));
+
         it("is populated once we have registered a presence handler",
             mock.initConverse(
                 null, ['rosterGroupsFetched'], {},

+ 4 - 0
src/headless/converse-roster.js

@@ -594,6 +594,10 @@ converse.plugins.add('converse-roster', {
                     // attribute (i.e., implicitly from the bare JID of the user's
                     // account) or it has a 'from' attribute whose value matches the
                     // user's bare JID <user@domainpart>.
+                    _converse.log(
+                        `Ignoring roster illegitimate roster push message from ${iq.getAttribute('from')}`,
+                        Strophe.LogLevel.WARN
+                    );
                     return;
                 }
                 _converse.api.send($iq({type: 'result', id, from: _converse.connection.jid}));

+ 1 - 1
tests/mock.js

@@ -263,7 +263,7 @@
                 _converse.api.user.logout();
                 done();
             }
-            await Promise.all(promise_names.map(_converse.api.waitUntil));
+            await Promise.all((promise_names || []).map(_converse.api.waitUntil));
             func(_done, _converse).catch(e => { fail(e); _done(); });
         }
     };