Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 5 Oct 2015 00:38:50 +0200
From: "Jason A. Donenfeld" <Jason@...c4.com>
To: misc <misc@...nsmtpd.org>, oss-security <oss-security@...ts.openwall.com>
Subject: Remotely triggerable buffer overflow in OpenSMTPD

Hi folks,

I'm passing the gauntlet for anyone who wants to analyze this for
impact etc. There's a remotely triggerable buffer overflow in
OpenBSD's OpenSMTPD -- the latest version, 5.7.2 -- reachable by
sending messages with huge header lines. Qualys recently published a
result of a big audit, but it seems like they based their
investigations primarily on an older version of OpenSMTPD that didn't
have as much of the "filter" infrastructure. I'd recommend interested
parties spend some time looking through the filter code, as there
could be more problems. Here's a vulnerability in the filter io path:

static void
filter_tx_io(struct io *io, int evt)
{
        struct filter_session   *s = io->arg;
        size_t                   len, n;
        char                    *data;
        char                    buf[65535];

        log_trace(TRACE_FILTERS, "filter: filter_tx_io(%p, %s)", s,
io_strevent(evt));

        switch (evt) {
        case IO_DATAIN:
                data = iobuf_data(&s->ibuf);
                len = iobuf_len(&s->ibuf);
                memmove(buf, data, len);
                buf[len] = 0;
                log_trace(TRACE_FILTERS, "filter: filter_tx_io: datain
(%zu) for req %016"PRIx64": %s",
                    len, s->id, buf);


In this block, it's possible for `len` to be greater than 65535. I
believe the maximum is 65536, but I've spent not too much time playing
with this to be sure. Either way, the memmove() overflows `buf`. When
len=65536, GNU's fortify source catches it and kills the program. I'm
not sure the behavior on OpenBSD or other platforms. Depending on the
layout of the stack, being able to overwrite two bytes (or perhaps
more? which would be even worse) could lead to execution, but, again,
I haven't looked for more than a few minutes, so I'm not sure.

I'm attaching here a crash reproducer. Running `sendmail
instance@...ng.opensmtpd < this.email.attachment` will result in a
remote OpenSMTPD dying (at least on GNU systems with fortify source;
on others, the behavior is undefined).

If the execution makes it past that memmove, and filter tracing is
enabled, this line is printed:

filter: filter_tx_io: datain (65536) for req 8e6eab5b833e834b: x-xxx-xxxxx: xx

If execution hits a fortify source abort point, this is the stack trace:

(gdb) bt
#0  0x0000003c6f433468 in raise () from /lib64/libc.so.6
#1  0x0000003c6f43483a in abort () from /lib64/libc.so.6
#2  0x0000003c6f472381 in __libc_message () from /lib64/libc.so.6
#3  0x0000003c6f4f8077 in __fortify_fail () from /lib64/libc.so.6
#4  0x0000003c6f4f6110 in __chk_fail () from /lib64/libc.so.6
#5  0x0000000000412840 in memmove (__len=65536, __src=0x1cff900,
__dest=0x7ffe12cf0e10)
    at /usr/include/bits/string3.h:59
#6  filter_tx_io (io=<optimized out>, evt=<optimized out>) at
../../smtpd/filter.c:739
#7  0x00000000004154c0 in io_dispatch (fd=<optimized out>,
ev=<optimized out>, humppa=0x1c957d8)
    at ../../smtpd/ioev.c:580
#8  0x0000003c82820044 in event_process_active_single_queue () from
/usr/lib64/libevent-2.1.so.5
#9  0x0000003c82820ddf in event_base_loop () from /usr/lib64/libevent-2.1.so.5
#10 0x000000000042d069 in pony () at ../../smtpd/pony.c:221
#11 0x00000000004071cc in fork_peers () at ../../smtpd/smtpd.c:829
#12 main (argc=<optimized out>, argv=<optimized out>) at ../../smtpd/smtpd.c:724

If my assumption is correct about 65536 being the maximum of len, I'd
recommend making that buffer be size 65537, or making it size 65536
and being smart about that buf[len]=0 line. If my assumption isn't
correct about 65536, perhaps the code will have to be more
significantly refactored. Probably the OpenSMTPD/OpenBSD developers
can make the best choice here though.

At some point we might want a CVE for this.

Thanks,
Jason

Download attachment "opensmtpd-buffer-overflow-large-header.crash" of type "application/octet-stream" (90141 bytes)

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.