Having described how Ethernet, IP and TCP headers can be identified in a packet’s bytecode the other day, I wanted to post a follow-up that deals with the function of each header and why the main header fields exist. Consequently, this post also provides a networking 101, and some handy COMSEC information related to what packet inspection systems can read and what isn’t encrypted in a SSL/TLS session.
Here I’ve used Wireshark just to better illustrate where the relevant hex digits are. In my workplace we have reference sheets for this stuff, and all security analysts become fluent in it after several weeks.
If you’re ever in doubt about the header placements, the initial bytecode deals with the link layer (Ethernet) and progresses up the OSI layer as we move along the sequence. A packet is analogous to an onion, with bytes being discarded the further it goes up the OSI layer.
Some of us are taught that Ethernet frames are encapsulated or re-encapsulated when they reach the gateway router, which is only partially correct. What actually happens is the TCP/IP packet is prefixed by three values: a destination MAC address, the source MAC address and the frame type. These three values form the 14-byte Ethernet header:
Here’s how it looks in Wireshark:
So it’s a very simple sequence of hex digits with just three variables. Ethernet’s been around a long time, and was designed to enable communication between fairly primitive network interfaces and layer 2 switches.
Initially the frame/packet is broadcast to every network interface in a VLAN or segment, and typically it’s dropped by every network interface that doesn’t have the destination MAC address. It’s kind of like shouting someone’s name in a room of people, and waiting to see who responds. The initial 6 bytes simply wakes the destination network card, and causes it to buffer the next 6 bytes.
One thing I’d add is the first three bytes of a MAC address usually (but not always) reveals the manufacturer of the network interface, which is how they’re listed in Wireshark captures.
In addition to MAC addresses there is a ‘Type’ value, tells the gateway router what the subsequent bytes are. The most common value encountered is 0x0800, or ’08 00′, which tells the router to expect an IP header.
On reaching a router, the Ethernet header is discarded, and we’re left with the TCP/IP packet, and from this point the packet is routed according to logical addresses (IPv4 or IPv6).
Because routers are usually more sophisticated than switches and network interfaces, there are more fields in the IP header. Everything within the IP header, which is typically 20-bytes in length, is related to getting the packet from A to B.
Many of these header fields are redundant, and won’t exist in IPv6, which is designed for minimising overhead by including only data necessary for routing.
The first header fields of importance are the protocol version and the header length, as these tell the routers whether it’s routing by IPv4 address, and also that everything after x number of bytes is a payload. They’re the initial values that routers must know.
Also in the header are the ‘Protocol’ and ‘TTL’ headers – it’s useful to learn what values to look for, and have a lookup table. If a ‘06‘ value appears around this part of the bytecode, we know it’s most likely a TCP packet.
Obviously the bytecodes for the source and destination IP addresses will exist here. They are easy to work out, since we know an IPv4 address is 32 bits in length and separated into 1 byte octets.
Each octet is converted independently into decimal form. Therefore C0 A8 03 03 becomes 1100 0000 : 1010 1000 : 0000 0011 : 0000 0011, which translates to 192.168.3.3.
That also means ‘CA 08‘ should appear regularly in this part of the bytecode for a typical packet capture, it being a local address. Counting six bytes further will reveal where the TCP header begins.
Finally, and further up the OSI layer, is the TCP header. Pretty much everything here is about session control – making sure the packets reach the application layer in the right order, making sure the packets reach the right software application (or browser tab) and ensuring all packets are communicated between client and server.
So the main header fields here are the source and destination ports, which come first because the TCP header is read after the packet reaches the destination IP address.
The server listens on a fixed port number (usually 80 for HTTP), and the client establishes a TCP connection from an ‘ephemeral’ or transient port. The latter is how multiple TCP sessions can share one IP address, enabling data to reach the correct applications and browser window.
Because the port number is represented by 2 bytes, the maximum number of ports is 65,536.
I’ve included a screenshot of the destination port bytes being highlighted, as it’s another thing to watch for. This tells us roughly what kind of data is likely in the payload.
Lastly there are the TCP status flags, which are useful for a variety of reasons. Remember, these are ultimately bit flags that just happen to translate to hex values.
One reason the SYN, FIN and ACK flags are important is they indicate whether a TCP session was established, whether that session was maintained and if it was terminated. If there are sessionless connections or the flags suggest packets were dropped, something isn’t right.
There are additional flags, such as PSH, which causes a payload to be pushed onto the memory space of whatever application’s using the destination port, and there’s the RST (reset) flag. During my study of the Great Firewall of China, I remember coming across a technique that involves packet inspection systems setting the RST flag whenever a banned web server was being accessed, thereby resetting the TCP session.