Data exfiltration using valid ICMP packets

I was thinking about how someone could go about doing data exfiltration in an average enterprise with decent security. I’m assuming DNS…

I was thinking about how someone could go about doing data exfiltration in an average enterprise with decent security. I’m assuming DNS exfiltration won’t work, as they have their own DNS server(s) and any other DNS traffic elsewhere I’d dropped. HTTP(S) also won’t work because they heavily whitelist/proxy. USB and external media is all locked down because they either disabled it or filled it in with something. Do you know what most companies still tend to let through? Of course you do, it’s in the title, good old ICMP.

ICMP security

Most companies don’t disallow ICMP out because… well, they need it for troubleshooting… how else are they going to determine what is causing system or network issues??? Typically you ping some outside IP address if you want to troubleshoot where your connectivity issue(s) are.

Is it new?

This isn’t entirely new, using ICMP to send messages has been done before; however, I’ll be communicating using normal ICMP packets, to the same IP… the first two I know have been done before. It’s just not very common, or the way I’m going about my communication. I’ll be using time to encode my data. Some, if not all, IPS systems can find invalid ICMP packets. You can even look at ICMP packets using packet captures and you’d notice the data isn’t a normal ICMP packet.

Encoding

There are different methods you can go about encoding your data. You want to do this for two reasons. One being the obvious… you don’t want it to look obvious. In terms of DNS exfiltration it would look pretty weird for DNS requests to go out with SSN in URLs, or in the data of a ping. Two, it makes it easier to come up with exfiltration ideals. Being limited to just using ASCII is kind of a pain, as some stealthy methods can’t be used because it’s to high level. Like on and off.

What I did

What I decided to do instead is to use time to represent my on and off. You give me a bunch of ASCII characters (letters and numbers). I take that data, convert it to binary. I then have a list if binary numbers. I iterate over that list and send out pings with a timeout of binaryNumber+leway. The leway is so that I’m forgiving slower connections, but that means the transfer will happen slower, but you’d also be more stealthy. You’d be sending out pings less often.

If a security researcher saw these ICMP packets they’d just see valid ICMP packets. Unless they knew about this method there wouldn’t be any data for them to find. If they knew about this method they would then need to look at the time between packets and try to find a pattern. That doesn’t mean they’d know what was sent. You could get a little trickier by encrypting, that way they’d just get noise when trying to look. There’d be a lot of entropy, too random, then there’s probably something there.

Code

To show this I made two Python 3 scripts. The first script is the ping script. You run it, giving it a string. It then encodes that data into binary. The script then proceeds to send that data via time in-between ICMP packets. The second script is the server. The server, running as root, is looking for ICMP packets and mapping the source address to a list of datetime objects. When the transmission is done you control+c and the script iterates over the datetime objects to get the binary data, then converts that to ASCII. I was able to send my name and number this way and it was pretty reliable. If you set the leway too low you could run into issues properly translating it.

The script can be viewed on GitHub:

https://github.com/martinoj2009/ICMPExfil