Subject: TCP connection will hang in FIN_WAIT1 after closing if zero window is advertised

From: Andrey Dmitrov <[email-masked]>
Date: Mon, 15 Sep 2014 20:11:44 +0400

Greetings,

there is possible vulnerability in the TCP stack. Closing a socket after 
the TCP zero window advertising by peer leads to the socket stuck in 
FIN_WAIT1 state. FIN-ACK packet is not sent and not retransmitted. So 
the connection remains alive and without relation to any socket while 
the peer sends replies to the zero probe packets. It is possible to 
create a lot of connections in the same manner which will be in 
FIN_WAIT1 state forever.

Linux version 3.13-1-amd64 ([email-masked]) (gcc version 
4.8.2 (Debian 4.8.2-16) ) #1 SMP Debian 3.13.10-1 (2014-04-15)

I've written a script on Lua to reproduce this issue, find it in 
attachment please. I've used it with two hosts host_A (victim) and 
host_B (attacker), which are directly connected to each other. host_A 
has lighttpd installed and runned. Actually host_A can have any opened 
TCP listener socket to be attacked. If it closes any established with 
attacker connection it will stuck in the FIN_WAIT1 state. The script 
creates a number of TCP connections with the victim and sends replies 
for the zero window probe packets.

The test requires lua, tcpdump and nemesis on the host_B:
aptitude install lua5.1 lua5.1-posix nemesis tcpdump

How to run the test:
1. Run a httpd daemon on the host_A (I've used lighttpd).
2. Copy the test script attack.lua to the host_B.
3. Fill in the tested interfaces configuration (source, destination IP 
and MAC addresses) in the beginning of the file attack.lua. You can set 
maximum connections number in the variable *limit*, by default it is 500.
4. Set a fake MAC address for victim interface in host_B ARP table. It 
is to prevent host_B system replies (RST) receiving by the host_A:
     sudo arp -s <host_A IP addr> <any MAC address>
5. Run the test script on the host_B:
     sudo ./attack.lua

After ~10 minutes you will see 500 connections in the FIN_WAIT1 state on 
the host_A:
netstat | grep FIN_WAIT1 | wc -l
500

Even if you close the http daemon the connections still will be alive.

Thanks,
Andrey Dmitrov