XMPP: Admin-in-the-middle

XMPP: Admin-in-the-middle

Every time somebody discusses instant messaging, at least one person shows up and recommends XMPP. We talked about myths of federation last time and showed you that there are several issues with XMPP. However, some people still consider XMPP to be an extremely privacy-friendly way of messaging nowadays.

In this article, we show you the power of an XMPP server admin and encourage you to always use your own XMPP server (or switch to more secure services).


  1. Setup
  2. Test 1: Monitor all connections
  3. Test 2: Use ejabberdctl for information gathering
  4. Test 3: Analyze the Mnesia database
  5. Test 4: See content of messages and passwords in cleartext
  6. Test 5: Manipulate user data
  7. Lessons learned
  8. Summary
  9. Links
  10. Sources
  11. Changelog

Always stay in the loop!
Subscribe to our RSS/Atom feeds.



For our experiment, we installed the latest version of ejabberd (18.06) on Debian 9. We mostly didn’t change the defaults. This doesn’t matter since the end user can’t see most of the configuration when connected to an XMPP server.

In ejabberd.yml, we added the domain name and IP address of our server and enabled “in-band registration”. Furthermore, we opened the ports 5222 (client-to-server connections, c2s) and 5269 (server-to-server connections, s2s).


We used three clients. Two Android phones had Conversations 2.2.8 (via F-Droid) and one Linux device had Gajim 1.0.3 installed.

Test 1: Monitor all connections

First of all, we wanted to monitor all c2s and all s2s connections. This is quite simple since you only need tcpdump or Wireshark. We ran tcpdump on the server and used another computer for monitoring:

#! /bin/bash
mkfifo /tmp/pcap_file
ssh [username]@[xmppserver] "tcpdump -n -w - -i ens3 '(port 5222) or (port 5269)'" > /tmp/pcap_file
wireshark -k -i /tmp/pcap_file

This allowed us to monitor all XMPP-relevant connections in real time. The result:

  • We see all public IP addresses of users of our XMPP server
  • We see all IP addresses of other servers which host users who chat with users of our server

Of course, this includes metadata like:

  • IP addresses of sender and receiver of each packet
  • timestamps
  • approximate location based on the IP address
  • bytes transmitted (one can differentiate between actual messages and XMPP status messages)
  • number of packets sent/received
  • etc.

Note that since TLS encryption is in place by default, we weren’t able to directly see the content of these packets. This metadata is also visible for the company which provides this server and others.

Having said this, we noted that the default TLS configuration of ejabberd is not that secure:

  • TLS 1.0, TLS 1.1 and TLS 1.2 are enabled (TLS 1.2 only is recommended)
  • self-signed certificate using RSA (2048 bit) (use one signed by a CA)
  • Key sizes of 256 bits (ECC) resp. 1024 bits (DH) for key exchange (use 384+ bits resp. 2048+ bits)
  • Several cipher suites don’t support perfect forward secrecy and/or AEAD
Part of the default TLS configuration of ejabberd. Green and blue fields can be considered secure in 2018. Red and gray is insecure.
Part of the default TLS configuration of ejabberd. Green and blue fields can be considered secure in 2018. Red and gray is insecure. (🔍 Zoom in)

Note that several XMPP server admins started to harden their servers for better transport security. This makes it impossible to establish server-to-server connections with their hardened servers if you use the defaults here.

Feedback of our readers

One reader considered this first test invalid due to unknown reasons.

Admins, server providers, ISPs and some other third parties are able to monitor traffic even if TLS is in use. Since XMPP ports are well-known and there is even cleartext XMPP traffic sent by default, third parties are able to identify this traffic. Of course, this is also true for other services. We never denied this. The first test is about awareness for XMPP metadata and passive network surveillance.

Test 2: Use ejabberdctl for information gathering

ejabberdctl is an administration script and very powerful. The server admin can use it to gather information about all server users. For instance:

  • See all users connected to the server (connected_users_info), including JID, type of connection, IP address, port number, resource priority, session duration
  • See all devices of a connected user (user_resources)
  • See all contacts of a user (get_roster)
  • See all MUCs (muc_online_rooms)
  • See all MUC options (get_room_options)
  • See all MUC affiliations (get_room_affiliations) like owner, admin, member, outcast, none
  • See all MUCs where a user is occupant (get_user_rooms)
  • Read content of vCards (get_vcard)
  • etc.

This shows that an admin can access most private data of users including their contact lists, their group memberships and other personal data like IP addresses, names, devices and so on. The admin doesn’t have to directly access the database or monitor traffic. He can just use ejabberdctl.

Feedback of our readers

Several readers mentioned that this test is true for all services that require servers.

It depends. Some services store your contacts and group memberships client-side and introduced other measures to hide this data from servers.

Test 3: Analyze the Mnesia database

We want to learn more about our users. Let’s analyze the database! By default, ejabberd uses Mnesia to store all data. An admin can simply enter sudo ejabberdctl dump dump.txt to dump the whole Mnesia database to dump.txt stored in the Mnesia folder. This file includes:

  • user-specific data for SCRAM-SHA-1 used for authentication (hashed password, salt, number of iterations)
  • user-specific key material (e.g. for OMEMO PreKeys)
  • PEP (Personal Eventing Protocol) information
  • last activity of users
  • private storage of users (bookmarks like saved MUCs)
  • all MUCs (members, options)
  • the same information accessible with ejabberdctl and more

Since most of it is stored in cleartext and the admin has direct access, he can read and change most of the values in the database.

Test 4: See content of messages and passwords in cleartext

So far, we didn’t read actual messages or passwords. This is also very easy. Just change the log level in ejabberd.yml to loglevel: 5 and restart the server! Now, the logging operates in debug mode which means that every message will be logged in ejabberd.log. This includes:

  • message metadata (message ID, from JID+client to JID, timestamp)
  • message content (if no encryption in use), may include images, files, location data, audio files
  • message status (received by a client, displayed (= read by) to a user)
  • client status (offline, online, typing)
  • non-public user actions (user changed avatar, status message, vCard information or created a private MUC)
  • passwords in cleartext even if SCRAM is enabled (every time users register a new account or change their password)
  • and more!
Cleartext passwords in ejabberd.log. Every time a user registers an account or changes his password, his password is logged (in-band registration is used in this example.
Cleartext passwords in ejabberd.log. Every time a user registers an account or changes his password, his password is logged (in-band registration is used in this example. (🔍 Zoom in)

Logging in debug mode basically logs every event. Combined with traffic data, an admin can monitor every single action of all users on the server. However, this not only includes users of this server but also users of other servers who are members in MUCs of this server or chat with people on this server.

Feedback of our readers

Some readers said that one can use OTR/OMEMO etc. to trust contacts and write private messages.

This is true, however, OTR/OMEMO etc. only protect the content of messages while metadata, status information, passwords and so on remain exposed in cleartext. Furthermore, there are some discussions on GitHub that put a question mark over the security of the OTR implementation in the Conversations client.

Test 5: Manipulate user data

Up to this point, the admin was somewhat passive in his actions. Let’s manipulate data now! We return to ejabberdctl to:

  • inject fake messages from arbitrary JIDs (send_message chat) even if these users aren’t on this server, see image below (Conversations shows these messages, Gajim ignores them until the sender JID of the message is in the user’s roster)
  • add arbitrary JIDs to a user’s contact list (add_rosteritem) or delete JIDs (delete_rosteritem)
  • arbitrarily change vCards of users (set_vcard)
  • invite users to MUCs (send_direct_invitation) and let them be owner (set_room_affiliation) while kicking the original owner (muc_unregister_nick) or make him member. Of course, admins can change all options of MUCs (change_room_option)
  • delete messages older than x days if not delivered (delete_old_messages)
  • and more
Conversations shows this faked message from snowden@nsa.gov (which can't be true since Mr. Snowden uses Signal!). Gajim only shows such messages after an admin added the fake sender to the user's contact list.
Conversations shows this faked message from snowden@nsa.gov (which can't be true since Mr. Snowden uses Signal!). Gajim only shows such messages after an admin added the fake sender to the user's contact list. (🔍 Zoom in)

This shows that the admin not only can read nearly everything but also manipulate data arbitrarily.

Lessons learned

This whole article isn’t about telling you that XMPP is super bad and you shouldn’t use it at all but to raise your awareness for the admin-in-the-middle. The main problems with XMPP are:

  • nearly everything is stored in cleartext on the server
  • OMEMO isn’t widespread while some clients dropped OTR which is somewhat awkward since this could force you to deactivate end-to-end encryption completely
  • even OMEMO and the Tor network provide little protection since most data remains unencrypted
  • your personal data is shared with other servers as soon as you chat with remote users or join remote MUCs which exposes your data to other admins
  • most of the admin’s actions are fully transparent which means that you can’t detect them as a user

What’s next? The clear recommendation is to either run your own XMPP server (which isn’t easy at all) or switch to other messaging systems like Signal. Why Signal?

  • Signal doesn’t store information about you (name + profile picture), your contacts or chat rooms on its servers, so they can’t change this data
  • Signal is far easier to use since registration only requires an arbitrary phone number
  • Signal enforces modern end-to-end encryption making it impossible to read or manipulate messages
  • Signal has implemented mechanisms to obfuscate groups and group memberships so that servers don’t learn about them
  • Contrary to popular belief, Signal doesn’t have to access your contacts at all

If you want to run your own XMPP server, have a look at the (incomplete) checklist below:

Feedback of our readers

Some readers repeatedly told us that Signal is evil, centralized and we shouldn’t recommend it at all. Additionally, they say that Signal is neither available on F-Droid nor “free” software and its developers hate federation (and so on).

We discussed some of these points in our “Federation myths” article (esp. in myth 2 and 3). If you don’t like Signal, don’t use it. However, don’t try to force us to tell our readers your ideological beliefs. Thanks.

Follow us on Mastodon:


Your XMPP server admin can access nearly all of your personal data and tons of metadata in cleartext. He becomes even more powerful if he runs more than one XMPP server. You have to trust and hope that the admin doesn’t abuse this power and that appropriate security measures are in place so that no third party can access your data, too. Unfortunately, server breaches are neither rare nor uncommon nowadays. Interestingly, many XMPP servers seem to be run by people in the European Union but only a small fraction published an obligatory privacy policy.

Moreover, passive monitoring of the network traffic makes it easy to identify which IP addresses connect to a server as clients (port 5222) or as another XMPP server (port 5269). Client and server actually exchange several unencrypted XMPP messages before talking over TLS when you connect to a server. Server providers, your ISP and other parties can easily see whether you use a particular server for XMPP communication. To avoid this, you always have to use Tor which makes things more complicated.

Running your own XMPP server requires knowledge about server security, regular maintenance and knowledge about XMPP server software. You shouldn’t consider running your own server as a “fire and forget” activity. As soon as your server becomes federated and you start chatting with remote users and participate in remote MUCs, some of your data will be out of control again. Moreover, you have to sometimes cope with incompatible server and client software. Last October, Tor and privacy activist Moritz Bartl (Zwiebelfreunde e.V.) stated that it is easy for state actors to monitor XMPP traffic and identify all server users. Furthermore, he is convinced that most XMPP server and client software is more a leisure project than secure software.

Tested and written in collaboration with Thorsten.



  • November 2, 2018: Added and commented some feedback of our readers.
  • August 17, 2018: Added image showing cleartext passwords in ejabberd.log. Added information about Tor in the summary.

See also