TCP Exploits

Prabhaker Mateti

Abstract: In these lectures, we go over the exploits that are possible on the Internet using design weaknesses of TCP rather than software errors. The lab experiments are Connection Killing by RST, Closing a Connection by FIN, The SYN Flooding, and Connection Hijacking.

Table of Contents

  1. Educational Objectives
  2. Design Weaknesses
    1. TCP Timers
    2. Connection Establishment and Termination
    3. The SYN Flood
    4. Simultaneous Connections
    5. SYN+FIN
    6. Covert Channels
  3. TCP Exploits
    1. Connection Killing by RST
    2. Closing a Connection by FIN
    3. Connection Hijacking
    4. Covert Channels
  4. Securing the TCP
  5. Lab Experiment
  6. Acknowledgements
  7. References

1. Educational Objectives

  1. Understand the role of sequence numbers in TCP.
  2. Understand several TCP exploits.
  3. Recognize design weaknesses of TCP.

TCP Exploits

There are security weaknesses at each layer of the network model and attackers have exploited every one of them. Security at the physical and data link layers is concerned with access to the physical transmission medium. This is accomplished with techniques similar to how you may protect your valuable jewelry.

The phrase TCP/IP typically refers to both TCP and UDP on top of IP. Faking a UDP packet is relatively simple. The header of a UDP packet is very simple due to its connectionless nature. So, it is not much more than IP address forgery (spoofing). Faking a TCP connection is much harder. In this article, we focus on TCP. For a discussion of weaknesses in IP, read [Mateti 2000, IP weaknesses].

TCP and IP were designed at a time when security concerns were almost non-existing and trust was assumed. This section summarizes design weaknesses in TCP from a security point of view. It is important to remember that many implementations have "fixed" these weaknesses, but are not described in RFCs. We assume that the reader is fluent in TCP and IP details (see the References).

TCP State Diagram and Timers

The diagram [from the web] enclosed here consists of three separate figures: (a) a TCP state diagram, (b) the three way and (c) four-way handshakes.

The TCP software layer constructs a finite state machine (FSM) at both ends for every (attempted) connection. An FSM consumes memory, and there are possibly thousands of FSMs, one each for a connection, at any given moment. Each connection logically starts in the Closed state, and makes transitions. After the connection is terminated, the TCP FSM returns to the Closed state again, and releases all resources allocated to this connection.

The FSM depends on many timers, coupled to certain states. We discuss a few timers below. TCP RFCs suggest values for some timers, leaving other timers open to individual implementations.

  1. Connection Establishment Timer is started when the SYN is sent during the initial connection setup. Typical value of this timer is 75 seconds. If a time-out occurs, the connection is aborted.
  2. FIN_WAIT timer is started when there is a transition from the FIN_WAIT_1 state to the FIN_WAIT_2 state. The initial value of this timer is 10 minutes. A TCP segment with a FIN bit set is expected in the FIN_WAIT_2 state. If a packet with a FIN bit set is received, the timer is cancelled. On expiration of the 10 minutes, the timer is restarted with a value of 75 seconds. The connection is dropped if no FIN packet arrives within this period.
  3. TIMED_WAIT timer is started when the connection enters the TIMED-WAIT state. This is to allow all the segments in transit to be removed from the network. The value of the timer is usually set to 2 minutes. On expiration of the timer, the connection is terminated.
  4. KEEP_ALIVE timer. TCP usually does not send anything over the connection if there is no data to send. There is no way of distinguishing this silence from the case when the connection is broken. Setting a keep-alive timer allows TCP to periodically check whether the other end of the connection is still active. The default value of this timer is 2 hours. After the expiration of the timer, probes are sent to the remote end. The connection is dropped if the remote does not respond to the probes.
  5. A Retransmission Timer, whose value is dynamically computed, is started when a segment is sent. If the timer expires goes off before an ACK is received, the segment is resent, and timer is restarted.
  6. A Persistence Timer is used to detect if any window size updates were lost.

An example of a state without an associated timer is the CLOSE_WAIT state. With a default value of the keep-alive timer of 2 hours, the state-machine can be frozen for that long.

Connection Establishment and Termination

TCP exploits are typically based on (i) IP spoofing and (ii) sequence number prediction. In establishing a TCP connection, both the server and the client generate an initial sequence number from which they will start counting the bytes transmitted. This sequence number is (should be) generated at random, and should be hard to predict. However, some implementations of the TCP/IP protocol make it rather easy to predict this sequence number. The attacker either sniffs the current SEQ/ACK of the connection, or can algorithmically predict them. For more on this, read [CERT CA-2001-09].

The TCP protocol uses a 3-way handshake between the two parties to start a connection. The client starts the process by sending a SYN packet to synchronize communication. The server host then sends one of two answers, using the its initial sequence number, back to the client: (i) a RST packet resets the connection, thus refusing the request for service, (ii) while an ACK packet acknowledges the request and awaits the client's first packet.

A connection is typically ended as follows. The TCP flag FIN indicates "no more data from sender". This flag is used when closing a connection down the normal way. The receiving host enters the CLOSE­WAIT state and starts the process of gracefully closing the connection. Each end of the connection sends a packet with the FIN flag. The receiver is expected to acknowledge a received FIN packet by sending a FIN packet. So four packets are used to close a TCP connection.

Closing a connection can also be done by using the RST flag. The RST flag of a TCP packet of a sender indicates to the receiver that a reset should occur. The receiving host enters the CLOSED state and frees resources associated with this instance of the connection. The RST packet is not acknowledged. Any new incoming packets for that connection will be dropped. The receiver accepts the RST packet provided the sequence number is correct.

The SYN Flood

When the TCP protocol was initially released, there was no limit set on the wait after receiving the SYN. Once a TCP session begins (i.e., after the ACK packet comes in) each TCP packet has a timeout. If a packet takes too long, it times out, and eventually, the connection itself will time out, but because of the way the state transition diagrams were specified so many years ago, in this particular state of opening the connection, there are no timeouts.

SYN flooding takes advantage of a flaw in how most hosts implement the three-way handshake. When a host YY receives the SYN request from XX, it must keep track of the partially opened connection in a "listen queue" for several (e.g., 75) seconds. This is to allow for successful connections even with long network delays. On the other hand, implementations can only keep track of a limited number of connections. An attacker may initiate many connection requests with spoofed source addresses to the victim machine. That causes victim machine to allocate resources to handle these requests. The SYN+ACK packet replies of the victim host are ignored by the attacker. Once a set limit of such half-open connections is reached, the victim host will refuse all successive connection establishment attempts regardless of whether they are originating from genuinely addressed hosts, until a partially opened connection in the queue is completed or times out. This ability to effectively remove a host from the network for at least 75 seconds can be used solely as a denial-of-service attack, or it can be used as a tool to implement other attacks. Note that neither outgoing connection attempts nor connections that are already established are affected by this attack.

Suppose ZZ initiates a connection to YY but spoofs as though the packet is from XX. This is the first packet (SYN connection init) of the three-way TCP handshake. YY replies with the second packet of the handshake, and will now wait for response from host XX. If the spoofer sends a packet to the server, the server will send an acknowledgement back to the "real" client. If host XX is reachable, there is no easy way for ZZ to prevent the packet from reaching XX. This real client does not know what to do with this ACK. XX will tell host YY (with a RST) that it did not initiate a connection. YY concludes it received a bogus packet, and will ignore the SYN, and normally nothing more will happen with XX. Remember that YY is wholly unaware of ZZ. So, the spoofer may try to flood the real client XX with dummy packets at such a rate that its buffers will overflow, and the ACK from the server YY will be lost.

But suppose host XX is turned off, ZZ some how observed this, and chose to impersonate XX. Or that the spoofed source IP address that ZZ used looks legitimate but is not assigned to any real host. So if XX is unreachable, YY has a rather long wait for the third packet of the handshake.

Also there is no explicit specification in TCP for the number of simultaneous channels permitted on a given port. The vast majority of systems in the Internet allow upto 1024 simultaneous sessions. Suppose an attacker sends 1024 packets to such a computer at port 80, say, with the SYN bit set, and spoofing the source address so that each packet has a different source host number. After receving these 1024 packets, the target system will stop listening to that port. Note that such a packet is only about 40 bytes long, so the total amount of traffic is only 40,960 bytes, taking a few seconds on a modem, or about 1/20 of a second on T1. That is, one second's worth of packets results in a system hang. Many systems probably run out of internal space to store the uncompleted connections before the second passes and crash.

This TCP design bug cannot be fixed at the router or using some add-on product. The only real fix is to modify operating systems so that it times out on incomplete TCP sessions.

Simultaneous Connections

Occasionally, it is possible that hosts XX and YY both wish to establish a connection and both of them simultaneously initiate the handshake. This is called simultaneous connection establishment. Both hosts XX and YY send out SYN's to each other. When the SYN's are received, each receiver sends out a SYN+ACK. Both hosts XX and YY must detect that the SYN and SYN+ACK actually refer to the same connection. If both hosts XX and YY detect that the SYN+ACK belongs to the SYN that was recently sent, they switch off the connection establishment timer and move directly to the SYN_RECVD state. This flaw could be used to stall a port on a host, using protocols such as FTP where the server initiates a connection to the client.

As an example, consider (malicious) host XX which has started an (active) FTP connection to a server YY. XX and YY are connected using the control-port 21 on YY. YY initiates the connection establishment procedure to initiate data transfer with XX.

  1. YY sends a SYN to XX, and makes a transition to SYN_SENT state. YY also starts the connection establishment timer.
  2. XX receives the SYN, and responds with another SYN.
  3. When YY receives the SYN, it assumes that this is a case of a simultaneous open connection. So, it sends out SYN_ACK to XX, switches off the connection establishment timer, and transitions to the state SYN_RCVD.
  4. XX receives the SYN_ACK from YY, but does not send a reply.
  5. Since YY is expecting a SYN_ACK in the SYN_RCVD state, and there is no timer, YY gets stalled in SYN_RCVD state.

XX was able to create a denial-of-service attack.


The TCP specification does not specify clearly certain transitions. As an example, suppose an attacker sends a TCP segment with both the SYN and the FIN bit set. Depending on the TCP implementation, victim host processes the SYN flag first, generates a reply packet with the corresponding ACK flag set, and perform a state-transition to the state SYN_RCVD. Victim host then processes the FIN flag, performs a transition to the state CLOSE_WAIT, and sends the ACK packet back to attacker. The attacking host does not send any other packet to victim. TCP state machine in the victim for this connection is in CLOSE_WAIT state. The victim connection gets stuck in this state until the expiry of the keep-alive timer.

Covert Channels

In TCP/IP, there are a number of methods through which data can be surreptitiously passed between hosts. That is, the "real data payload" is not located in the data field (following the first 24 bytes of the TCP header).

A number of fields in the TCP/IP header are unused or optional, and these can be used for covert data transmission. However, it is likely that various filters along the way strip or modify this data. So, for reliable covert operation an attacker uses the mandatory fields: The IP packet identification field, SYN, and ACK. The basis of the exploitation relies in encoding ASCII values of the range 0-255 into these areas. Using this method it is possible to pass data between hosts in packets that appear to be initial connection requests, established data streams, or other intermediate steps. These packets either contain no actual data, or contain data designed to look innocent. Typically they can also contain forged source and destination IP addresses as well as forged source and destination ports. This can be useful for tunneling information past some types of packet filters. Additionally, forged packets can be used to initiate an anonymous TCP/IP "bounced packet network" whereby packets between systems can be relayed off legitimate sites to thwart tracking by sniffers and other network monitoring devices. These techniques will be described below.

Manipulation of the IP Identification Field

IP packets can get fragmented along the route from the source to the destination because of different MTRs of different segments. All fragments that originally belonged to an IP packet are given the same IP id field number so that all the fragments can be identified and assembled back into a whole packet. As long as this purpose is served, the specific choice made for the value does not matter.

*The first encoding method simply replaces the IP identification field with the numerical ASCII representation of the character to be encoded. This allows for easy transmission to a remote host which simply reads the IP identification field and translates the encoded ASCII value to its printable counterpart. The lines below show a tcpdump(8) representation of the packets on a network between two hosts "" and "" A coded message consisting of the letters "HELLO" was sent between the two hosts in packets appearing to be destined for the WWW server on The actual packet data does not matter.

The field in question is the IP portion of the packet called the "id" field located in the parenthesis. Note that the ID field is represented by an unsigned integer during the packet generation process of the included program. This program does not perform any type of byte ordering functions normally used in this process, therefore packet data is converted to the ASCII equivalent by dividing by 256.

Packet One:

18:50:13.551117 > S 537657344:537657344(0) win 512 (ttl 64, id 18432)

Decoding:...(ttl 64, id 18432/256) [ASCII: 72(H)]

Packet Two:

18:50:14.551117 > S1393295360:1393295360(0) win 512 (ttl 64, id 17664)

Decoding:...(ttl 64, id 17664/256) [ASCII: 69(E)]

Packet Three:

18:50:15.551117 > S 3994419200:3994419200(0) win 512 (ttl 64, id 19456)

Decoding:...(ttl 64, id 19456/256) [ASCII: 76(L)]

Packet Four:

18:50:16.551117 > S3676635136:3676635136(0) win 512 (ttl 64, id 19456)

Decoding:...(ttl 64, id 19456/256) [ASCII: 76(L)]

Packet Five:

18:50:17.551117 > S 774242304:774242304(0) win 512 (ttl 64, id 20224)

Decoding:...(ttl 64, id 20224/256) [ASCII: 79(O)]

Packet Six:

18:50:18.551117 > S3843751936:3843751936(0) win 512 (ttl 64, id 2560)

Decoding:...(ttl 64, id 2560/256) [ASCII: 10(Carriage Return)]

This method is used by having the client host construct a packet with the appropriate destination host and source host information and encoded IP ID field. This packet is sent to the remote host which is listening on a passive socket which decodes the data.

This method is relatively straightforward and easy to implement as shown in the included program: covert_tcp. The reader should note that this method relies on manipulation of the IP header information, and may be more susceptible to packet filtering and network address translation where the header information may re-written in transit especially if located behind a firewall. If this happens, loss of the encoded data may occur.

Sequence Number Field

The sequence number field is a 32-bit number, bytes 4-7, of the TCP header. One can generate the initial sequence number from the characters we wish to covertly send.

This is the method used by covert_tcp as shown in the following packets (The "S" indicates a synchronize packet with the 10 digit number following being the sequence number being sent). Again, no byte ordering functions are used by covert_tcp to generate the sequence numbers. This enables a more "realistic" looking sequence number. Therefore in our example the sequence numbers are converted to ASCII by dividing by 16777216 which is a representation of 65536*256.

Again our message of HELLO is being sent:

Packet One:

18:50:29.071117 > S 1207959552:1207959552(0) win 512 (ttl 64, id 49408)

Decoding:... S 1207959552/16777216 [ASCII: 72(H)]

Packet Two:

18:50:30.071117 > S 1157627904:1157627904(0) win 512 (ttl 64, id 47616)

Decoding:... S 1157627904/16777216 [ASCII: 69(E)]

Packet Three:

18:50:31.071117 > S 1275068416:1275068416(0) win 512 (ttl 64, id 41984)

Decoding:... S 1275068416/16777216 [ASCII: 76(L)]

Packet Four:

18:50:32.071117 > S 1275068416:1275068416(0) win 512 (ttl 64, id 7936)

Decoding:... S 1275068416/16777216 [ASCII: 76(L)]

Packet Five:

18:50:33.071117 > S 1325400064:1325400064(0) win 512 (ttl 64, id 3072)

Decoding:... S 1325400064/16777216 [ASCII: 79(O)]

Packet Six:

18:50:34.071117 > S 167772160:167772160(0) win 512 (ttl 64, id 54528)

Decoding:... S 167772160/16777216 [ASCII: 10(Carriage Return)]

Because of the sheer amount of information one can represent in a 32 bit address space (4,294,967,296 numbers), the sequence number makes an ideal location for storing data. Aside from the obvious example given above, one can use a number of other techniques to store information in either a byte fashion, or as bits of information represented through careful manipulation of the sequence number. The simple algorithm of the covert_tcp program takes the ASCII value of our data and converts it to a usable sequence number (which is actually done by the packet generation functions and is converted back to ASCII in a symmetrical manner). Note that this method (as well as the other methods in this paper) are similar to a "substitution cipher" whereby packets containing the same information will display the same sequence number (note packets three and four which contain the letter "L" in the encoding and their sequence numbers). Methods that incorporate a random number generation of the sequence number with a subsequent inclusion of the data to be encoded through an XOR or similar operation may yield a more random result. Inclusion of encrypted data to perform the same function is a logical extension to this idea.

The TCP Acknowledge Sequence Number Field "Bounce"

This method relies upon basic spoofing of IP addresses to enable a sending machine to "bounce" a packet of information off of a remote site and have that site return the packet to the real destination address. This has the benefit of concealing the sender of the packet as it appears to come from the "bounce" host. This method could be used to set up an anonymous one-way communication network that would be difficult to detect especially if the bounce server is very busy.

This method relies on the characteristic of TCP/IP where the destination server responds to an initial connect request (SYN packet) with a SYN/ACK packet containing the original initial sequence number plus one (ISN+1). In this method, the sender constructs a packet that contains the following information:

- Forged SOURCE IP address.
- Forged SOURCE port.
- Forged DESTINATION IP address.
- Forged DESTINATION port.
- TCP SYN number with encoded data.

The source and destination ports chosen do not matter (except if you want to conceal the traffic as a well known service such as HTTP and/or you are having the receiving server listening for data on a pre-determined port, in which case you will want to forge the source port as well). The DESTINATION IP address should be the server you wish to BOUNCE information off of and the SOURCE IP should be the address of the server you wish to communicate WITH.

The packet is sent from the client's computer system and routed to the forged destination IP address in the header ("bounce server"). The bounce server receives the packet and sends either a SYN/ACK or a SYN/RST depending on the state of the port the packet was destined for on the bounce server. The return packet is sent to the forged source address with the ISN number plus one. The listening destination server takes this incoming packet and decodes the information by transforming the returned sequence number minus one back into the ASCII equivalent. It should be noted that the low order bits are dropped in the translation process of covert_tcp because of the method used to "encode" and "decode" information, so the program does not need to adjust for the incremented SYN packet number.

A step-by-step representation of the bounce method:

- Sending Client: A
- Bounce Server: B
- Receiving Server: C

Step One: Client A sends a forged packet with encoded information to bounce server B. This packet has the address of receiving server C.

Step Two: Bounce server B receives the packet and returns an appropriate SYN/ACK or SYN/RST packet based on the status of the port. Since bounce server B thinks the packet came from receiving server C, the packet is sent to address of receiving server C. The acknowledgment sequence number (which is the encoded sequence number plus one) is sent to server C as well.

Step Three: Server C, expecting to receive a packet from the bounce server B (or a pre-determined port) decodes the data and writes it out to disk.

This method is essentially tricking the remote server into sending the packet and encapsulated data back to the forged source IP address, which it rightfully thinks is legitimate. From the receiving end, the packet appears to originate from the bounced server, and indeed it does. As a side note, if the receiving system is behind a packet filter that only allows communication to certain sites, this method can be used to bounce packets off of the trusted sites which will then relay them to the system behind the packet filter with a legitimate source address. This could be vital in communicating with receiving servers in heavily protected or scrutinized networks.

Bouncing a packet off of a well known Internet site (.mil, .gov, .com, etc.) is also a useful technique for concealing operations in ordinary traffic. Be sure the bounce site is not using round-robin DNS (stable IP address) or if it is, that the receiving server is passively listening on a pre-determined port to decode the transmissions from multiple sites (i.e. send out a forged source address and source port of 1234 so the bounce server returns the packet to the listening server on port 1234). Using this technique, the sending client can bounce packets off of hundreds of Internet hosts while the receiving server listens and writes out any data destined for the pre-defined port number regardless of IP address.

If your network site has a correctly configured router, it may not allow a forged packet with a network number that is not from it's network to traverse outbound. Alas, many routers are not configured with this protection in mind and will happily pass the data so you can generally expect this technique to work.

Covert Channels

The covert_tcp program is a simple proof of concept utility written (by Craig H. Rowland). It uses raw sockets to construct forged packets and encapsulate data from a filename given on the command line. The program itself is straightforward and very slow in transmitting of data (about one packet per second). Because covert_tcp is subjugating the TCP/IP protocol for a purpose not designed, the normal reliability modes are non- existent and in essence functions much like UDP. This program does not attempt to provide for any type of flow control or error detection, although these things can be added.

Covert channels could be incorporated into an operating system kernel, or daemon that is set to receive the name of a file and send it.

TCP Exploits

This section describes a few exploits while they are in progress. The source code of these exploits is downloadable (see the References).

Below, we show the relevant contents of packets sniffed from an attack in progress. XX, YY and ZZ are IP addresses, whose actual byte values are irrelevant here. Assume that the "sniper program" S (on host ZZ) is on the same subnet as XX. YY need not be on the same subnet. The data portion of the packets is often irrelevant, so it is not shown. The SEQ and ACK numbers are in hex. These were obtained by running a sniffer while the attack was in progress.

Connection Killing by RST

The attacker (on host ZZ) is sniffing packets in a connection between XX and YY. He (i.e., his sniper program) will calculate, from YY's ACK packets to XX, the sequence number for XX's packets, and fire off a bogus RST packet from ZZ (faking to be XX) to YY.

Here is an actual attack. XX on port 1810 and YY on port 23 are connected for a while.

  1. Attacker S waits for a packet to get current SEQ/ACK. Several packets, as seen by S, are shown below. S is ready to send his RST after the very first.

    XX.1810-YY.23 SEQ: 57E1F2A6 ACK: B8BD7679 FLAGS: -AP--- Window: 3400
    YY.23-XX.1810 SEQ: B8BD7679 ACK: 57E1F2A8 FLAGS: -AP--- Window: 2238
    XX.1810-YY.23 SEQ: 57E1F2A8 ACK: B8BD767B FLAGS: -A---- Window: 3400
    YY.23-XX.1810 SEQ: B8BD767B ACK: 57E1F2A8 FLAGS: -AP--- Window: 2238
    XX.1810-YY.23 SEQ: 57E1F2A8 ACK: B8BD7691 FLAGS: -A---- Window: 3400

  2. The attacker sends off to YY.23 his RST packets, with source forged as XX.1810. His program sent two RST packets. One after the ACK of B8BD7679. The reply from YY was:

    YY.23-XX.1810 SEQ: B8BD7679 FLAGS: ---R--

    But this packet arrived at XX much later, in this particular attack, at that particular time because of LAN load or whatever. Connection is still on. So off goes another RST from the sniper after B8BD7691. The reply from YY was:

    YY.23-XX.1810 SEQ: B8BD7691 FLAGS: ---R--

    The second RST from the sniper was the packet that killed the connection. The first reset packet has been buffered somewhere on our system, because the Ethernet segment was busy when we wanted to send it. This is the 'unexpected thing' that happens some times. Here the data stream slowed down. When it doesn't cool down so fast, the attacker could miss his RST (or the connection will be killed a little later than when he wanted).

Closing a Connection by FIN

The attacker constructs a spoofed FIN packet. It will have the correct SEQ number so that it is accepted by the host. This host would believe the (spoofed) sender did not have any data left. Any packets that may follow would be ignored as bogus. Here is an actual attack

  1. Connection between XX:23 and YY:1072 is running.

    XX.23-YY.1072 SEQ: 19C6B98B ACK : 69C5473E FLAGS: -AP--- Window: 3400

    plus 2 data bytes

  2. Sniper detected it, and will send a bogus packet (ZZ as YY to XX).

    YY.1072-XX.23 SEQ: 69C5473E ACK: 19C6B98D FLAGS: -A---F Window: 7C00

    Sniper sets the SEQ as ACK of above packet. Sniper calculates his ACK as: SEQ of above packet + data length of that packet = 19C6B98B + 2 = 19C6B98D.
  3. Host XX to YY: "Okay, you ended the session, so here is my last data."

    XX.23-YY.1072 SEQ: 19C6B98D ACK: 69C5473E FLAGS: -AP--- Window: 3400
    XX.23-YY.1072 SEQ: 19C6B998 ACK: 69C5473F FLAGS: -A---- Window: 3400
    XX.23-YY.1072 SEQ: 19C6B998 ACK: 69C5473F FLAGS: -A---F Window: 3400

  4. Host XX now has flushed its buffer and sent his FIN for the connection. Sniper sniffs this packet and now knows the host XX fell for the spoof and the killing was a success!
  5. We impersonated YY, making XX believe we had no further data. But the real YY doesn't know that and continues to send packets.

    YY.1072-XX.23 SEQ: 69C5473E ACK: 19C6B98D FLAGS: -A---- Window: 3750

    Host XX has that connection closed by now, and thus thinks the (real) packets of (real) YY are spoofed (or at least bogus)! So host XX sends some RST packets.

    XX.23-YY.1072 SEQ: 19C6B98D FLAGS: ---R--

  6. This goes on for a couple of packets.

Connection Hijacking

YY trusts the packets from XX because of its correct SEQ/ACK numbers. So if there was a way to mess up XX's SEQ/ACK, YY would ignore XX's real packets. Attacker could then impersonate to be XX, but using correct SEQ/ACK numbers from the perspective of YY. The attacker can confuse XX's SEQ/ACK numbers as seen by YY by simply inserting a data packet into the stream at the right moment (ZZ as XX->YY). YY would accept this data, and update ACK numbers. XX would continue to send it's old SEQ numbers, as it's unaware of our spoofed data. This results in ZZ hijacking the connection: host XX is confused, YY thinks nothing is wrong as ZZ sends 'correct' packets to YY. Each time a packet arrives at YY out of sequence from the real XX, the YY answers it with 'correct' SEQ/ACK.

Here is an actual attack. Not all packets that transpire after step 1 are shown.

  1. Attacker examines with a sniffer, and sees the port number 1040, and also that the user is in an interactive shell via telnet to YY. He starts hijack (the programs name) on host ZZ as

    hijack XX 1040 YY

    The following packet from XX->YY is detected. The data portion of the packets is relevant, so it is shown.

    XX.1040-YY.23 SEQ: 5C8223EA ACK: C34A67F6 FLAGS: -AP--- Window: 7C00 XX.1040-YY.23 45 E 00 . 00 . 29 ) CA . F3 . 40 @ 00 . 40 @ 06 . C5 . 0E . 9D . C1 . 45 E 3F ? 9D . C1 . 2A * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # EA . C3 . 4A J 67 g F6 . 50 P 18 . 7C | 00 . 6D m 29 ) 00 . 00 . 6C l

  2. Server YY echoes that data byte (happens to be a 'l')

    YY.23-XX.1040 SEQ: C34A67F6 ACK: 5C8223EB FLAGS: -AP--- Window: 2238 YY.23-XX.1040; 45 E 00 . 00 . 29 ) B5 . BD . 40 @ 00 . FC . 06 . 1E . 44 D 9D . C1 . 2A * 0B .; 9D . C1 . 45 E 3F ? 00 . 17 . 04 . 10 . C3 . 4A J 67 g F6 . 5C \ 82 . 23 # EB .; 50 P 18 . 22 " 38 8 C6 . F0 . 00 . 00 . 6C l

  3. XX ACKnowledges that:

    XX.1040-YY.23 SEQ: 5C8223EB ACK: C34A67F7 FLAGS: -A---- Window: 7C00
    (data is irrelevant)
  4. Now the hijack program on ZZ address-spoofs XX with further data to YY. The hijacker sends some Backspace (0x08) characters and two Enter (0x0A) characters to clean up the command line of the user. This may generate some error messages back from the shell. But hijack program should handle that too.

    XX.1040-YY.23 SEQ: 5C8223EB ACK: C34A67F6 FLAGS: -AP--- Window: 7C00 XX.1040-YY.23 45 E 00 . 00 . 32 2 31 1 01 . 00 . 00 . 45 E 06 . 99 . F8 . 9D . C1 . 45 E 3F ? 9D . C1 . 2A * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # EB . C3 . 4A J 67 g F6 . 50 P 18 . 7C | 00 . AE . F5 . 00 . 00 . 08 . 08 . 08 . 08 . 08 . 08 . 08 . 08 . 0A . 0A .

  5. The following is the echo of the spoofed data from the server YY.

    YY.23-XX.1040 SEQ: C34A67F7 ACK: 5C8223F5 FLAGS: -AP--- Window: 2238 YY.23-XX.1040 45 E 00 . 00 . 3C < B5 . BE . 40 @ 00 . FC . 06 . 1E . 30 0 9D . C1 . 2A * 0B . 9D . C1 . 45 E 3F ? 00 . 17 . 04 . 10 . C3 . 4A J 67 g F7 . 5C \ 82 . 23 # F5 . 50 P 18 . 22 " 38 8 26 & 7C | 00 . 00 . 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 5E ^ 48 H 0D . 0A . 0D . 0A .

    Note that ACK = 5C8223F5 = 5C8223EB + 0A. This is how the hijacker detects success. At this point the connection is controlled by the hijacker, and the real XX's SEQ/ACK numbers are out of sync with YY. At this point the real telnet client's session on XX hangs. Most people ignore this as a network problem and re-login after a while, accepting the disconnection as Murphy's law. Indeed, connection hangs do happen without any spoofing involved because of other reasons.

  6. TCP rules require that each time a packet arrives at a host out of sequence, the host should answer it with correct SEQ/ACK. The real XX send a packet to YY, and YY responds as follows.

    XX.1040-YY.23 SEQ: 5C8223EB ACK: C34A67F7 FLAGS: -AP--- Window: 7C00
    YY.23-XX.1040 SEQ: C34A680B ACK: 5C8223F5 FLAGS: -A---- Window: 2238

  7. Hijack will now send the strings of text it wants to be executed. The hijacker boasts with a shell command. 'echo "echo HACKED" >> $HOME/.profile'

    XX.1040-YY.23 SEQ: 5C8223F5 ACK: C34A680B FLAGS: -AP--- Window: 7C00 XX-YY.23 45 E 00 . 00 . 4D M 31 1 01 . 00 . 00 . 45 E 06 . 99 . DD . 9D . C1 . 45 E 3F ? 9D . C1 . 2A * 0B . 04 . 10 . 00 . 17 . 5C \ 82 . 23 # F5 . C3 . 4A J 68 h 0B . 50 P 18 . 7C | 00 . 5A Z B6 . 00 . 00 . 65 e 63 c 68 h 6F o 20 22 " 65 e 63 c 68 h 6F o 20 48 H 41 A 43 C 4B K 45 E 44 D 22 " 20 3E > 3E > 24 $ 48 H 4F O 4D M 45 E 2F / 2E . 70 p 72 r 6F o 66 f 69 i 6C l 65 e 0A . 00 .

  8. Now hijacker waits for this data to be confirmed. ACK = 5C8223F5 + 0x25 = 5C82241A.

    YY.23-XX.1040 SEQ : C34A680B ACK: 5C82241A FLAGS: -AP--- Window: 2238 YY.23-XX.1040 ... data ...
  9. The connection between ZZ and YY continues. The hijacker can execute more commands. The hijack program stays on track of SEQ/ACK, and eventually FINishes the connection.

Example Tools

Juggernaut ( issue 50) is a network sniffer that can also be used to hijack TCP sessions. Juggernaut can be configured to wait for the login prompt, and then record the network traffic that follows (usually capturing the password). It can maintain a connection database of all the TCP connections made, and possibly "hijack" the session. After a connection is made, the attacker can watch the entire live session. As the session is watched, the attacker can reset, or hijack the connection.

Hunt (search  ) is a program for intruding into a TCP connection, watching it and resetting it. It can detect an ongoing connection (not only when SYN started), hijack, detect an ACK storm, ARP spoof, and synchronize the true client with the server after hijacking.

Secure TCP

Better Sequence Numbers

[The following is based on RFC 1948.] The choice of initial sequence numbers for a connection should not be random. Rather, it must be chosen so as to minimize the probability of old stale packets being accepted by new incarnations of the same connection. Furthermore, most implementations of TCP contain special code to deal with such reincarnations when the server end of the original connection is still in TIME-WAIT state. Accordingly, simple randomization will not work well. But duplicate packets, and hence the restrictions on the initial sequence number for reincarnations, are peculiar to individual connections. That is, there is no relationship, syntactic or semantic, between the sequence numbers used for two different connections.

We can prevent sequence number guessing attacks by giving each connection -- that is, each 4-tuple of <local host, local port, remote host, remote port> -- a separate sequence number space. Within each space, the initial sequence number is incremented as usual; however, there is no obvious relationship between the numbering in different spaces.

The obvious way to do this is to maintain state for dead connections, and the easiest way to do that is to change the TCP state transition diagram so that both ends of all connections go to TIME-WAIT state. That would work, but it is inelegant and consumes storage space. Instead, we use the current four-microsecond timer M and set

ISN = M + F(local host, local port, remote host, remote port).

It is vital that F not be computable from the outside, or an attacker could still guess at sequence numbers from the initial sequence number used for some other connection. We therefore suggest that F be a cryptographic hash function of the connection-id and some secret data. MD5 [9] is a good choice, since the code is widely available. The secret data can either be a true random number [10], or it can be the combination of some per-host secret and the boot time of the machine. The boot time is included to ensure that the secret is changed on occasion. Other data, such as the host's IP address and name, may be included in the hash as well; this eases administration by permitting a network of workstations to share the same secret data while still giving them separate sequence number spaces. Our recommendation, in fact, is to use all three of these items: as random a number as the hardware can generate, an administratively- installed pass phrase, and the machine's IP address. This allows for local choice on how secure the secret is. Note that the secret cannot easily be changed on a live machine. Doing so would change the initial sequence numbers used for reincarnated connections; to maintain safety, either dead connection state must be kept or a quiet time observed for two maximum segment lifetimes after such a change.

4.2 IPv6

The IP that is widely in use currently is IPv4 even though IPsec and IPv6 implementations are available for all popular OS. IPv6 improves the security of IP substantially compared to IPv4. However, there are no such widely agreed upon extensions for TCP. There exist only experimental suggestions from researchers.

The Secure-TCP protocol was proposed in 1995 as an extension to the current TCP. It provides secure service negotiation, the key exchange for encryption and TCP segment encryption.

Lab Experiment

All work should be carried out in Operating Systems and Internet Security (OSIS) Lab, 429 Russ. Use any of the PCs numbered 19 to 30. No other WSU facilities are allowed.

Objective: Run the TCP exploit programs (sniper-fin, sniper-rst, and hijack) based on the above with a goal of learning how the attack actually works in detail. Observe the details of the packets being transmitted using a sniffer. Capture sequences of packets to and fro and explain how the specific attack worked. Examine the source code of sniper-fin, sniper-rst, and hijackprograms both because you need to learn to invoke them, and because a later assignment may/ will use the source code.

  1. Download ipspoof.tgz. Build the three programs sniper-fin, sniper-rst, and hijack using the Makefile.
  2. Setup a network of four PCs, P0, P1, P2, P3 with P1 and P2 as a routers under BackTrack. Boot P0 into Windows, P3 into Knoppix. Install putty on Windows P0. Enable telnet service on P3. (See below.)
  3. You will be running a sniffer, and sniper-fin, sniper-rst, and hijack programs on P1. Use any sniffer you like. Verify that the sniffer is running properly.
  4. [telnet-kill] Telnet from P0 to P3. Invoke sniper-fin on P1 to kill this connection. Observe and copy-and-paste into a text file the sniffer output as the connection gets killed. Add your annotations and observations to this text file.
  5. Do step [telnet-kill] but with sniper-rst on P2.
  6. Do step [telnet-kill] but with hijack on P1. Append the line of "evil data" to the text file journal you are keeping.
  7. Edit the journal file, and wrap it with other parts of your writing so that it is a lab report.

Link to Grading Sheet

Enable Telnet Service

Recent distributions of Linux are not installing the telnet service by default. Rather than trying to install the binary packages that will have specific library dependencies, it is better to to compile and install telnetd, et al. The following is a link to a local copy of the source that Debian (and its derivatives Ubuntu, Knoppix and BackTrack) uses: inetutils_1.8.orig.tar.gz. Build it as usual; that is: untar, configure, and make. This tar ball provides telnet ifconfig ping telnetd ftp libinetutils/ talk whois ftpd talkd.

6. Acknowledgements

Most of the material in this lecture is based on articles by Brecht Claerhout and Craig H. Rowland.

This work was supported in part by NSF DUE-9951380.


  1. CERT, Advisory CA-2001-09 Statistical Weaknesses in TCP/IP Initial Sequence Numbers, Recommended Reading.
  2. Brecht Claerhout, A short overview of IP spoofing: Parts I and II, 1996. The papers are found in many web archives, but do not seem to be published in any formal way. ipspoof.tgz is a collection of files from these papers. Even though the title says IP spoofing, these are all about TCP exploits based on IP spoofing. Highly Recommended Reading.
  3. Wesley M. Eddy, "Defenses Against TCP SYN Flooding Attacks", The Internet Protocol Journal,, Volume 9, Number 4, 2006. Highly Recommended Reading.
  4. Prabhaker Mateti, IP Spoofing, Fragmentation and Smurfing, June 2000. A lecture from a course on Internet Security. InternetSecurity/ Lectures/ IPexploits. Required Reading.
  5. Prabhaker Mateti, TCP/IP Refresher, 2012. A lecture from a course on Internet Security. InternetSecurity/ Lectures/ TCPIP/. Required Reading.
  6. Prabhaker Mateti, "Security Issues in the TCP/IP Suite", in "Security in Distributed and Networking Systems", ISBN-10: 9812708073, 28 pp., 2007 sec-tcpip.pdf.  Required Reading.
  7. Craig H. Rowland, Covert Channels in the TCP/IP Protocol Suite, First Monday, vol 2, no. 5 Recommended Reading.
  8. Mike Schiffman, The Libnet Packet Construction Library,, mirrored 2007. Libnet is a high-level API (toolkit) allowing the application programmer to construct and inject network packets. Become familiar with it.
  9. TCP Shrew Attacks, Shrews: Low-Rate TCP-Targeted Denial of Service Attacks,, 2004. Recommended Visit.

Copyright © 2012