Sunday, March 11, 2012

ICMP for stealth transport of data

ICMP (Internet Control Message Protocol) has been used for data transfer since always. Known as ICMP Tunnel, there are several projects and articles about this, mainly open source, like ICMP-Chat for unix-like that is about 10 years old now. Also an interesting article, explaining how to tunnel TCP over ICMP with a simple command line tool for unix-like environment, also ported to Windows.

In case you are not familiar with the idea, a description from Wikipedia follows:

"ICMP tunneling works by injecting arbitrary data into an echo packet sent to a remote computer."..."This vulnerability exists because RFC 792, which is IETF's rules governing ICMP packets, allows for an arbitrary data length for any type 0 (echo reply) or 8 (echo message) ICMP packets."

It is correct to say that ICMP is normally not considered a threat, at least not by the majority of network administrators. It's common to add security mechanisms (IDS, IPS, appliances, etc) to a corporate network, but in the end all types of ICMP packets, with all payload sizes etc, pass freely at least from within the private network to the outside world. This technique is used to send sensitive data outside a private network without relying on SMTP, HTTP or other upper layer protocol that are commonly monitored and logged.

The Sender:

The sender has very simple implementation. Considering the objective is to send data to the outside world, the reply is actually irrelevant. The Sender code does not require to handle the replies.

At first I started writing the Sender code with raw sockets, having lots of fun using binary operators (<<, >>, ~, etc), writing one's complement and reading the RFC 792. Then I found the code would only run when executing as administrator. The whole idea wouldn't make much sense if the Sender process requires elevated privilege. Take for example the ASP.NET Application Pool, as default, wouldn't be able to run it. And the worse is that this is not something new at all, SOCK_RAW function access was blocked to non administrator users as described by this Microsoft knowledge base article since Windows NT 4.0, which means, always.

I can still remember writing ICMP type 8 (echo request) packets with custom payload about 4 years ago, with C#, and without writing that much code anyway. So I tried the Ping class, introduced on .Net Framework 2.0 only to find a third parameter of type byte[] called buffer: Great! That's the payload. So this is the way to go.

Working with ICMP is not the same as standard TCP or UDP sockets. We don't need to Bind a socket to a logical port so the operating system knows which software will handle the packets. To better describe this, I will quote a paper from SANS institute:

Although ICMP messages are sent in IP packets and it uses IP as if it were a higher-level protocol, ICMP is in fact an internal part of IP, and must be implemented in every IP module.

Because of this behavior, monitoring processes and its TCP or UDP ports in use is pointless when using this technique.

When implementing the Receiver part of this PoC, I used Microsoft Network Monitor 3.4, which has an API and already comes with a wrapper class in C# called NetmonAPI.cs. So if you want to run this code, install Microsoft Network Monitor, and add NetmonAPI.cs to your project.

Obviously, running the two portions of the code on the same computer does not explain clearly what goes on behind the scenes. But note that there is nothing handling the reply from the Ping code (the Sender part). The Sender thread, is pinging Google but doesn't know about the reply at all. The Receiver code, running on a different thread, using Microsoft Network Monitor 3.4 API is intercepting all ICMP type 8 packets and parsing its data field.

Now adding the Sender portion to an HttpModule as I mentioned in previous post, an attacker could send sensitive data to another peer via simple ICMP echo requests. The data could be scrambled with a simple XOR or even ciphered with symmetric-key algorithm using hardcoded password or asymmetrically with a public key. Breaking large data into small chunks, would avoid fragmentation (remember MTU for Ethernet is 1500 bytes) and strangely big ICMP packets. Reordering the data on the Receiver gives great possibilities for data transfer. Even an ICMP Chat for Windows could be done, as mentioned in the introduction, exists one for unix-like systems.

Mitigation

On Wikipedia mitigation section, I found:

"Although the only way to prevent this type of tunneling is to block ICMP traffic altogether, this is not realistic for a production or real-world environment. One method for mitigation of this type of attack is to only allow fixed sized ICMP packets through firewalls to virtually eliminate this type of behavior."

I disagree that allowing only fixed size ICMP packets would avoid ICMP Tunnel since the data can be break into smaller chunks, fixed ones, and reassembled by the Receiver. Using the code I created as PoC, we can easily change the size of the data, even writing fixed size data, by adding one layer to control sequence numbering, offset, etc. Also we can change the ICMP type by using instead of echo Request, Destination Unreachable, or any other. However, considering the idea here is the theft of information, sent from within the network (behind NAT for example), to an external system that will probably receive and log data not only from one, but from several compromised systems, echo Request fits perfectly.

It's true that there are applications and other protocols relying on ICMP to work properly. The impact of blocking ICMP completely should be assessed prior to taking such action. Still, it should be blocked when not needed, and firewall rules to allow it on each particular case it is required.

About Me

Works with Software development, graduated in Computer Networks, Computer Security hobbyist.
Interested in these three fields since the late 1990's when everyday, hours were spent in front of the computer (especially on IRC ;) looking for more.