Skip to content

Instantly share code, notes, and snippets.

@soderlind
Last active May 20, 2025 16:16
Show Gist options
  • Save soderlind/772cd9a4b5c213c1ec16e79efe184c08 to your computer and use it in GitHub Desktop.
Save soderlind/772cd9a4b5c213c1ec16e79efe184c08 to your computer and use it in GitHub Desktop.
WordPress Web Application Firewall (WAF) Custom rules for Azure Front Door (AFD)

WordPress WAF Custom rules for Azure Front Door (AFD)

What the Bicep File Does

This Bicep file (waf-wordpress-exclusions.bicep) defines an Azure WAF policy specifically configured with rule exclusions for WordPress sites, based on the OWASP Core Rule Set - WordPress Rule Exclusions Plugin

Key Features

  1. Base WAF Policy Configuration:

    • Creates a WAF policy resource with configurable name and location
    • Supports both Detection and Prevention modes
    • Includes standard settings for request body checking and file upload limits
  2. OWASP Core Rule Set:

    • Implements OWASP CRS 3.2
    • Incorporates rule group overrides specifically for WordPress functionality
  3. WordPress-Specific Exclusions:

    • Implements exclusions for common WordPress features that trigger false positives
    • Includes exclusions for:
      • WordPress login forms
      • Comment submission
      • Admin post editing
      • WordPress Customizer
      • Gutenberg Editor
      • WordPress sessions and cookies

How to Use This File

  1. Deploy using Azure CLI:

    az deployment group create --resource-group YourResourceGroup --template-file waf-wordpress-exclusions.bicep
  2. Deploy using Azure PowerShell:

    New-AzResourceGroupDeployment -ResourceGroupName YourResourceGroup -TemplateFile waf-wordpress-exclusions.bicep
  3. You can customize parameters during deployment:

    az deployment group create --resource-group YourResourceGroup --template-file waf-wordpress-exclusions.bicep --parameters wafPolicyName=my-wordpress-waf wafMode=Detection
@description('Name of the WAF policy')
param wafPolicyName string = 'waf-wordpress-policy'
@description('Location for all resources.')
param location string = resourceGroup().location
@description('WAF mode. Detection or Prevention')
@allowed([
'Detection'
'Prevention'
])
param wafMode string = 'Prevention'
@description('Enable WAF rule set logging')
param enableLogging bool = true
// Define the WAF Policy resource
resource wordpressWafPolicy 'Microsoft.Network/ApplicationGatewayWebApplicationFirewallPolicies@2022-05-01' = {
name: wafPolicyName
location: location
properties: {
policySettings: {
requestBodyCheck: true
maxRequestBodySizeInKb: 128
fileUploadLimitInMb: 100
state: 'Enabled'
mode: wafMode
}
managedRules: {
// Define the OWASP Core Rule Set (CRS)
managedRuleSets: [
{
ruleSetType: 'OWASP'
ruleSetVersion: '3.2'
ruleGroupOverrides: [
// WordPress rule exclusions based on wordpress-rule-exclusions-before.conf
// WordPress Login Rule Exclusions
{
ruleGroupName: 'REQUEST-942-APPLICATION-ATTACK-SQLI'
rules: [
{
ruleId: '942430'
state: 'Disabled'
}
{
ruleId: '942431'
state: 'Disabled'
}
{
ruleId: '942432'
state: 'Disabled'
}
]
}
{
ruleGroupName: 'REQUEST-932-APPLICATION-ATTACK-RCE'
rules: [
{
ruleId: '932236'
state: 'Disabled'
}
]
}
{
ruleGroupName: 'REQUEST-931-APPLICATION-ATTACK-RFI'
rules: [
{
ruleId: '931130'
state: 'Disabled'
}
]
}
]
}
]
// WordPress Specific Exclusions
exclusions: [
// WordPress Login Forms
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'pwd'
}
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'redirect_to'
}
// WordPress Comments
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'author'
}
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'comment'
}
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'email'
}
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'url'
}
// WordPress Admin - Post Editing
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'content'
}
// WordPress Admin - URL handling
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: '_wp_http_referer'
}
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'wp_http_referer'
}
// WordPress Customizer
{
matchVariable: 'RequestArgNames'
selectorMatchOperator: 'Equals'
selector: 'wp_customize'
}
// Cookies
{
matchVariable: 'RequestCookieNames'
selectorMatchOperator: 'Equals'
selector: '_wp_session'
}
// Gutenberg Editor
{
matchVariable: 'RequestUri'
selectorMatchOperator: 'Contains'
selector: '/wp-json/wp/v'
}
// WordPress Admin
{
matchVariable: 'RequestUri'
selectorMatchOperator: 'Contains'
selector: '/wp-admin/'
}
]
}
}
}
// Output the resource ID of the WAF policy so it can be referenced later
output wafPolicyId string = wordpressWafPolicy.id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment