Following the rules spoils the fun – suppressing normal TCP replies
The details of a TCP handshake are beyond the scope of this chapter, but we'll discuss the basics to understand what we need to do to pull off the masquerade. Most of us are familiar with the TCP three-way handshake:
- The client sends a SYN request (synchronize)
- The receiver replies with a SYN-ACK acknowledgment (synchronize-acknowledge)
- The client confirms with an ACK acknowledgment; the channel is established and communication can begin
This is a very simple description (I've left out sequence numbers; we'll discuss those further), and it's nice when it works as designed. However, those of you with any significant Nmap experience should be familiar with the funny things that can happen when a service receives something out of sequence. Section 3.4 of RFC 793 is where the fun is really laid out, and I encourage everyone to read it. Basically, the design of TCP has mechanisms to abort if something goes wrong – in TCP terms, we abort with a RST control packet (reset). This matters to us here because we're about to establish a fraudulent TCP connection designed to mimic one created by the Safari browser on an iPad. Kali will be very confused when we get our acknowledgment back:
- Scapy uses our network interface to send the forged SYN packet
- The captive portal web service sends a SYN-ACK back to our address
- The Kali Linux system itself, having not sent any SYNs, will receive an unsolicited SYN-ACK
- Per RFC specification, Kali decides something is wrong here and aborts with a RST packet, exposing our operating system's identity
Well, this won't do. We have to duct-tape the mouth of our Kali box until we get through validation. It's easy enough with iptables.
iptables is the Linux firewall. It works with policy chains where rules for handling packets are defined. There are three policy categories: input, forward, and output. Input is data destined for your machine; output is data originating from your machine; and forward is for data not really destined for your machine but will be passed on to its destination. Unless you're doing some sort of routing or forwarding – like during our man-in-the-middle attack earlier in the chapter – then you won't be doing anything with the forward policy chain. For our purposes here, we just need to restrict data originating at our machine.
Extra credit if you've already realized that, if we aren't careful, we'll end up restricting the Scapy packets! So, what are we restricting, exactly? We want to restrict a TCP RST packet destined for port 80 on the gateway and coming from our Kali box. For our demonstration, we've set up the listener at 192.168.108.215 and our Kali attack box is at 192.168.108.225.
# iptables -F && iptables -A OUTPUT -p tcp --destination-port 80 --tcp-flags RST RST -s 192.168.108.225 -d 192.168.108.215 -j DROP
Let's break this down:
- -F tells iptables to flush any currently configured rules. We were tinkering with rules for our ARP attack, so this resets everything.
- -A means append a rule. Note that I didn't use the potentially misleading term add. Remember that firewall rules have to be in the correct order to work properly. We don't need to worry about that here as we don't have any other rules, so that's for a different discussion.
- OUTPUT identifies the policy chain to which we're about to append a rule.
- -p identifies the protocol, in this case TCP.
- --destination-port and --tcp-flags are self-explanatory: we're targeting any RST control packets destined for the HTTP port.
- -s is our source and -d is our destination.
- -j is the jump, which specifies the rule target. This just defines the actual action taken. If this were omitted, then nothing would happen but the rule packet counter would increment.
The following screenshot illustrates the output of the preceding command:
We're ready to send our forged packets to the captive portal authentication page.