-
Notifications
You must be signed in to change notification settings - Fork 939
Writing New WAF Checks
Pinaki Mondal edited this page Oct 27, 2019
·
1 revision
- Create a new python script in the plugins directory with the short-name of the check (e.g.
wafname.py
). - Use the template below to get started.
- Make modifications within the
is_waf
method so that it returnsTrue
if the WAF is detected, otherwise return False. - Test and test some more.
- Once happy with the results, you are welcome to submit a pull on GitHub.
That's all!
#!/usr/bin/env python
'''
Copyright (C) 2019, WAFW00F Developers.
See the LICENSE file for copying permission.
'''
NAME = 'WAF Name'
def is_waf(self):
schemes = [
# This part contains the checks needed to identify the WAF
self.matchHeader(('Header Field', 'Header Key')),
self.matchReason(503),
self.matchContent(r"Regex for identifying the WAF")
]
# Use any() if any of the checks can identify the WAF.
# Use all() if all the checks are needed to identify the WAF.
if any(i for i in schemes): # Replace any with all(i for i in schemes)
return True
return False
The following tips should help you in getting quickly up to scratch with adding new checks:
- Check the code in the
plugins
directory, some checks are very simple, others a bit more complex. - Sometimes, WAFs will simply reveal themselves all the time through some HTTP header.
- Other times, they will show themselves only when certain rules are triggered by the "attacks".
- Note that each HTTP request and response is cached so that the tool does not emit a huge amount of traffic.
- Group some fingerprints under diff. schemas to write the plugins if they don't match the
any()
orall()
criteria.
When creating new checks, you will normally want to make use of one of the following methods:
-
self.matchHeader(self, headermatch, attack=False)
Whereheadermatch
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 toTrue
, the matchHeader does not send the normal HTTP request, but instead sends a series of attack requests. -
self.matchStatus(self, statuscode, attack=True)
Wherestatuscode
is an integer value containing the status code returned for a simple malicious request. Setting theattack=False
will return the instance of a normal request. -
self.matchReason(self, reasoncode, attack=True)
Wherereasoncode
is an string value containing the response phrase/reason to be matched with the code returned for a simple malicious request. Setting theattack=False
will return the instance of a normal request. -
self.matchContent(self, regex, attack=True)
Whereregex
is an regular expression value containing the regex to be matched within the content returned for a malicious request. Setting theattack=False
will return the instance of a normal request. -
self.matchCookie(match)
Which is a shortcut forself.matchHeader(('set-cookie', match))
.
Note:
self.Request
and methods based on it (e.g.self.normalrequest()
and functions inattacks
) makes use ofrequests
library.
Last Updated - 27/10/2019 by @0xInfection
- Home - Welcome to WAFW00F Wiki!
- Getting Started - Getting started and setting up WAFW00F.
- Usage - Basic usage of WAFW00F.
- For Developers - Contributing new WAF plugins.
- Contributing - Making new pull requests.