Skip to content

How to write new WAF checks

Sandro Gauci edited this page Apr 1, 2017 · 4 revisions

Steps to becoming a wafw00f groupie

  1. Create a new python script in the plugins directory with the short-name of the check (e.g. wafname.py)
  2. Use the template below to get started
  3. Make modifications within the is_waf method so that it returns True if the WAF is detected, otherwise return False
  4. Test and test some more
  5. Once happy with the results, you are welcome to submit a pull on github

That's all!

Simple template for getting started

#!/usr/bin/env python

NAME = 'WAF Name'

def is_waf(self):
    return self.matchheader(('X-Powered-By-WAF', 'regex'))

Tips

The following tips should help you in getting quickly up to scratch with adding new checks:

  1. Check the code in the plugins directory, some checks are very simple, others a bit more complex
  2. Sometimes, WAFs will simply reveal themselves all the time through some HTTP header
  3. Other times, they will show themselves only when certain rules are triggered by the "attacks"
  4. Note that each HTTP request and response is cached so that the tool does not emit a huge amount of traffic

Exposed methods for your checks

When creating new checks, you will normally want to make use of one of the following methods:

  • self.matchheader(headermatch, attack=False, ignorecase=True), where headermatch is a tuple consisting of the header name (case insensitive) and a regular expression to match the value of the header, e.g. ('someheader','^SuperWAF[a-fA-F0-9]$'). If attack is set to True, the matchheader does not send the normal HTTP request, but instead sends the five attack requests. The value of ignorecase parameter determines if the regular expression match has a re.IGNORECASE flag or not.
  • self.matchcookie(match) which is a shortcut for self.matchheader(('set-cookie', match))

If you need more flexibility, the matchheader() function is making use of the following, which are also accessible from each check:

  • self.request(self, method='GET', path=None, usecache=True, cacheresponse=True, headers=None, comingfromredir=False)
  • self.attacks
  • self.normalrequest()

Note that self.request and methods based on it (e.g. normalrequest() and functions in attacks) makes use of httplib and returns an httplib.HTTPResponse object.

Clone this wiki locally
You can’t perform that action at this time.