Re: exim remote heap overflow, probably not exploitable

From: Nick Cleaton (nick_at_cleaton.net)
Date: 09/03/03

  • Next message: Gerardo Richarte: "InlineEgg library release"
    Date: Wed, 3 Sep 2003 20:11:27 +0100
    To: vuln-dev@securityfocus.com
    
    

    On Mon, Sep 01, 2003 at 07:00:34AM +0100, Nick Cleaton wrote:
    >
    > Exim (www.exim.org) is a message transfer agent (MTA) developed
    > at the University of Cambridge for use on Unix systems connected
    > to the Internet.
    >
    > There's a heap overflow in all versions of exim3 and exim4 prior
    > to version 4.21. It can be exercised by anyone who can make an
    > SMTP connection to the exim daemon.
    >
    > The overflow is very limited, and in my opinion it's probably not
    > exploitable. However, it's possible that this will prove to be
    > exploitable for arbitrary command execution on some platforms in
    > some circumstances.
    >
    > Patches:
    >
    > http://www.exim.org/pipermail/exim-announce/2003q3/000094.html
    >
    > Full details coming soon to vuln-dev.

    At line 1972 of exim-4.20/src/smtp_in.c :

      if (*smtp_data == 0) Ustrcpy(smtp_data, "(no argument given)");

    'smtp_data' is a pointer into the 513 byte heap buffer 'cmd_buffer'.

    A carefully formatted HELO or EHLO command can arrange for '*smtp_data'
    to be 0 and for 'smtp_data' to be within 2 bytes of the end of
    'cmd_buffer', so that the string "o argument given)" followed by a
    NULL is written off the end of cmd_buffer.

    Consider an input line consisting of "HELO" followed by 506 spaces
    followed by a NULL then a newline.

    This is the longest input line that this loop at line 441 will
    accept:

        while ((c = (receive_getc)()) != '\n' && c != EOF)
          {
          if (ptr >= cmd_buffer_size)
            {
            os_non_restarting_signal(SIGALRM, sigalrm_handler);
            return OTHER_CMD;
            }
          cmd_buffer[ptr++] = c;
          }

    Now the code at line 462 removes any trailing whitespace from the
    buffer and NULL terminates it:

      while (ptr > 0 && isspace(cmd_buffer[ptr-1])) ptr--;
      cmd_buffer[ptr] = 0;

    but it doesn't trim all our spaces because the NULL we put at the
    end of the line protects them. At this point the buffer is mostly
    full of spaces, but the last two chars in the buffer are NULLs.

    Now smtp_data is pointed to the character after the HELO command,
    and then advanced over any whitespace by this code at line 508:

       while (isspace(*smtp_data)) smtp_data++;

    after which smtp_data points to the NULL at byte 511 of cmd_buffer.

    We can, of course, choose to use less space characters so as to
    write less far off the end of the buffer. So, we can write a single
    NULL up to 18 bytes off the end of the buffer, with the side effect
    of writing ASCII over everything up to the NULL.

    Papers such as http://www.phrack.org/show.php?p=57&a=8 and
    http://bespin.org/~qitest1/txt/heap_off_by_one.txt.asc suggest that
    it might well be exploitable under linux.

    My main reason for rating this as "probably not exploitable" even
    under Doug Lea's malloc is that the 513 byte buffer is never
    free()ed, and neither is the 8192 byte buffer that gets malloc()ed
    immediately after the 513 byte buffer.

    A quick scan of the exim sources didn't find much in the way of
    free() calls on buffers over 512 bytes in any code that runs in
    normal circumstances before these two buffers get allocated, so I'm
    imagining that it's likely that they'll both come off the wilderness
    chuck. The relevant part of the heap will then look something like:

          513ByteBuffer CorruptBoundaryTag 8192ByteBuffer

    and the corrupt boundary tag will never be accessed since the chunks
    before and after it are never free()ed.

    Does that seem reasonable, or am I in dreamland ?

    Can anyone get as far as a segfault on some platform ?

    --
    Nick Cleaton
    nick@cleaton.net
    

  • Next message: Gerardo Richarte: "InlineEgg library release"

    Relevant Pages

    • Re: server scenario - variables in the right spot?
      ... If I'm correct in what I think you mean by 'data structures' then I also ... steps, the command has, and a way to mark which steps are done or not done, ... Assuming you are using the same receive callback for each BeginReceive, ... that processes the data for the first buffer. ...
      (microsoft.public.dotnet.languages.csharp)
    • Re: server scenario - variables in the right spot?
      ... ReceiveCallback calling beginReceive again: I do this but not exactly how ... Assuming you are using the same receive callback for each BeginReceive, then I don't see what the difference is. ... The posted receive won't be completed until after the command has been sent and replied to, of course, but there's no harm in being ready to receive beforehand. ... you would wind up running the code in the callback that actually processes the data for that buffer before the code in the same callback that processes the data for the first buffer. ...
      (microsoft.public.dotnet.languages.csharp)
    • Re: In vi/vim delete lines
      ... I frequently delete to a mark. ... | A buffer containing lines is put only once, ... | If the last command before a `.' ... The basic meta-characters for the replacement pattern are `&' and `~'; ...
      (comp.unix.shell)
    • Re: Spartados Help Needed
      ... All command line input, including all ... in the buffer during a key repeat. ... However, the XIO Atari ... your lomem will be at $17A2. ...
      (comp.sys.atari.8bit)
    • [SECURITY] telnet client
      ... For general information regarding FreeBSD Security Advisories, ... The telnetcommand is a TELNET protocol client, ... fixed-sized buffer. ... src/UPDATING ...
      (comp.unix.bsd.freebsd.misc)