POSTED BY: Dimitrios Glynos / 25.02.2012

libpurple OTR information leakage

census ID:census-2012-0001
CVE ID:CVE-2012-1257
Affected Products:libpurple (all versions), libpurple clients with DBUS support (incl. all versions of pidgin), pidgin-otr (all versions)
Class:Information Exposure (CWE-200), Privacy Violation (CWE-359), Information Exposure Through Sent Data (CWE-201)
Remote:No
Discovered by:Dimitris Glynos

libpurple-based applications broadcast the plaintext of OTR (off-the-record) conversations over DBUS. This makes the plaintext available to other (possibly unrelated) applications executing under the same user. Also, due to a design flaw in libpurple, the user’s choice of not logging OTR plaintext on Pidgin is not communicated over to the third party applications listening on DBUS. This may lead to unintentional (on disk) logging of private messages.

Details

libpurple is an Instant Messaging (IM) library developed by the Pidgin project. It is used by a number of IM clients including Pidgin and Adium. libpurple-based clients support the OTR (“Off-the-Record”) protocol either natively or via a plugin. The OTR messaging protocol enables users to communicate securely over any IM network.

If libpurple is compiled with DBUS support and there is a DBUS session daemon running on the system, then all messages passing through libpurple are broadcasted over DBUS. The reason behind this is to allow for third party applications, such as desktop widgets to process these messages (e.g. create an animation when a message arrives). However, among the messages transmitted over DBUS one also finds the plaintext form of OTR conversations. This is a security problem, as the private OTR messages may leak to other (unrelated) processes that are executing under the same user as the libpurple-based application.

The core issue lies in the fact that when private information is broadcasted over DBUS there is no guaranty as to which applications will receive this and how they will handle it. The IM client that decrypts OTR ciphertext might enforce special security policies to protect the plaintext (such as disallow logging), but there is no way of making these policies mandatory for the 3rd party applications that receive the plaintext via DBUS. The sender essentially relies on the receiver being a “good citizen” and honoring the security attributes of incoming DBUS signals.

Also, as pointed out by Howard Chu, libpurple does not allow for full attribute manipulation by plug-ins. Hence, with the current API of libpurple, it is impossible for pidgin-otr to indicate to other applications that logging is prohibited for private messages.

Exploitation Notes

This issue is associated with a low risk factor, as it requires from an attacker to have already gained same-user access to the victim user’s host. However, we will provide some exploitation notes on this, mostly for reasons of completeness. For our exploitation example we will be focusing on the popular libpurple-based application, Pidgin.

To snoop in on a Pidgin user’s conversation a remote attacker would need to connect to the DBUS daemon that is responsible for the user’s session. There are at least two ways to achieve this.

The first one is to exploit an application that runs within the same desktop session as Pidgin. This application would have inherited the necessary DBUS_SESSION_BUS_ADDRESS environmental variable and would thus be able to connect to the DBUS daemon over a unix socket without a problem.

The second way is to compromise the user’s account in some way and steal the DBUS_SESSION_BUS_ADDRESS value. There are multiple ways of acquiring the value for this variable, one of them being through /proc/<pid>/environ (which is accessible to processes of the same owner), and another being through a file in ~/.dbus/session-bus/. Using this value, the attacker would now be able to connect to DBUS with applications that are not part of the desktop session.

Please note that the above methods do not require any control over the Pidgin process (ptrace or other).

pidgin-otr-snooping.py is a proof-of-concept Python script that connects to DBUS and prints all messages received via Pidgin’s “ReceivedImMsg” and “WroteImMsg” signals. The example below shows messages transmitted during an OTR conversation:

user@host:~$ python pidgin-otr-snooping.py
sent 'hey' to user1@example.com
received 'ho' from user1@example.com
sent 'lets go!' to user1@example.com

An exploited application that connects to DBUS (or reuses an already established connection) to listen for private messages provides identical forensic evidence (logs) as any application that connects to DBUS for legitimate purposes. It is thus difficult to identify in-memory eavesdropping of this sort, especially in cases where there is no supportive evidence that might suggest it (offending process image, related traffic logs etc.).

Discussion

A possible way to fix this issue is for libpurple to support a new type of IM messages, i.e. private messages.

Most (if not all) communication primitives in libpurple use a flags parameter (of type PurpleMessageFlags) to qualify the type of message being transmitted/received. The example below shows the prototype of such a communication function from pidgin-2.10.1/libpurple/server.c:

557 void serv_got_im(PurpleConnection *gc, const char *who, const char *msg,
558                           PurpleMessageFlags flags, time_t mtime)

The PurpleMessageFlags type is defined in pidgin-2.10.1/libpurple/conversation.h as follows:
105 typedef enum
106 {
107         PURPLE_MESSAGE_SEND        = 0x0001, 
108         PURPLE_MESSAGE_RECV        = 0x0002, 
109         PURPLE_MESSAGE_SYSTEM      = 0x0004, 
110         PURPLE_MESSAGE_AUTO_RESP   = 0x0008, 
111         PURPLE_MESSAGE_ACTIVE_ONLY = 0x0010,
118         PURPLE_MESSAGE_NICK        = 0x0020, 
119         PURPLE_MESSAGE_NO_LOG      = 0x0040,  
120         PURPLE_MESSAGE_WHISPER     = 0x0080, 
121         PURPLE_MESSAGE_ERROR       = 0x0200, 
122         PURPLE_MESSAGE_DELAYED     = 0x0400, 
123         PURPLE_MESSAGE_RAW         = 0x0800, 
125         PURPLE_MESSAGE_IMAGES      = 0x1000, 
126         PURPLE_MESSAGE_NOTIFY      = 0x2000, 
127         PURPLE_MESSAGE_NO_LINKIFY  = 0x4000, 
129         PURPLE_MESSAGE_INVISIBLE   = 0x8000  
130 } PurpleMessageFlags;
This enumeration could be extended to include a new type for private messages. Private messages should by default not be logged by applications or be broadcasted over DBUS.

Updates

The Pidgin/libpurple development team has acknowledged this issue.

On a related note, Nadim Kobeissi has reported a similar leak in Adium. Apparently Adium forwards OTR plaintexts to the Growl notification system which by default keeps them in its notification history.

Disclosure Timeline

Vendor Contact(s):December 20th, 2011 [1, 2, 3]
CVE assignment:February 21st, 2012
Public Disclosure:February 25th, 2012

Acknowledgements

We would like to thank Peter Lawler for his helpful comments.