It's ironic that I'm writing about fitting in since I never have in my entire life. And while I've been a social misfit, I'm now talking about misfit crafted packets – specifically TCP. This pertains to packets that you craft and that you may observe entering a network near and dear to you. There are certain basic characteristics or behaviors that are expected of well-formed TCP packets. And, that is what this blog is about.
First things first – let's say you want to craft a well-formed SYN packet. The best model for emulation is the SYN of the operating system that you're attempting to emulate – the range of source ports it tends to use, the TCP window size, the IP TTL, IP identification number, IP flags, etc. as well as a randomized 32-bit sequence number.
Those fields and value are pretty obvious and well covered in literature so I won't bother to discuss them, but some crafters I've seen forget about the TCP options. Every packet with the SYN flag set – either a SYN or SYN/ACK packet – should have the Maximum Segment Size set. Sure, it's possible to craft a SYN or SYN/ACK without the MSS option and have the receiver accept it, but it stands out to the trained eye or astute filters looking at the session or traffic in aggregate. If you want to remain stealthy, you'll include the MSS option. There needs to be a value associated with it and that is typically 1460 for an Ethernet network.
If you ever see a packet flying by on your network that has a SYN flag set and does not have a TCP options Maximum Segment Size (MSS) – you can be fairly certain that it was crafted. And, if it was crafted – it probably is for some nefarious purposes. There are other TCP options too that can be included, but most current well-known TCP/IP stacks list the MSS as the first of the TCP options in the TCP header. However, Solaris stacks do not follow this convention and may present some false positives if you include this check.
How would you find SYN packets with no MSS flag? It's not that easy using some of the common tools. Snort cannot discover this with its rule language since it doesn't permit you to examine the TCP header options and the "offset" keyword pertains to the payload portion of the packet – not the TCP header. Tcpdump is not much help unless you assume that the MSS option must be the first. It has a value of 0x02 and it must be found in the 20th byte offset of the TCP header of any SYN segment. The tcpdump filter to discover such a segment would be:
tcp[13] & 2 != 0 and ((tcp[12]/16 == 5) or (tcp[12]/16 > 5 and tcp[20] != 02))
· 'tcp[13] & 2 !=0' looks for the SYN flag set
· 'tcp[12]/16 ==5' looks for a TCP header length of 5. This is fairly convoluted because the value for the TCP header length is found in the high-order nibble so we must first divide by 16 to make it more logical (at least for me). Now, a TCP header length of 5 (32-bit words) means a conventional 20-byte TCP header with no options.
· There can still be TCP options, yet no MSS. The rest of the "and" clause examines that by finding TCP options where the TCP header length is greater than 5, and assumes that the MSS value appears first in the 20th byte offset of the TCP header with a value of 02.
Wireshark is the best tool for finding such traffic using its display filter of:
!(tcp.options.mss) && (tcp.flags.syn == 1)
That finds any packet where the TCP options MSS flag is NOT set, but the segment has the SYN flag set. As you can see in the Wireshark capture that follows, the displayed segment was a SYN flag and TCP options of "SACK permitted", "Timestamps", and "Window scale", yet no MSS.
Once the MSS is set on the SYN or SYN/ACK, it should not appear in any other segment. This is true of two other TCP options – the window scale, and the Selective Acknowledgment acceptable. If any of these three options appears on a non-SYN segment, it is surely crafted. Again, Wireshark can expose these bogus packets using a display filter of:
tcp.flags.syn == 0 && (tcp.options.mss || tcp.options.wscale || tcp.options.sack)
The following Wireshark capture displays some of nmap OS fingerprinting packets that are exposed with the above display filter:
The specific packet that is displayed has the FIN, PUSH, and URG flags set along with the window scale, MSS, and timestamp set.
Another unusual condition that may be a reflection of a crafted packet or a poorly written TCP/IP stack is where a client SYN packet has a non-zero acknowledgement value. After all, the client has received nothing to acknowledge. The tcpdump filter to discover such packets is:
tcp[13] = 2 and tcp[8:4] > 0
The following Wireshark display filter exposes these packets.
tcp.flags.syn == 1 && tcp.flags.ack == 0 && tcp[8:4] > 0
The nmap OS fingerprinting scan creates some of segment with these characteristics as shown in the following Wireshark output:
When I've crafted packets, it is typically in a research environment and I'm not worried about the traffic being uncovered. As I've mentioned before, I use Scapy to craft my packets and the easiest way to close a session is to use a one packet reset. However, if I were trying to fit in, I'd go through the trouble of crafting the 4-way graceful FIN close so as not to attract notice.
That's about it for fitting in.