
Exfiltrate Data using the old ping utility trick
Date: 2013-09-10 08:28:31We are back with a great blogpost. This time about data exfiltration using ping, packed together as a simple backdoor-like code. The technique may work in generell for linux and windows as well, however the main target and interest was Android.
During the article we will provide examples demonstrating how to implement a client/server architecture that will enable a remote server to exchange data with an Android device via a custom application that need no permissions to run. Example code for the client and server side is provided as a package as well.
During the research it was recognized that the ping utility was already exposed here as a data exfiltration vector on Android and in generel it is public knowledge as shown as well here (quite cool collection of data exfiltration on liners on linux systems). However, we found a different way of communicating, which ends up in the ability to receive bigger data packages on the side of Android.
ICMP Echo Request
The Internet Control Message Protocol(ICMP) is most known by normal users via the utility ping or traceroute, found on basically every Operating System today. If ping is executed it will send an icmp packet with the flags(icmptype and icmpcode) set for an “ICMP Echo Request”, if the remote host wants to acknowledge this, it will respond with an “ICMP Echo Reply”. The protocol itself is a rich suite for information gathering and testing of remote systems. ICMP Backdoors are nothing new, one of the first public implementations is ICMP Backdoor. Our implementation is not using a custom client tool, but the original ping utility as it is supposed to work on a device with a “No permissions app”.
Vulnerable versions
Devices running Android versions prior to version 3.0 allow any user to use the ping utility, which comes with any Android OS version. As of July 8, 2013, Google estimates the following Android version distribution on active devices that contacted the Google Play service:
Version | Codename | API | Distribution |
---|---|---|---|
1.6 | Donut | 4 | 0.1% |
2.1 | Eclair | 7 | 1.4% |
2.2 | Froyo | 8 | 3.1% |
2.3.3 - 2.3.7 | Gingerbread | 10 | 34.1% |
3.2 | Honeycomb | 13 | 0.1% |
4.0.3 - 4.0.4 | Ice Cream Sandwich | 15 | 23.3% |
4.1.x | Jelly Bean | 16 | 32.3% |
4.2.x | Jelly Bean | 17 | 5.6% |
According to Google, roughly 40% of Android devices run a version prior to version 3.0
Sending and Receiving data
Sending data
The ping command line utility allows a user to measure response times from a remote server. Besides that, ping also allows the user to choose a pattern to send inside the ICMP packet, for network testing purposes, using the flag -p as documented in man pages:
-p pattern
You may specify up to 16 ”pad” bytes to fill out the packet you send. This is useful for diagnosing data-dependent problems in a network. For example, -p ff will cause the sent packet to be filled with all ones.
So, from the client point of view, one can use this flag to send data to a remote server.
Receiving data
Although the client can send data to a server, the usual default server OS behavior when receiving ping requests is to send a ping reply back with the same content.
Example Implementation
Attached with this document there is a sample Android project implementing a simple client/server protocol that allows for the server to request the download of a file, upload a file to the device and execute a remote command on the device and get the result.
The control flow is summarized on the following table:
Source | Destination | ICMP | Custom Proto (in ICMP data field) |
---|---|---|---|
Standard KeepAlive | |||
Client | Server | Echo Request (data size 9*) | KeepAlive (pattern 0×1) |
Server | Client | Echo Reply (data size 9) | KeepAlive Response (data 0×2) |
Receive file from server | |||
Client | Server | Echo Request (data size 9) | KeepAlive (pattern 0×1) |
Server | Client | Echo Reply (data size 9) | ReceiveFile (from server) Command (data 0×5) |
Client | Server | Echo Request (data size 1024) | ReceiveData (pattern 0×3) |
Server | Client | Echo Reply (data size 1024) | Send File Name (PingData**) |
Client | Server | Echo Request (data size 1024) | ReceiveData (pattern 0×3) |
Server | Client | Echo Reply (data size 1024) | Send File Content (PingData**) |
……………………………………… | (repeat until EOF) | ||
Client | Server | Echo Request (data size 1024) | ReceiveData (pattern 0×3) |
Server | Client | Echo Reply (data size 1024) | Send File Content (PingData**) |
Send file to server | |||
Client | Server | Echo Request (data size 9) | KeepAlive (pattern 0×1) |
Server | Client | Echo Reply (data size 9) | SendFile (to server) Command (data 0×6) |
Client | Server | Echo Request (data size 1024) | ReceiveData (pattern 0×3) |
Server | Client | Echo Reply (data size 1024) | Send File Name (PingData**) |
Client | Server | Echo Request (data size 24) | SendData (pattern filecontents) |
……………………………………… | (repeat until EOF)*** | ||
Client | Server | Echo Request (data size <=24) | SendData (pattern filecontents) |
Execute command in client | |||
Client | Server | Echo Request (data size 9) | KeepAlive (pattern 0×1) |
Server | Client | Echo Reply (data size 9) | Execute (in client) Command (data 0×7) |
Client | Server | Echo Request (data size 1024) | ReceiveData (pattern 0×3) |
Server | Client | Echo Reply (data size 1024) | Send Command line (PingData**) |
Client | Server | Echo Request (data size 24) | SendData (pattern command result) |
……………………………………… | (repeat until EOF)*** | ||
Client | Server | Echo Request (data size <=24) | SendData (pattern command result) |
* the first 8 data bytes in the ICMP data field are used by ping for timestamps. | ** a PingData packet is a packet that consists in a 2 byte header with data size followed by the data itself. The reason for this is that an echo reply must have at least the same size of the request regardless of the actual data size we want to transmit.t | *** Any valid server echo reply works in this case, for example, an usual echo reply packet. The client is only interested in sending the data back to the server. |
Improvements
The previous example shows how one can use the standard ping utility to communicate to a remote server. It provides a simple protocol to achieve its proposed goals.
There a several improvements, in a real world scenario, that could be taken into account. Given this, I will highlight three possible improvements.
- 1. Solidify and expand the communications protocol and features
- 2. Add compression. The upstream from the client is 16 bytes per packet and the downstream is theoretically 64kb (in the example 1kb is used)
- 3. Add encryption. Private key encryption is a must to hide traffic contents.
Several Considerations
- As mentioned before, the upstream from the client is 16 bytes per packet and the downstream is theoretically 64kb, but in the example 1kb is used. The reason for this is that are several routers that drop fragmented ping packets. 1Kb was chosen because it is usually smaller than most routers MTU.
- The server ICMP echo reply must be, at least, the same size of the echo request, otherwise the ping utility does not show the packet content, only a packet truncated message.
- Regardless of the reply data, the bytes displayed by the ping utility at the client are the size of the request, other bytes are discarded.
- The ping utility behaves a bit strangely when building packets with a given pattern. Basically it builds the data payload with repetitions of the pattern and only after it overwrites the first 8 bytes with timestamps. This may confuse the developer when implementing the protocol, since the pattern has to be properly aligned in order to get to the server in an expected way.
Attached Code
The attached code can be seen as a test-toolkit. It is a proof of concept only to show it is possible to transfer even more data through the ping channel back on the Android device. The package includes the following:
- APK Eclipse Project for building a ready to go APK
- Python Script for interacting with the APK
- Shellscripts bound to the icmp.py script for pre defined actions
Btw., the serverside could have been implemented with hping as well, but it was more fun to do it in python with raw sockets.
APK_Source – the sourcecode to compile with Eclipse
PingTunnel-server – the python code and shellscripts for your linux box