OSEC

Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
Bugtraq archives for 1st quarter (Jan-Mar) 1998: Way to stop /tmp races

Way to stop /tmp races

Pavel Machek (pavelELF.UCW.CZ)
Sat, 21 Mar 1998 20:37:10 +0100

Hi!

Maybe I have a way to stop /tmp races, at expense of relatively small
semantic change. Trick is to modify open() to force O_EXCL if it is
under /tmp. Code follows, it is pretty short.

Share and enjoy,

                                                                Pavel
PS: Special question for solar designer:
  You have patch for similar purpose, but it was kernel patch. How did
you solve:

A: (victim)                     B: (attacker)
                                > /tmp/file
                                chmod 666 file
writes data to /tmp/file
closes /tmp/file
                                changes data in /tmp/file
reads back spoofed data

? [Sorry if it is stupid question.]

PPS: This is linux-specific, but at least like libc change it can be
done on any unix I know of.

/*
 * Ok, we'll close some of those nasty /tmp races.
 *
 * Copyright 1998 Pavel Machek <pavelucw.cz>,
 *                 distribute under General Public License, version 2
 *
 * To use: gcc safetmp.c -shared -o libsafetmp.so
 * then either export LD_PRELOAD=/full_path/libsafetmp.so
 * or if you are root and *DARING*
 *            echo "/full_path/libsafetmp.so" > /etc/ld.so.preload
 *
 * Version 0.0.1. Should work on Linux, should be possible to make it
 *                      work on other systems.
 */

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

int
open( const char *pathname, int flags, ... )
{
int ret;
const char *s;
mode_t mode = 0;
va_list ap;
va_start( ap, flags );

if (flags & O_CREAT)
  mode = va_arg( ap, mode_t );

s = pathname;
if (*s == '/') {
  while( *s == '/' )
    s++;
  if ((!strncmp( s, "tmp/", 4)) &&
      ((flags & (O_CREAT|O_TRUNC)) == (O_CREAT|O_TRUNC)) &&
      (!(flags & O_EXCL))) {
    syslog( LOG_INFO, "Insecure open: %d tries to open(%s,%d,%d)\n", getpid(), pathname, flags, mode );
    unlink( pathname );
    flags |= O_EXCL;
  }
}

return __open( pathname, flags, mode );

va_end( ap );
return ret;
}



--
I'm really pavelatrey.karlin.mff.cuni.cz.         Pavel
Look at http://atrey.karlin.mff.cuni.cz/~pavel/ ;-).