A protocol tunnel uses a particular protocol to tunnel data between two end points. The data can be encapsulated or encoded within the protocol payload so that a legitimate protocol communication takes place. Data Exfiltration is one of the usages of protocol tunnels; data Exfiltration refers to smuggling (sensitive) data out of a particular network or host. Such data can be files, network packets, etc. During the Exfiltration process, there is more traffic from inside to outside than there is from outside to inside.
There have been a number of ways to tunnel and Exfiltration data. For example, HTTP protocol can be used for such operation. Also, protocols like ICMP can be used to carry arbitrary data. An ICMP Echo request packet generated by a Windows machine carries the data “abcdefghijklmnopqrstuvwabcdefghi”. Another protocol used to tunnel and exfiltration data is DNS. DNS packets can carry alphanumeric encoded data as part of the hostnames (e.g. abcdefghijklmnopqrstuvwxyz.destination.com)
I was thinking recently about the NTP protocol and how it can also be used to tunnel data. An NTP packet contains four 4 64-bit timestamp fields; each field is in the following format:
0 1 2 3
01234567890123456789012345678901
+++++++++++++++++++++++++++++++++
| Integer Part |
+++++++++++++++++++++++++++++++++
| Fraction Part |
+++++++++++++++++++++++++++++++++
According to RFC 958, “NTP timestamps are represented as a 64-bit fixed-point number, in seconds relative to 0000 UT on 1 January 1900. The integer part is in the first 32 bits and the fraction part in the last 32 bits, as shown in the following diagram.” This means that every field can range from 0x0000000000000000 to 0xFFFFFFFFFFFFFFFF.
The only drawback here is that one packet can carry up to 32 bytes of data which is too little to transfer huge chunk of data. However, this approach can be used to carry small, yet sensitive, data such as shell commands. For example, an attacker can have an interactive shell transferring and executing commands on the compromised system using NTP Tunnel.
For example, to send the command “ls –l”, it can be inserted in a timestamp field as follows:
00 6c 73 20 2d 6c 00 00
Which will be interpreted as:
Apr 29, 2036 12:44:16.1774 UTC
One of the traditional methods of any exploit is to pass a “shellcode” that spawns a shell. The attacker then would have a remote shell over TCP stream. The way to spawn a shell, not necessary through a shellcode but in any general way, is done by executing the following function:
char *str[] = {“/bin/sh”};
execve( “bin/sh”, str, NULL);
Executing this will simply spawns an interactive shell. If this was executed locally, the input and output streams are the standard input (stdin) and the standard output (stdout). However, when it is executed remotely, the input and output streams are piped to the TCP stream.
However, what if a user wants to have a local program running and executing commands received remotely, or from an input stream other than ‘stdin’ ? there are various proposed ways to do that. Looking at the exec() family (i.e. execl, execlp, execv, execvp, and execve), these functions do not give the user a control over the input stream or output stream, they only return a status code indicating success or failure. On the other hand, there is the popen() function which actually executes a command while giving the user a file descriptor to either write input or read output of the command. For example, the following code snippet lets the user execute the command “ls –l” and get the output within the program:
FILE *fd;
fd = popen( “ls –l”, “r” );
while( fgets(line, sizeof line, fd) )
printf(“%s”, line);
Such piece of code would be handy to use in a program that receives commands remotely from a user, or locally from a file, and pipes the output to whatever the user wants. However, there is one drawback to such implementation, that is, a command like “cd” will not work, and the user will not be able to navigate between directories. So, in order to have a full interactive shell, the command that needs to be executed is the shell itself, i.e. “sh”. But now we face another problem, running “sh” from popen() function will actually spawns a shell where its input and output are bound to stdin and stdout, and we will not be using the piping functionality provided by pipe.
The best way to run a fully interactive shell where its input and output are controlled by the user is to execute “sh” by one of the exec() functions and at the same take control of the stdin and stdout through the use of pipes; typically, two pipes are needed. The following diagram simplifies the description:
----------------- | | ----------------- --> pipe1 --> > /bin/sh > --> Pipe2 --> ----------------- | | -----------------
The steps to implement this are as follows:
1] Create two pipes (p1 and p2) and two FILE pointers (ptr1 and ptr2).
2] Fork a child process [pid=fork()].
3] The child process takes control of stdin and stdout by associating them with the reading-end of the first pipe and the writing-end of the second pipe, respectively.
4] The child process spawns a shell (“/bin/sh”) using an execlp() function.
5] The parent process associates the file descriptors with the writing-end of the first pipe and with the reading-end of the second pipe.
6] Anything written to the first file descriptor will be passed as input to the running interactive shell; and any results from the interactive shell can be read from the second file descriptor.
...
int p1[2], p2[2];
FILE *ptr1, ptr2;
pipe(p1); pipe(p2);
pid=fork;
if( pid == 0 ){
close(0); /* close the stdin */
dup(p1[0]); /* reading-end of pipe1 takes
control of stdin */
close(1); /* close the stdout */
dup(p2[1]); /* writing-end of pipe2 takes
control of stdout */
execlp(“/bin/sh”, “sh”, NULL, NULL)
}
ptr1 = fdopen( p1[1], “w” ); /* writing-end of pipe1 */
ptr2 = fdopen( p2[0], “r” ); /* reading-end of pipe2 */
fprintf( ptr1, “ls –l” );
while( fgets( line, 50, ptr2) ) printf(“%s”, line);
...
In this case, the user has an interactive shell with cd-ing and also can control the input and output stream.
References:
- Popen specification
- Fork, Exec and Process control
- Using the UNIX Pipe in C
Some people from the security community have commented on my tool DNS MRE (Multiple Race Exploiter). HD Moore, the original author of Metasploit Project, has pointed out the uniqueness of this tool in that it can poison/overwrite the DNS cache by utilizing a CNAME record in the answer. He also noted the static TTL used in all fake replies which can make an IDS/IPS signature. Tahir from HatSecurity has pointed the same thing about the static TTL …
Thanks for that;
The next version will contain the following features:
1- Automatic finding of Name Server IPs of the target domain. This only works if the attacked DNS server supports recursion. For DNS server configured with forwarder, the user (attack/pentester) has to manually find the forwarder IP.
2- Randomized TTL values in all replies. Or the user can set the TTL value for all the replies
3- A better algorithm to attack "patched" system, that is, poisoning a patched system in the shortest possible time. This can take the following format:
* There is no sleep() between iterations
* There is no sleep() between query and reply (maybe except the first iteration)
* Sending Multiple queries before sending their corresponding replies.
4- Concerning the source IP addrss of the replies, the user should choose between:
* Using the local IP address
* Using static spoofed IP address
* Using dynamic spoofed IP addresses
5- Poisoning a DNS Server that sends a DNS query with Additional RR of DNSSEC (the server is saying it's willing to accept DNSSEC but is not required)