Firewall Bypass over ICMP Covert Channel

It’s been a while since my last post mostly because of busy schedule. Anyways, I discovered something interesting so decided to share with you all.

Imagine a scenario where you are behind firewall that allows only few specific protocol , but luckily it’s allowing ICMP packets to pass through. In such cases covert channel through ICMP can be very handy.Using ICMP echo and reply requests we can construct a tunnel to overcome network restrictions.

ICMP is a layer 3 protocol (in OSI and TCP/IP model), This is also the lowest level any firewall can work. ICMP interestingly can also be used to hide the traffic and bypass firewall rules which is mostly undetectable without proper packet inspection.

The ICMP header starts after the IPv4 header and is identified by IP protocol number ‘1’. All ICMP packets have an 8-byte header and variable-sized data section. The first 4 bytes of the header have fixed format, while the last 4 bytes depend on the type/code of that ICMP packet
ICMP datagram has following structure
1

Where

Type=Type of ICMP message ( 8 for ping request and 0 for ping reply )

CODE=Used to show specific condition

CHECKSUM=checksum of data

DATA=Actual data

ping utility is most commonly used utility to send ICMP requests. So, Let’s analyse a ICMP packet through wireshark to get better understanding

3
Let’s take a look at ping request packet

4

We can see here the type , checksum and actual data that’s being sent through the ICMP request

5

First 14 bytes are Ethernet Header
6
next 20 bytes is IPv4 header
7
Remaining of it being ICMP packet(Header + Payload)

You might notice that data that was sent via ping is abcdefghijklmnopqrstuvwabcdefghi (32 bytes)

How to modify data sent in ICMP ?

Python will allow us to do this task easily , we can modify packet and send out own desired data using raw packet.

1
2
3
4
5
import socket
s=socket.socket(socket.AF_PACKET,socket.SOCK_RAW)
s.bind(("eth0",0))
packet="\x00\x0c\x29\x28\x37\xea\x00\x50\x56\xc0\x00\x08\x08\x00\x45\x00\x00\x3c\x1a\x5d\x00\x00\x80\x01\x8a\x90\xc0\xa8\x0a\x01\xc0\xa8\x0a\x82\x08\x00\x42\x7b\x00\x01\x0a\xe0\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x61\x62\x63\x64\x65\x66\x67\x68\x69"
s.send(packet)

8

Notice that it’s same packet as ping request shown before (including IPv4 and Ethernet Header) and actual data starts from \x61 which is a so we can modify packet from there to send any desired text message after changing that.

so,

1
2
3
4
5
import socket
s=socket.socket(socket.AF_PACKET,socket.SOCK_RAW)
s.bind(("eth0",0))
packet="\x00\x0c\x29\x28\x37\xea\x00\x50\x56\xc0\x00\x08\x08\x00\x45\x00\x00\x3c\x1a\x5d\x00\x00\x80\x01\x8a\x90\xc0\xa8\x0a\x01\xc0\xa8\x0a\x82\x08\x00\x42\x7b\x00\x01\x0a\xe0\x61\x61\x61"
s.send(packet)

is going to send out aaa

What else ?

We can send any data thru ICMP by this technique , check out this stackoverflow answer on how to send image in data field of ICMP by python

You may even send all your traffic using ICMPTX(IP-over-ICMP). ICMPTX is a program that allows a user with root privledges to create a virtual network link between two computers, encapsulating data inside of ICMP packets.

There is a similar, thoroughly program called itun, a simple icmp tunnel that claims to do the same thing. Also, check out PingTunnel which is not IP-over-ICMP, but rather TCP-over-ICMP and, therefore, less useful.