Dynamic Defence Against Network Attacks (DYANA)

Keep out pleaseZXTM 5.0 allows you to call a customized version of Java's Servlet API from within TrafficScript™. In this article we'll show how you can dynamically change ZXTM's configuration by accessing the SOAP interface of the admin server from a Java Extension that is run when a TrafficScript rule detects a network attack.

For more background material on ZXTM's Java Extensions please consult the documents linked to at the end of this article.

The example we use is to look for requests containing attack attempts in TrafficScript and adding the IP address from which the attack originated to the list of banned IPs in Service Protection classes.

The number of attacks out there is huge (and growing) -- it's impossible to look at them all here. We'll pick just a single one for the purposes of this article, the dreaded abuse of the HTTP CONNECT method.

HTTP's CONNECT Method

You may not be familiar with this method, because the bulk of the HTTP requests on the internet consists of the more conventional GET, HEAD and POST methods. The CONNECT method was added later on and provides a mechanism for proxy-ing https connections. Basically, the proxy establishes a TCP connection to a remote site on the user's behalf and then simply forwards on packets between the client and the final destination. For details, please see the original specification.

There are, of course, legitimate uses of the CONNECT method. In fact, it can even be used together with ZXTM's forward proxy functionality to tunnel SSL traffic with ZXTM.

Abuses of CONNECT

While originally intended for SSL traffic, due to its very generic nature, the CONNECT method can be used to handle any type of TCP connection. In fact, since SSL traffic is incomprehensible for all intermediate nodes, the proxy has to be completely agnostic of the details of the packets it forwards. Therefore, also connections that are not using HTTPS can be proxied with the CONNECT method.

Most web-sites, of course, do not intend to provide SSL proxy functionality. Nevertheless, malicious users regularly try to trick unassuming servers into functioning as proxies. Why would they do that? One reason is to get around access restrictions. Mail servers, for example, usually have blacklists of IP addresses which have been used for sending SPAM in the past. Connections from these IPs will be closed straight away. This makes life harder for spammers. Today, most SPAM is not sent from the spammer's computer directly, but rather from hijacked machines. Spammers are, unfortunately, a rather clever breed and will go to great lengths to send their rubbish to as many recipients as possible. When they hijack a machine on the internet (often private Windows boxes without adequate protection), they will initially be able to use that machine for their evil intentions. Once word has spread that this machine is not to be trusted for SMTP traffic, the spammer has to go and find another machine. This not only involves extra work, chances are that most easy victims have already been captured by other spammers. Also, since home users are typically assigned dynamic IP addresses, it's rather likely that any IP address a machine is given by its ISP has at some time in the past been abused for spamming (you will have cursed this if you have ever tried to send an email directly from your private Linux PC). The machines that are usually not on this type of blacklist are servers with static IP addresses. Therefore, spammers are increasingly trying to make their SMTP connections appear to come from such trusted machines. The CONNECT method is every spammer's favorite HTTP extension. Here's how it works:

  1. Hijack an average Windows PC and install your spam software.
  2. Find an HTTP server which implements the CONNECT method naively in the sense of happily forwarding all connections from any machine to every machine.
  3. Point your spamware at that server and feed any amount of email to as many SMTP servers as you can.

There is some more background information about this attack on apache's wiki page.

ZXTM's answer - Part 1: TrafficScript™

ZXTM's TrafficScript programming language allows you to inspect the requests before they reach your backend servers. One of TrafficScript's functions is http.getMethod() which tells you the method used by a particular request. The following TrafficScript request rule will reject all CONNECT requests:

sub isAttack()
{
   $meth = http.getMethod();
   return string.icmp($meth, "CONNECT") == 0;
}

if( isAttack() ) {
   connection.close("HTTP/1.0 403 Forbidden\n");
}

We've used a subroutine, which is a new functionality introduced with version 5.0. Due to the simplicity of our attack detection code, it is not really necessary to create a dedicated subroutine in this case. But as mentioned previously, the proxy abuse we protect against is just one example of many attacks in the wild. Therefore, every administrator will extend the subroutine isAttack to cover as many scenarios as possible.

ZXTM's answer - Part 2: Service Protection classes

So we've established our first line of defence. The attacker's CONNECT attempts will not succeed. It is very likely, however, that after the first attempt from any given IP address others will follow because, as explained above, most attacks these days originate from compromised computers. ZXTM can help you against this threat of course. The Service Protection functionality lets you define a list of IP addresses from which not to accept connections. Add the offending computer to this list and ZXTM will block all subsequent CONNECT requests and other forms of attack before it even invokes a single TrafficScript rule. The following screen-shot from the Catalog-Protection-page shows the necessary configuration:

Service Protection Class Configuration

Setting this up, however, involves manual intervention of the ZXTM administrator and is therefore cumbersome, slow and error prone. Wouldn't it be nice if ZXTM could itself detect the attack and then automatically block the evil computer? Surely TrafficScript can check for the malign CONNECT method, but how do you forward the information about an attack to ZXTM's configuration?

ZXTM's answer - Part 3: Java Extensions

Enter Java Extensions, another new feature of ZXTM 5.0. With Java Extensions you can run arbitrary Java commands from inside ZXTM. One of the things you can do is make SOAP requests from a Java Extension. This can be used to access ZXTM's SOAP Control API. The details of how to use SOAP from Java are explained in another knowledgehub article. There you also find links to download the needed jar files. ZXTM's SOAP API lets you control almost every aspect of your traffic manager's behavior, including which IP addresses are in the blacklist of each individual Service Protection class.

Apart from the password of the admin user, our extension needs a few things to work:

  • The object over which SOAP calls for Protection classes will be made:
    private static CatalogProtectionPort cpport = null;
  • The object over which SOAP calls for Virtual Server classes will be made
    private static VirtualServerPort vsport = null;

The SOAP connections have to be initialized in the servlet's init() method, see the full source code for details.

Now let's have a look at the service() method:

   public void service( ServletRequest req, ServletResponse res )
   throws ServletException, IOException
   {
      try {
         ZXTMServletRequest zreq = (ZXTMServletRequest)req;
         String srcip = (String)zreq.getAttribute("srcip");
         String vsname = (String)zreq.getAttribute("virtualserver");
         if( null == srcip || null == vsname ) {
            return; // ZXTM closed this connection anyway
         }
         String[] vsnames = {vsname};
         String[] pnames = null;
         synchronized (vsport) {
            pnames = vsport.getProtection(vsnames);
         }
         if( pnames.length > 0 && pnames[0].length() > 0 ) {
            String[] protection = {pnames[0]};
            String[][] values = {{srcip}};
            synchronized (cpport) {
               cpport.addBannedAddresses(protection,values);
            }
         } else {
            // log(vsname + " has no protection classes");
         }
      } catch( Exception e ) {
         log("Exception in service: " + e.getMessage());
      }
   }

First the IP address and the name of the virtual server are retrieved from the ServletRequest object using ZXTM's extension of the Servlet API. This extension supplies you with a lot of extra information compared to what plain Servlets offer. In this case we extract the attributes 'srcip' and 'virtualserver'. Then we contact ZXTM's SOAP interface to find out the Service Protection class of the virtual server. If it has one, we construct the arguments for the SOAP call: For the first Service Protection class in the list, the new IP address is added to the 'banned IP' list. The actual SOAP call is protected against concurrent access.

The modification of the TrafficScript rule is very simple (assuming that the extension is called BlockAttack and resides in the Java package com.zeus.protection; the isAttack subroutine is unchanged from above):

if( isAttack() ) {
   java.run("com.zeus.protection.BlockAttack");
   connection.close("HTTP/1.0 403 Forbidden\n");
}

Rule processing pauses until the Java Extension has finished, then the negative reply is sent and the connection is closed.

There is a myriad of vulnerabilities and corresponding attacks; what we've picked here is just a simple example. It's a good idea to check your logs for attacks that have actually been directed to your site and extend the 'attack detection' function.

There is one improvement we should make: What happens on a system with 64 ZXTM child processes that is swamped with CONNECTs from the same IP? Naively employing the above Java Extension would probably overwhelm the admin server, because SOAP requests are rather heavy-weight. One way to avoid this problem is to have a class-wide set of blocked IP addresses in the extension:

   private static Set<String> bannedIPs =
      Collections.synchronizedSet(new HashSet<String>());

The first thing to do in the service() method then, is to check whether the IP we're about to block is already in this set. If it is, return immediately, if not, insert it and then make the SOAP call.

   if( !bannedIPs.add(srcip) ) {
      return;  // nothing to do for us
   }

For full details, you can download the full source code of the Java Extension.

Due to the dynamic assignment of IP addresses to customers by ISPs, the address we have just banned from accessing our site may tomorrow belong to another computer with a legitimate interest in our pages. An optional improvement to this extension is therefore to add a background thread that removes banned IPs after a configurable period of time using the removeBannedAddresses() method from the SOAP Control API.

Further Reading

michael [Zeus Dev Team] 03 October 2008  Permalink  
Leave a comment ...
Your email address will not be displayed.
Your URL will be displayed.
This public messageboard is not a forum for technical support. To report technical support problems, please contact our dedicated Support team using the instructions at the bottom of this page.
Options:
 
(Line breaks become <br />)
(Set cookies for name, email & url)
Download Free ZXTM Desktop Edition

Recent Articles

Other Resources



www.zeus.com