Fetchmail security advisory

From: antirez (antirezat_private)
Date: Thu Aug 09 2001 - 15:03:41 PDT

  • Next message: Matt Zimmerman: "Re: Fetchmail security advisory"

    Fetchmail advisory, copyright(C) 2001 Salvatore Sanfilippo
    Distribution of this document is unlimited.
    
    THE PROBLEM
    
    In a security auditing I found two remotly explotiable
    memory corruption problems. The bug, that is similar
    in the file pop3.c and imap.c, allows an attacker to
    'poke' arbitrary memory addresses with 32 bit data, so you
    can write what you want in memory.
    
    Protections like stackguard WITHOUT the xor-canary active
    will not be effective against this problem.
    
    To exploit the problem you need to impersonate the server,
    so the attacker can be the server itself or, faking the
    DNS resolver, some other attacker. See the last section
    of this document about DNS forgery information.
    
    IMPACT
    
    The attacker can execute arbitrary code in your system,
    both if fetchmail is running as user or as root.
    If the attacker is able to fake your DNS resolver or
    your DNS server it can take control of your system even
    without to take control of one of your POP3/IMAP servers.
    
    VERSION AFFECTED
    
    Probably all the fetchmail versions prior (not including) 5.8.17.
    
    THE CODE
    
    This is the relevant portion of code affected:
    
    pop3.c:
    
    static int pop3_getsizes(int sock, int count, int *sizes)
    [snip]
            while ((ok = gen_recv(sock, buf, sizeof(buf))) == 0)
            {
                int num, size;
    
                if (DOTLINE(buf))
                    break;
                else if (sscanf(buf, "%d %d", &num, &size) == 2)
                    sizes[num - 1] = size;
            }
    [snip]
    
    The problem is just the same in the file imap.c, see yourself.
    
    As you can see you can pass two integers, num and size.
    The first is your offset, the second the 32bit value you
    want to write in the memory location.
    
    You can provide negative and positive offsets (num) so you
    can write both before and after the address of the 'sizes' pointer.
    
    To write you should simulate the POP3 session, wainting for the
    LIST command. Than issue a fake LIST response. The following is part of
    the output of the exploit you can find attached:
    
    +OK			(banner)
    +OK			(user)
    +OK			(password)
    +OK 10 0		(stat)
    +OK 0			(last)
    +OK			(list)
    -30 -1431655766		(first line of the list output)
    -29 -1431655766		(second line ...)
    [snip]
    .
    
    The 'sizes' buffer is stack allocated (with alloca()), and
    is the number of messages in the STAT response * sizeof(int) so you
    can request a piece of memory to put your shellcode,
    you can also put it in some static buffer (try grep 'static char' *.c) to
    exploit in a more portable way.
    
    Note that alloca() used where you can get a big 'size' argument
    isn't a big idea. You can also crash fetchmail just providing a
    very big response to STAT.
    
    THE FIX
    
    Fetchmail should use %u %u instead of %d %d as scanf format string,
    than do a sanity check about the message number the server provide
    in the LIST response lines and in the STAT response.
    
    DNS FORGERY
    
    The exploit may be used without to take the control of the
    POP/IMAP server if you are able to spoof a DNS packet with
    the right destination port and query ID. This is quite hard
    but not impossible, and it is strictly related to the resolver
    library the victim is using.
    
    DNS forgery against software like fetchmail will probably
    be simpler than against other software since in daemon
    mode fetchmail polls the mailbox with a fixed period, and
    resolves the name every time it polls. You have a lot
    of try.
    
    As stated, this issue is related to the libc, not to fetchmail itself,
    but a weak libc resolving rutine will help a lot the attacker.
    In the case of glibc 2.x you should guess the following stuff:
    
    pid, seconds, useconds, source port, query time, DNS server ip address.
    [with glibc, the ID is computed using something like (PID xor USEC xor SEC)]
    
    pid: you can try the whole pid space, or a subset assuming
    fetchmail in daemon mode running with a pid in the range
    1-500 or so.
    
    seconds, useconds: you can use ICMP timestamp to syncronize, this
    may reduce your 2^16 ID space a lot.
    
    source port: I never tested this but maybe sending UDP packets
    to different ports you may be able to guess high ports
    that are open by the DNS resolver, to do this you need to
    send this UDP packets spoofed from the victim DNS server
    than try to see the IP ID sequence. It isn't trivial
    but may work. Someone on the list known something of better?
    
    query time: With fetchmail is quite simple, you can try to send
    your fake DNS responses without to stop, waiting (hoping) for
    a natural syncronization with the query time. This will only
    work with fetchmail in daemon mode, and will work better
    if the poll time is short. Of course the IP ID will help you
    a lot of the host is in idle.
    
    As you can guess, if you can't fake the DNS you can anyway exploit
    fetchmail if you are on the server side, and your security
    is the minium of the security of all your POP/IMAP servers.
    
    AUTHOR STATUS AND FIX
    
    The fetchmail author helped a lot fixing the issue ASAP.
    This advisory was sent to bugtraq only after the fixed
    version of fetchmail (5.8.17) was available at
    http://www.tuxedo.org/~esr/fetchmail/
    
    EXPLOIT
    
    An example exploit is attached to this mail, it is poorly
    written but should be enough to prove the fetchmail vulnerability.
    You will probably need to joke with offsets to make it working
    on your system.
    
    NOTE
    
    I tried to follow this policy in the release of this advisory:
    http://www.wiretrip.net/rfp/policy.html
    
    regards,
    antirez
    
    -- 
    Salvatore Sanfilippo <antirezat_private>
    http://www.kyuzz.org/antirez
    finger antirezat_private for PGP key
    28 52 F5 4A 49 65 34 29 - 1D 1B F6 DA 24 C7 12 BF
    
    
    



    This archive was generated by hypermail 2b30 : Thu Aug 09 2001 - 17:20:33 PDT