ModSecurity WAF using a Whitelist Approach

Description

A Web Application Firewalls usually detects and prevents attacks like SQL injection. It achieves that by using regular expression to filter potential harmful strings. A common setup is using ModSecurity as a plugin for Apache in combination with the OWASP Core Rule Set. Initially you use a "training phase" to adapt the rule set to your web application. Or basically, fix all the false positives.

We implemented a different approach for a customer, that still suffered from False Positives. Most concepts are using a blacklist of characters or strings that they filter out or block. But it is also possible to implement a whitelist approach, defining what characters are valid for each input field.

In this specific customer case, the software package build process also creates the whitelist ruleset for ModSecurity: The development team creates a definition file of software endpoints, parameters, and input types. During the build, a translator compiles this into regular expressions to only allow secure data passing through the WAF.

Such a whitelist ruleset could look like the following example:

SecRule REQUEST_HEADERS:Host "^[\d\.]+$" "id:1000001,log,deny,msg:'BLOCK: Host header must not be a IPv4 address'"
SecRule REQUEST_HEADERS:Host "^[0-9a-f]{1,4}:" "id:1000002,log,deny,msg:'BLOCK: Host header must not be a IPv6 address'"

# Validate filename
SecRule REQUEST_FILENAME "!^[-./_A-Za-z0-9]{1,100}$" "id:1000003,log,deny,msg:'BLOCK: Malformed filename request'"

# Validate stores
SecRule REQUEST_FILENAME "!(^/endpoint1)" "id:1000004,log,deny,msg:'BLOCK: Store not allowed'"

# Validate URL /endpoint1
SecRule REQUEST_URI "@beginsWith /endpoint1" "id:1000005,nolog,noauditlog,setvar:tx.store=0"
SecRule TX:STORE "@eq 0" "id:1000006,chain,deny,msg:'BLOCK: Request method not allowed.'"
  SecRule REQUEST_METHOD "!^POST$" "log,t:urlDecode"
SecRule TX:STORE "@eq 0" "id:1000007,chain,deny,msg:'BLOCK: Argument not allowed on /endpoint1'"
  SecRule ARGS_NAMES "!^cid|msg$" "log,t:urlDecode"
SecRule TX:STORE "@eq 0" "id:1000008,chain,deny,msg:'BLOCK: Invalid parameter cid on /endpoint1'"
  SecRule ARGS:cid "!(^$|^[0-9]+$)" "log,t:urlDecode"
SecRule TX:STORE "@eq 0" "id:1000009,chain,deny,msg:'BLOCK: Invalid parameter msg on /endpoint1'"
  SecRule ARGS:msg "!(^$|^[a-zA-Z]+$)" "log,t:urlDecode"

The example ruleset above will check for the following criteria:

  • The HTTP-Host header must not be a IPv4 or IPv6 address.
  • The URL endpoint must only contain alphanumeric and some special characters.
  • Only the URL endpoint /endpoint1 is allowed.
  • Only the method POST is allowed.
  • Only the two parameters" %} cid and msg are allowed.
  • The parameter cid must only contain numbers.
  • The parameter msg must only contain lower and uppercase letters.
If one of the checks above fails, the request is blocked.

back to projects
  • ModSecurity
  • WAF
  • Web Application Firewall