xorl %eax, %eax

CVE-2009-1789: Eggdrop/Windrop PRIVMSG Underflow

with 2 comments

This vulnerability was disclosed by Thomas Sader on 14 May 2009. The bug affects Eggdrop and Windrop 1.6.19 and probably earlier releases. Eggdrop is one of the most popular open source IRC bots. Here is the vulnerable code as seen in src/mod/server.mod/servmsg.c:

2  * servmsg.c -- part of server.mod
3  *
4  * $Id: servmsg.c,v 1.95 2008-02-16 21:41:10 guppy Exp $
5  */
6 /*
7  * Copyright (C) 1997 Robey Pointer
8  * Copyright (C) 1999 - 2008 Eggheads Development Team
 ...
446 /* Got a private message.
447  */
448 static int gotmsg(char *from, char *msg)
449 {
450   char *to, buf[UHOSTLEN], *nick, ctcpbuf[512], *uhost = buf, *ctcp,
451        *p, *p1, *code;
452   struct userrec *u;
453   int ctcp_count = 0;
454   int ignoring;
 ...
490       ctcp = ctcpbuf;
491       /* copy the part after the second : in front of it after
492        * the first :, this is temporary copied to ctcpbuf */
493       strncpy(p1 - 1, p + 1, strlen(ctcpbuf) - 1);
 ...
590   return 0;
591 }

This function is used to handle the private messages (PRIVMSG) received by eggdrop. However, when it attempts to copy the part after the second ‘:’ it uses strncpy(3) in an unsafe manner. IRC PRIVMSG command has a format similar to:

:PRIVMSG <receiver>{,<receiver>} : <text to be sent>

But the above code doesn’t check whether there are any data after the second ‘:’. This means that ctcpbuf that contains those data might contain 0 bytes. At line 493 the length of that buffer is used as a size limit like this:

strlen(ctcpbuf) - 1

Of course, if there are no data in it, it will result to -1 since it will wrap around zero (or 0xFFFFFFFF since it is also promoted size_t) and it will attempt 4GB of data to p1-1 which almost certainly will crash the eggdrop with a segmentation fault. This was patched like this:

 ctcp = ctcpbuf;
-      /* copy the part after the second : in front of it after
-       * the first :, this is temporary copied to ctcpbuf */
-      strncpy(p1 - 1, p + 1, strlen(ctcpbuf) - 1);
+
+      /* remove the ctcp in msg */
+      memmove(p1 - 1, p + 1, strlen(p + 1) + 1);

This bug was introduced as a patch to CVE-2007-2807 which was an strcpy(3) stack overflow. Once again, this was classified as a DoS vulnerability. I am not saying that this is trivial to exploit but there is certainly a possibility of code execution. I don’t understand why someone classifies a memory corruption vulnerability as DoS… Again, ANY memory corruption vulnerability might lead to code execution.

For this bug, consider a case where you can manipulate the previous stack frames so that they contain some data that you’ll use to overwrite  p1-1 and just terminate them with a NULL, even if size limit is 4GB, strncpy(3) will stop when it finds that NULL. It isn’t impossible…. Anyway…

Written by xorl

May 29, 2009 at 23:06

Posted in bugs

2 Responses

Subscribe to comments with RSS.

  1. Actually, strncpy does not stop when it finds a NULL in src:

    “char *strncpy(char * restrict s1, const char * restrict s2, size_t n);
    […]If the array pointed to by s2 is a string that is shorter than n characters, null characters are appended to the copy in the array pointed to by s1, until n characters in all have been
    written.[…]”

    Some libc’s might deviate from this specification, but at least both glibc and OpenBSD’s libc pads with NULLs.
    So it will always be a 4GB write. It seems to me that it’s impossible to avoid a segfault and, unless the signal handler is vulnerable in some way, achieve code execution.

    chasoto

    May 30, 2009 at 16:28

  2. That’s true. Windows’ libc pads it too. I just gave an example, I haven’t exploited it. Nevertheless, classifying a memory corruption vulnerability as DoS is wrong in my opinion. That was my point.
    Another interesting to check condition is if that underflow overwrites a SEH handler or something similar with NULL. Again, just a suggestion.

    xorl

    May 30, 2009 at 17:04


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