Fire in the hole

Posted on February 15, 2013

5



In this post I tested in my lab if tunneling with icmp really opens a hole that a simple stateful firewall cannot realize. ICMP is a protocol that is opened everywhere since we need it for our daily job and honestly I have never thought that even with this I open a hole on firewall.
There is another tunneling mechanism that can be used, like udp 53 tunneling or whatever tcp port tunneling or even an ssh server can listen on any opened port and an ssh tunneling is pretty easy.
Those facts make it really important to use an application firewall or an IPS or an anomaly detection system.
The original documentation and the posts about icmptx can be found with google or here:
http://thomer.com/icmptx/
There is a lot of tests and posts about icmptx but no one tested it through real firewalls, like Checkpoint or Fortigate.

On the following picture we can see a topology how that can work with our icmptx server at home.
Our icmptx server is protected with a firewall as well and it forwards every imcp packet to the icmptx server.

ICMPTX_Topo_Basic

Lets see how I did it in my enviroment and what I have found about it:
(for all the commands I used I had to use root privileges)

The topology I used in lab was not so complicated as above. I have not protected my server with a firewall like at home and the server and the firewall are on the same network. Lets create an issue for our test.

ICMPTX_Topo_Test

The Problem discription:
The client 1 in the LAN has no access to client 3 but can access client 2. The Firewall admin is an idiot and does not want to allow our access.
This access cannot wait anymore since there is an online video server on client 3 where the Super G Woman from Schladming will be reachable LIVE! We have to get access, Maria Höfl Riesch runs in a minute!

A) Setting up ICMPTX Server:
*******************************

SW: Ubuntu Server
HW: HP DL 380

1. Change the following settings to ignore icmp request in the operation system.

xyz@sec-server1:~$ sudo echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all
xyz@sec-server1:~$ sudo echo 1 > /proc/sys/net/ipv4/ip_forward

OR for permanent changes:

Edit the sysctl.conf file and add the following line:

xyz@sec-server1:~$ sudo vi /etc/sysctl.conf
...
# icmptx requirements
net.ipv4.ip_forward=1
net.ipv4.icmp_echo_ignore_all=1

Execute sysctl -p to enforce this setting immediately:

xyz@sec-server1:~$ sudo sysctl -p
net.ipv4.ip_forward = 1
net.ipv4.icmp_echo_ignore_all = 1

2. Setup NAT on the same interface.
Since we terminate the tunnel and forward the traffic on the same interface we have to use NAT.
That helps for the packets to find the way back to the server that terminated the tunnel, since my source ip is on another net, that is not known in the destionation net.

xyz@sec-server1:~$ sudo iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
xyz@sec-server1:~$ sudo iptables -A FORWARD -s 20.0.0.0/24 -o eth0 -j ACCEPT
xyz@sec-server1:~$ sudo iptables -A FORWARD -d 20.0.0.0/24 -m state --state ESTABLISHED,RELATED -i eth0 -j ACCEPT

Check what you did:

xyz@sec-server1:~$ sudo iptables -vnL --line-numbers -t nat
Chain PREROUTING (policy ACCEPT 1474K packets, 61M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 99876 packets, 6845K bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 76754 packets, 4773K bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 25331 packets, 1603K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     104K 6403K MASQUERADE  all  --  *      eth0    0.0.0.0/0            0.0.0.0/0

More info on this and how to check it if it is correct, at the end of the post.

3. Start the icmptx SERVER.

The IP is the IP of this machine.
This command requires root privilege since it will create a tunnel interface if it can start.

xyz@sec-server1:~$ sudo icmptx -s 20.0.0.34 &
[1] 7026
xyz@sec-server1:~$ sudo ifconfig tun0 mtu 3500 10.10.10.1 netmask 255.255.255.0
xyz@sec-server1:~$

Check what you did:

xyz@sec-server1:~$ ifconfig tun0
tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:10.10.10.1  P-t-P:10.10.10.1  Mask:255.255.255.0
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:3500  Metric:1
          RX packets:3 errors:0 dropped:25 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:500
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

xyz@sec-server1:~$
xyz@sec-server1:~$ jobs
[1]+  Running                 sudo icmptx -s 20.0.0.34 &

B) ICMPTX Client:
******************

SW: Ubuntu Server
HW: HP DL 380

1. Start the icmptx client.

The IP is the real IP of the machine on the other end of the tunnel.

# icmptx -c 20.0.0.34 &
# /sbin/ifconfig tun0 mtu 3500 up 10.10.10.2 netmask 255.255.255.0

Check what you did:

# /sbin/ifconfig tun0

2. Set the route to the tun0 interface

We do not go out through the gateway we have, we route everything through the tunnel, since we are BAD:

# /sbin/route add -host 20.0.0.34 gw 40.0.0.1 dev eth0
# /sbin/route del default
# /sbin/route add default gw 10.10.10.1 tun0

C) IPTABLES info:
******************

Add a nat rule (hide nat on eth0 as the outgoing interface)

# sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

list rules and nat rules

# sudo iptables -vnL --line-numbers
# sudo iptables -vnL --line-numbers -t nat

delete NAT rule

# sudo iptables -t nat -D POSTROUTING 2

And thats it, but there is something I realised during my test. I have tested this tunneling first with a fortigate firewall and that does not worked. The icmp packets were forwarded to the server, but there was no access through the icmp tunnel.
I have thought the ICMP Inspection makes it impossible to tunnel through the Fortigate gateway and started to test with different devices:
1. through a simple router without NAT and without access-list. It has worked without any problem.
2. through a Linux Firewall with access-lists and NAT (iptables). It has worked without any problem. And here I started to get nervous, since the sniffer trace has not showed me any differences before and after the linux firewall. But after that I compared the sniffer trace from Fortigate and from Linux firewall, I realised that the Fortigate makes with NAT a small change in the packet. To prove it, I went to the next test.
3. through a Fortigate again but without NAT. It worked without any problem. The result with NAT is not exactly a security feature (as I thought) but a proof of non rfc compliant nat process. I just checked the RFC for NAT Behavioral Requirements for ICMP and find this:


3.1. ICMP Query Mapping

Unless explicitly overridden by local policy, a NAT device MUST
permit ICMP Queries and their associated responses, when the Query is
initiated from a private host to the external hosts. ICMP Query
mapping by NAT devices is necessary for current ICMP-Query-based
applications to work. This entails a NAT device to transparently
forward ICMP Query packets initiated from the nodes behind NAT, and
the responses to these Query packets in the opposite direction. As
specified in [NAT-TRAD], this requires translating the IP header. A
NAPT device further translates the ICMP Query Id and the associated
checksum in the ICMP header prior to forwarding.

NAT mapping of ICMP Query Identifiers SHOULD be external-host
independent. Say, an internal host A sent an ICMP Query out to an
external host B using Query Id X. And, say, the NAT assigned this an
external mapping of Query Id X’ on the NAT’s public address. If host
A reused the Query Id X to send ICMP Queries to the same or different
external host, the NAT device SHOULD reuse the same Query Id mapping
(i.e., map the private host’s Query Id X to Query Id X’ on NAT’s
public IP address) instead of assigning a different mapping. This is
similar to the “endpoint independent mapping” requirement specified
in the TCP and UDP requirement documents [BEH-UDP], [BEH-TCP].

Source:
http://tools.ietf.org/html/rfc5508

And in the sniffertrace from Fortigate with NAT I see that it changes the Query ID but the icmptx seems to be based on it..

Before NAT:

icmp_before_nat

After NAT:

icmp_after_nat

Against this behaviour I have dig google further and find some othe icmp tunnel alternates:

ICMPTX Variant:
http://code.gerade.org/hans/
http://www.cs.uit.no/~daniels/PingTunnel/

If I have time I will test them, they look like icmptx improvments. :-) And I will test how a Cisco and a Checkpoint Firewall follow the NAT concept (RFC). If you feel the power, you can test it and update me.

Advertisements
Posted in: Penetration, Security