xorl %eax, %eax

irssi event_wallops() off-by-one Read/Write

leave a comment »

This nice little vulnerability was discovered by the almighty nemo who reported it on 15 May 2009. irssi is one of the most popular minimalistic IRC clients. Here is the vulnerable function as seen in 0.8.13 release of irssi:

2  fe-events.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
      ...
284 static void event_wallops(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr)
285 {
286         g_return_if_fail(data != NULL);
287
288         if (*data == ':') data++;
289         if (ignore_check(SERVER(server), nick, addr, NULL, data, MSGLEVEL_WALLOPS))
290                 return;
291
292         if (g_ascii_strncasecmp(data, "01ACTION ", 8) != 0)
293                 printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_WALLOPS, nick, data);
294         else {
295                 /* Action in WALLOP */
296                 int len;
297                 char *tmp;
298
299                 tmp = g_strdup(data+8);
300                 len = strlen(tmp);
301                 if (tmp[len-1] == 1) tmp[len-1] = '\0';
302                 printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_ACTION_WALLOPS, nick, tmp);
303                 g_free(tmp);
304         }
305 }

This function can be found at src/fe-common/irc/fe-events.c and it handles the WALLOPS IRC command. So… this function initially checks that the data received are not NULL (line 286), then it checks that this is an IRC command, meaning that it starts with ‘:’ character and increments it to point to the command (line 288). It checks if the application should ignore this message (line 289) which it doesn’t by default. At line 292, if the command was not ACTION, then it prints the data using printformat(). However, if this is not the case, it moves to the else clause. It duplicates the command at line 299, stores its length at variable len at line 300. Then, at line 301 it attempts to remove the 0x01 prefix character that the IRC command has by replacing it with a NULL. Finally, it prints out the message and frees the allocated space for tmp.
What nemo noticed is that a user could use a command that has zero length at line 300, this could lead to a read out of bounds at line 301, and if there is an integer with value of 1 there, it will lead to an off-by-one underflow since it will overwrite the first integer of the previous chunk with NULL. To fix this, the following patch was applied:

               len = strlen(tmp);
-               if (tmp[len-1] == 1) tmp[len-1] = '\0';
+               if (len >= 1 && tmp[len-1] == 1) tmp[len-1] = '\0';
                printformat(server, NULL, MSGLEVEL_WALLOPS, IRCTXT_ACTION_WALLOPS, nick, tmp);

The bug is easy to spot but difficult to exploit, heap off-by-one exploitation is possible but definitely not a trivial task, and here, this must be done remotely which makes it even harder. nemo in his report provided information on how to reproduce the vulnerability.

Written by xorl

May 28, 2009 at 17:03

Posted in bugs

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s