Blocking the w00tw00t scanner with fail2ban

Protect your web server! Learn how to block the w00tw00t scanner using fail2ban by creating your own filters. A simple step-by-step guide.

Fail2Ban, right after installation, is ready to work with many of the most popular network services (including ssh, ftp, smtp, http(s), pop3, imap). However, you can't predict in advance the attacks that will appear in the future, and this is where the versatility of this tool shows. The second case is an application generating logs that aren't defined in the standard filters. We can create new filter definitions ourselves or look for them online.

A good example would be blocking the popular and equally annoying scanner w00tw00t.at.ISC.SANS.DFind:), which tests web servers (apache, nginx, lighttpd...) for security, or rather the lack thereof.

In this example, Nginx was used as the web server, but Apache would work equally well, since both have a compatible log format, unless we've changed the default format. If we do make such a change, we need to create the appropriate filtering rules ourselves.

Assuming we already have the Fail2Ban tool installed, adding a block for the scanner w00tw00t.at.ISC.SANS.DFind:) or w00tw00t.at.ISC.SANS.Win32:) comes down to a few steps:

  • We define the appropriate filter: nano /etc/fail2ban/filter.d/scanner-w00tw00t.conf and paste in the following content:
  • [Definition]
    
    # Option:  failregex
    # Notes.:  regex to match the w00tw00t scan messages in the logfile. The
    #          host must be matched by a group named "host". The tag "" can
    #          be used for standard IP/hostname matching.
    # Values:  TEXT
    failregex = ^ .*"GET \/w00tw00t\.at\.ISC\.SANS\..+\:\).*?"
    # Option:  ignoreregex
    # Notes.:  regex to ignore. If this regex matches, the line is ignored.
    # Values:  TEXT
    ignoreregex =
    
  • We create an entry called scanner-w00tw00t under HTTP servers in the [JAILS] section, in the file /etc/fail2ban/jail.local
  • #
    # HTTP servers
    #
    
    [apache]
    
    enabled = false
    port    = http,https
    filter  = apache-auth
    ...
    ...
    ...
    
    [scanner-w00tw00t]
    enabled  = true
    port      = http,https # or https if our web server listens on 443
    filter   = scanner-w00tw00t
    action   = iptables-allports[name=scanner-w00tw00t]
    #logpath  = /var/log/nginx/access.log
    logpath = /var/log/nginx/*.access.log
    maxretry = 1
    bantime  = 86400
    
  • A few words of explanation about the logpath option, which is responsible for the path to the log file. At first glance nothing complicated, but I've already run into a problem where fail2ban selectively blocked scanning of our server. The cause of this situation was splitting logs into separate files per virtual host / handling several domains. A common mistake is providing the main log file for nginx: access.log, when we want all the sites hosted on the server to be protected. The solution is to use the almost trivial regular expression: "*.access.log", which probably needs no further explanation.
  • After restarting fail2ban we check whether there were any errors by displaying the logs: cat /var/log/fail2ban; it should look roughly like this:
  • 2013-11-22 13:55:52,754 fail2ban.server : INFO   Exiting Fail2ban
    2012-12-12 12:12:12,372 fail2ban.server : INFO   Changed logging target to /var/log/fail2ban.log for Fail2ban v0.8.x
    2012-12-12 12:12:12,374 fail2ban.jail   : INFO   Creating new jail 'ssh'
    2012-12-12 12:12:12,374 fail2ban.jail   : INFO   Jail 'ssh' uses poller
    ...
    ...
    2012-12-12 12:12:12,632 fail2ban.jail   : INFO   Jail 'scanner-w00tw00t' uses poller
    2012-12-12 12:12:12,635 fail2ban.filter : INFO   Added logfile = /var/log/nginx/domain.com.access.log
    2012-12-12 12:12:12,637 fail2ban.filter : INFO   Added logfile = /var/log/nginx/subdomain1.domain.com.access.log
    2012-12-12 12:12:12,639 fail2ban.filter : INFO   Added logfile = /var/log/nginx/subdomain2.domain.com.access.log
    2012-12-12 12:12:12,641 fail2ban.filter : INFO   Added logfile = /var/log/nginx/domain.org.access.log
    2012-12-12 12:12:12,643 fail2ban.filter : INFO   Added logfile = /var/log/nginx/subdomain1.domain.org.access.log
    2012-12-12 12:12:12,648 fail2ban.filter : INFO   Added logfile = /var/log/nginx/subdomain2.domain.org.access.log
    2012-12-12 12:12:12,646 fail2ban.filter : INFO   Added logfile = /var/log/nginx/main.access.log
    2012-12-12 12:12:12,653 fail2ban.filter : INFO   Set maxRetry = 1
    2012-12-12 12:12:12,659 fail2ban.filter : INFO   Set findtime = 600
    2012-12-12 12:12:12,660 fail2ban.actions: INFO   Set banTime = 86400
    ...
    ...
    2012-12-12 12:12:12,689 fail2ban.jail   : INFO   Jail 'scanner-w00tw00t' started
    
  • Now all that's left is to test this solution, of course from a machine that isn't included in ignoreip. Having access to some other shell handy, just use the command: curl http://our_IP/w00tw00t.at.ISC.SANS.Win32:\) or use a browser on your phone. You'll of course observe the correct reaction in /var/log/fail2ban:
  • 2013-12-12 14:14:14,167 fail2ban.actions: WARNING [scanner-w00tw00t] Ban 80.50.50.200