[Maarten Van Horenbeeck] [Information Security] [Resources]

Entity tags as an HTTP covert channel

During a recent penetration test I was faced with an issue. I obtained access to a network and needed to "smuggle" out a certain binary file. However, DNS was not an option as resolution could only be performed on the HTTP proxies. In addition, we wished to avoid audit activitites taking place after the test identifying what data exactly travelled the network.

With HTTP Tunneling, this is usually difficult to achieve. Most of these tools perform tunneling either through a GET or POST request that contains the actual data in the URI request string. This means that after the fact, it is possible to identify what has been tunneled. The request string is often stored in proxy logs and can easily be retrieved.

In HTTP however, there is a certain interaction between the "Etag" header (on the server side) and "Match-If-None" (and some related tags, on the client side). Upon a connection, a server can provide an Etag, or entity-tag, which is used by the client to identify the version it has in its cache. Proxies can also put this field to use.

As is the case with e.g. basic authentication, these headers can be lengthy and offer good performance in sending through data. More importantly, the headers themselves are usually not logged. For the Etag header, no particular format is described. It is merely a random value contained by "" thatt identifies the entity and "may" be used for caching.

So, I put it to use a bit differently. I split up a file into small groups of bytes and launched requests through the proxy with these parts of the file (base64 encoded) as an Etag header. On the other end I had an application running which received each of the Etags and stored them to a file locally.

Naturally, the proxy would normally have cached my requests, if they were for one file, so I added a return "no-cache" header in the response. One disadvantage with this method is that in your proxy logs, you will have a high amount of GET requests with very little content. An example:

1148834194.664 258 TCP_MISS/200 64 GET - DIRECT/ -
1148834195.073 258 TCP_MISS/200 64 GET - DIRECT/ -

This is quite apparent even to the untrained eye. As such, I used the "byte-range" header in the request so that they would be logged as 206 entries, and had the server create a random ASCII text file so that the size of the transactions would be higher. This is a bit less obvious, as 206 means that a partial transfer is taking place - it could just be a client that's downloading a file in pieces.

Potential countermeasures that can be implemented:
For this purpose, I wrote a small piece of Perl code that could essentially get the job done. It is however not a software tool, as such don't expect it to work in all circumstances. It is called Wondjina.
"In Aboriginal mythology, the Wondjina (or wandjina) were cloud and rain
 spirits who, during the Dream time, painted their images (as humans but
 without mouths) on cave walls. Their ghosts still exist in small ponds."
Do note that while in fact, Wondjina only tunnels out (one way traffic) the matching between Etag and if-none-match is ideal for bidirectional tunneling. Wondjina has a lot of limitations that depending on the situation you may require to run this succesfully:
If you'd like to give it a try, get wondjina here.
Read basic use instructions and documentation here.

Articles and discussions on HTTP tunneling

Securityfocus: Data driven attacks using HTTP tunneling
Devarticles.com: HTTP Tunneling revealed
Detecting HTTP Tunneling Activities

Links to HTTP tunneling tools and services

HTTPTunnel uses GET and POST for full socket tunnels
Hopster is commercial software for tunnling through HTTP proxies
HTun allows a TUN device to be tunneled

Reference works

RFC 2616 - HyperText Transfer Protocol -- HTTP/1.1
ETag header support in the Squid proxy
A guide to understanding covert channel analysis of trusted systems [Light Pink Book]

Books that could be of help

HTTP Developer's Handbook