Converse.js leaking information about which rooms are bookmarked
CVE-2018-6591: When storing bookmarks on the server Converse.js does not properly configure the access model to be private.
The Personal Eventnig Protocol (PEP) is a commonly used extension (XEP) for XMPP. It is a subset of the more powerful Publish-Subscribe (XEP-0060), operating on the user’s account. Primarily it is being used to publish information like a user’s avatar or nick name, that should be visible to other contacts. Each type of information is stored on a different »node«. The default access model of a node is set to be readable by everyone with mutual presence subscription (=contacts). If desired the access model can be changed to being readable by everyone (=open) or to being only readable by the owner. However not every XMPP server supports changing the access model.
Private Data in PEP
Some XMPP extensions like XEP-0048: Bookmarks suggest to store private information in PEP and refer to another extension (XEP-0223) on how to conveniently change the access model of a node and upload new information within the same request. However the server will silently ignore the part of the request requesting the change of access model if it doesn’t support it. A recent change to XEP-0060 introduced a way for a client to discover whether or not a server actually supports publishing and changing the access model simultaneously.
Converse.js up to version 3.3 does not properly check if the server supports changing the access model before uploading bookmarks into PEP. Therefore the bookmark node stays with the default access model, giving all contacs access to that information.
However the real issue at hand is the lack of discoverability of the necessary steps for client developers. A client developer has to read through four different protocol extensions to discover that the way of changing the access model described in XEP-0223 is actually optional and will be ignored by the server if not supported. Just following the examples provided by XEP-0223 will ultimately create a vulnerable client.
The lack of discoverability of that information is made apparent by other library developers making the exact same mistake. The Slixmpp library for example has a mechanism of storing private information in PEP but no built-in mechanism for checking if it is safe to do so. The only reason applications using that library are not affected by this vulnerability is that Slixmpp uses a different storage backend for bookmarks by default, and thus the private PEP code is never actually invoked unless a client developer changes the default storage backend.
Update: According to source code documentation of the command line client Poezio, which is using Slixmpp, it will use PEP as a storage mechanism if the legacy storage mechanism (XEP-0049: Private XML Storage) is not available or when explicitly configured to do so.
Assuming a user has ever used a vulnerable client to modify their own bookmarks, everyone with mutual presence subscription will be able to retrieve that user’s bookmarks using the items retrieval mechanism described in section 6.5 of XEP-0060. The bookmarks also include the passwords for password protected group chats.
Due to the automatic subscribtion mechanism built into PEP, that was designed for users to be notified once a contact changes their avatar for example, it is sufficent to put the feature storage:bookmarks+notify into one’s disco features to be automatically notified whenever a contact adds or removes a new bookmark.
Converse.js needs to check if the server annouces the http://jabber.org/protocol/pubsub#publish-options feature on the user’s account before attempting to publish private data into PEP. (Section 7.1.5 of XEP-0060). Other client developers who want to migrate to storing private data into PEP must do the same. Library developers should provide an easy method for performing that check.
I have previously documented the correct approach for using PEP with a different access model.
Given the uncertainty of how many other clients out there might be affected or how long they’ll remain unpatched it might be worthwhile for servers, which do not support changing the access model on nodes, to at least prevent third parties from accessing the storage:bookmarks node, independently of what access model they are configured with. (It is safe to assume that the access model for this node is never meant to be something other than private.)