IPTables Brown Bag

by Joel R. Voss
Sept 5, 2018 - May 15, 2019

``So... how is this better than KDE?''

(C) 2000 Paul `Rusty' Russell. Licenced under the GNU GPL.

Talk Slides

No introduction necessary

The commands you need to know to effectively operate IPTables in a hostile environment (the internet, the WiFi, the LAN, and OpenCTF).

sudo iptables -L -n
Password:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If you see policy ACCEPT and no rules like this, your firewall is down.

What can we do to fix this?

Assume you have a server with only SSH inbound open. Anything outbound open.

sudo iptables -A INPUT -p tcp -i eth0 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp -i eth0 -j DROP
sudo iptables -A INPUT -p udp -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p udp -i eth0 -j DROP

Note that I am not blocking ICMP inbound or any other protocols. I like ICMP and think that we should support it. If you want to block it, you should know how by looking at the above code for tcp and udp.

Remember that you have to do this for each interface or you have to accept having the same rule on all interfaces.

sudo iptables -L -n
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state RELATED,ESTABLISHED
DROP       tcp  --  anywhere             anywhere
ACCEPT     udp  --  anywhere             anywhere             state RELATED,ESTABLISHED
DROP       udp  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Since iptables is usually a part of a firewall or a router, you will want to check the nat table. For your laptop, VM, or tablet, you might find it empty like so:

sudo iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Are your tables broken? Do you want to start over from scratch?

sudo iptables -F

Now how do you avoid having to run these commands each time you boot? You need an init script that does iptables-restore with your file.

sudo iptables-save >firewall_inbound1.txt

sudo iptables-restore firewall_inbound1.txt

If you use Gentoo, there's an init script that is pretty cool. It saves rules to /var/lib/iptables/rules-save which seems like an okay place to save firewall rules.

sudo /etc/init.d/iptables save

It's the same as if you did this yourself by hand.

So now the next level of security is outbound filtering. What if you have a rogue program that talks on port 1337? Same thing as before, just use the outbound table.

sudo iptables -A OUTPUT -p tcp --dport 1337 -j DROP

You don't have to deal with interface this time.

Now you want to learn how effective your firewall is. How do you do that? Most admins create a chain called LOG_DROP and jump to it. When a packet finds itself in this chain, it is logged, then dropped. Let's do that. When your logs get messy, you can remove the log from the LOG_DROP chain.

sudo iptables -N LOG_DROP
sudo iptables -A LOG_DROP -j LOG
sudo iptables -A LOG_DROP -j DROP

sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere             state RELATED,ESTABLISHED
DROP       tcp  --  anywhere             anywhere
ACCEPT     udp  --  anywhere             anywhere             state RELATED,ESTABLISHED
DROP       udp  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere             tcp dpt:1337

Chain LOG_DROP (0 references)
target     prot opt source               destination
LOG        all  --  anywhere             anywhere             LOG level warning
DROP       all  --  anywhere             anywhere            

As you can see, this provides you with a cool little chain that you can use to test things. Let's test what happens when you have two rules that match the same thing in a chain.

sudo iptables -A OUTPUT -p tcp --dport 1337 -j LOG_DROP

Apparently it never gets hit since no logs are produced when we nc altsci.com 1337

Man in the Middle - 2010

So now we are ready for some serious business.

What are you likely to need for hacking?

The first thing I have ever really liked in iptables is the ease of which you can do ARP spoofing. Here is my script that will (with a bit of clever additions) take over a whole network:

sudo iptables -t nat -N MIDDLERNAT
sudo iptables -t nat -I MIDDLERNAT \
    -p tcp --dport 80 -j REDIRECT \
    --to-ports 1080
sudo iptables -t nat -A PREROUTING -j MIDDLERNAT
echo 1 |sudo tee /proc/sys/net/ipv4/ip_forward
sudo python dnsam1.py &
sudo python arpam1.py &
python -m http.server 1080 >~/logs/http_logs-"$(date "+%Y-%m-%dT%T")" 2>&1 &

The next thing you'll probably need for hacking is modifying outbound packets so that they fit some unnecessary firewall filter. Admins put firewall filters in front of their servers with the hope that you can't connect but they can. How does that work again?

Due to time constraints, I leave this up to the reader. Or you can ask me afterward and I'll update the living paper.

Logging

The next thing you'll probably want for hacking is logging on packets that don't match your expected network traffic. Paranoia can sometimes lead you to wonder if a clever hacker has put malware onto your system. How do you decide if there's an easy way to determine if that is true? First step of any malware discovery is escalation of privilege. With a secondary device, you can log packets coming out of your first machine.

Your traffic should be on your ssh port and nothing else. Let's log everything that is not from your IP address.

sudo iptables -A INPUT -p tcp -i eth0 -s 10.30.0.128 --dport 22 -j ACCEPT

sudo iptables -D INPUT -p tcp -i eth0 -j DROP
sudo iptables -D INPUT -p udp -i eth0 -j DROP

sudo iptables -A INPUT -p tcp -i eth0 -j LOG_DROP
sudo iptables -A INPUT -p udp -i eth0 -j LOG_DROP
sudo iptables -A INPUT -j LOG

[833191.946620] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:f4:96:34:11:97:39:08:00 SRC=10.30.0.126 DST=10.30.0.255 LEN=72 TOS=0x00 PREC=0x00 TTL=128 ID=23903 PROTO=UDP SPT=57621 DPT=57621 LEN=52
[833196.476826] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:14:ab:c5:81:26:e4:08:00 SRC=10.30.0.104 DST=10.30.0.255 LEN=78 TOS=0x00 PREC=0x00 TTL=128 ID=7037 PROTO=UDP SPT=137 DPT=137 LEN=58
[833197.229610] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:14:ab:c5:81:26:e4:08:00 SRC=10.30.0.104 DST=10.30.0.255 LEN=78 TOS=0x00 PREC=0x00 TTL=128 ID=7039 PROTO=UDP SPT=137 DPT=137 LEN=58
[833197.981881] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:14:ab:c5:81:26:e4:08:00 SRC=10.30.0.104 DST=10.30.0.255 LEN=78 TOS=0x00 PREC=0x00 TTL=128 ID=7041 PROTO=UDP SPT=137 DPT=137 LEN=58
[833199.967419] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:e4:a4:71:93:9a:95:08:00 SRC=10.30.0.123 DST=10.30.0.255 LEN=72 TOS=0x00 PREC=0x00 TTL=128 ID=23080 PROTO=UDP SPT=57621 DPT=57621 LEN=52

Now we add a log for outbound traffic.

sudo iptables -A OUTPUT -j LOG --log-prefix="[outbound]"

So now we have a problem of too much logging. So let's fix that.

sudo iptables -D OUTPUT -j LOG --log-prefix="[outbound]"

sudo iptables -A OUTPUT -p tcp --dport 22 -m state --state RELATED,ESTABLISHED,NEW -j ACCEPT
sudo iptables -A OUTPUT -p tcp --sport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT

sudo iptables -A OUTPUT -j LOG --log-prefix="[outbound]"

[834946.498108] [outbound]IN= OUT=eth0 SRC=10.30.0.107 DST=10.10.0.2 LEN=56 TOS=0x00 PREC=0x00 TTL=64 ID=19291 DF PROTO=UDP SPT=56642 DPT=53 LEN=36
[834949.310985] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:e4:a4:71:93:9a:95:08:00 SRC=10.30.0.123 DST=10.30.0.255 LEN=72 TOS=0x00 PREC=0x00 TTL=128 ID=23249 PROTO=UDP SPT=57621 DPT=57621 LEN=52
[834951.503459] [outbound]IN= OUT=eth0 SRC=10.30.0.107 DST=10.15.0.2 LEN=56 TOS=0x00 PREC=0x00 TTL=64 ID=37847 DF PROTO=UDP SPT=43322 DPT=53 LEN=36
[834952.569834] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:ac:bc:32:b3:7f:df:08:00 SRC=10.30.0.110 DST=10.30.0.255 LEN=72 TOS=0x00 PREC=0x00 TTL=64 ID=64817 PROTO=UDP SPT=57621 DPT=57621 LEN=52
[834954.207725] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:ac:bc:32:b3:7f:df:08:00 SRC=10.30.0.110 DST=255.255.255.255 LEN=162 TOS=0x00 PREC=0x00 TTL=64 ID=64380 PROTO=UDP SPT=17500 DPT=17500 LEN=142
[834954.207726] IN=eth0 OUT= MAC=ff:ff:ff:ff:ff:ff:ac:bc:32:b3:7f:df:08:00 SRC=10.30.0.110 DST=10.30.0.255 LEN=162 TOS=0x00 PREC=0x00 TTL=64 ID=50695 PROTO=UDP SPT=17500 DPT=17500 LEN=142
[834956.508610] [outbound]IN= OUT=eth0 SRC=10.30.0.107 DST=10.10.0.2 LEN=56 TOS=0x00 PREC=0x00 TTL=64 ID=20388 DF PROTO=UDP SPT=56642 DPT=53 LEN=36
[834956.512811] [outbound]IN= OUT=eth0 SRC=10.30.0.107 DST=216.218.134.11 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=26133 DF PROTO=TCP SPT=46774 DPT=91 WINDOW=29200 RES=0x00 SYN URGP=0

As you can see, the attacker made a DNS request, it was replied to, then they connected to port 91. There was no response.

Now let's talk about the unfortunate consequences of this firewall design. They can create a list of legitimate inputs and outputs and log everything, set up an alert on every log they generate, and each time you pop a shell and use a port other than the one that they use for their service, you are caught.

So how do you bypass this firewall rule? Use a mitm on a rule that the firewall allows.

One of the books that I noticed had a pretty good explanation of iptables is Security Power Tools. It's 11 years old but it's terse.

Lack of documentation is a major problem with iptables. You will find people doing it wrong because there is no clear test or list of do's and don'ts. The reason for this is because you need to know a significant amount about networks to use iptables correctly and when you get there, you don't need a manual so much as a pentest. And what Blue team guy is also a Red team guy? Oh no!