Developer Notes

Fire extinguisher - photo by Piotr Chrobot on Unsplash

Manage WAF rules for Azure Application Gateway

Azure Application Gateway is a great way to shield your Azure APIs and WebApps from the big bad internet. The v2 WAF SKU includes powerful Web Application Firewall integration including protection against the common OWASP attacks. The built-in rules are a bit crude though and can cause false positives, resulting unintended blocking.

403 forbidden microsoft-azure-application-gateway/v2

Analysing WAF logs to find blocked requests

To find out what rules are causing request to be blocked I use the following KQL query:

AzureDiagnostics
| where Category == "ApplicationGatewayFirewallLog"
| where action_s == "Blocked" or action_s == "Matched"
| order by TimeGenerated
| project TimeGenerated, clientIp_s, hostname_s, requestUri_s, action_s, Message, details_message_s, ruleSetType_s, ruleId_s, details_file_s

The query lists all the relevant information you need to identify and resolve inadvertent blocking. In the Azure portal, open up the log tab on the App Gateway and execute the query. It should look something like this:

WAF rule query output
WAF rule query output

There are multiple requests here getting flagged for different reasons. Too many flags result in requests being block from that source.

Note the last two columns; they list the rule number and section. This will help locate the rules in the Azure Portal or to specify the correct rules in an ARM template.

Disable rules

Disabling OWASP rules without proper investigation is probably not a good idea, but some of the rules are... well... a bit crude and can match on things that you consider normal use of your application. For example, I've seen friendly URLs for products match SQL Injection rules. Missing HTTP Accept headers are not an uncommon thing either when 3rd parties integrate with your APIs. 

You can disable rules manually in the Azure portal and the query will help you find the right rules.

Disable WAF rules in the Azure Portal
Disable WAF rules in the Azure Portal

If you're deploying your infra as code, here's how to do that from an ARM template. To make the overrides reusable between different WAF rules I prefer putting them in the variables section:

"htmlOwaspRuleOverrides": [
    {
        "ruleGroupName": "REQUEST-932-APPLICATION-ATTACK-RCE",
        "rules": [
            {
                "ruleId": "932150",
                "state": "Disabled"
            }
        ]
    },
    {
        "ruleGroupName": "REQUEST-942-APPLICATION-ATTACK-SQLI",
        "rules": [
            {
                "ruleId": "942370",
                "state": "Disabled"
            },
            {
                "ruleId": "942210",
                "state": "Disabled"
            },
            {
                "ruleId": "942430",
                "state": "Disabled"
            },
            {
                "ruleId": "942440",
                "state": "Disabled"
            },
            {
                "ruleId": "942450",
                "state": "Disabled"
            }
        ]
    }
]

Then, under the managed rules, set the overrides:

"managedRules": {
    "exclusions": [],
    "managedRuleSets": [ 
        {
            "ruleSetType": "OWASP",
            "ruleSetVersion": "3.1",
            "ruleGroupOverrides": "[variables('htmlOwaspRuleOverrides')]"
        }
    ]
}

There's full ARM template in this gist