Whitelisting

Whitelisting is the process of resolving a false-positive by making an exception to the WAF rulset on a given WAF policy. It is one of the main tasks and activities around WAF in general.

NOTE: You should always have the approach of making the exception that would open the least possible holes into the WAF security. For example - you should strive to have the least possible Custom rules and make managed exception (or exclusion) to the WAF ruleset instead. And when making a managed exception to the ruleset, you shuold avoid making global or group level exceptions but target the specific Rule ID that is being triggered, also called individual exception. When doing an individual exception you should also avoid using Match variable and selector combinations that would let too much traffic, for example: RequestHeaders Equals host. We will try to warn you in these occasions.

In Azure WAF Manager, when you are examining the log, we will be let you know if we think a certain request is false-positive (to the best of our ability) and we will be suggesting what should be whitelisted for this particular block. One of the most useful features of Azure WAF Manager is that we provide a button which can make the exception directly to the WAF policy with single click.

Whitelisting diagram

Let's explode this further.

Whitelisting in the Azure Portal VS Azure WAF Manager

Azure Portal

If you were to work with the log and whitelist a false-positive from the Azure Portal. The steps you need to take are:

Step 1

Assuming that the Front Door is already sending WAF Logs to the Log Analytics workspace. Find the WAF logs by going to the Log Analytics workspace where logs are being sent and then construct a Kusto query to find the required logs and display them. Here is an example for drilling for Front Door WAF Logs:

AzureDiagnostics
// Last 1d
| where TimeGenerated >= ago(1d)
// Show Front Door WAF Logs
| where Category == "FrontdoorWebApplicationFirewallLog"
// Rename few columns to be better suited
| extend Rule = strcat(ruleName_s), ClientIP = strcat(clientIp_s, clientIP_s)
// Really you should be interested in blocked requests
| where action_s == "block"
// You want to filter out some columns to reduce the columns
| project TimeGenerated, policy_s, ResourceGroup, SubscriptionId, Rule, requestUri_s, ClientIP, details_matches_s,  trackingReference_s
// And you want to sort and see the newest first
| sort by TimeGenerated desc 

And you get a result like this:

TimeGenerated policy_s ResourceGroup SubscriptionId Rule requestUri_s ClientIP details_matches_s trackingReference_s
2023-15-1T09:51:39.6887434Z Gladiatus APPS 439efe26-9a97-420c-a1e1-0c941db1ffd8 Microsoft_DefaultRuleSet-1.1-RCE-932150 http://gladiatus.gamerz-bg.com:80/wp-plain.php 104.243.33.163 [{"matchVariableName": "CookieValue:g","matchVariableValue": "echo Sp3ctra"}] 20230115T080922Z-hdc0gg5r955wr4ud77qdftgemw0000000200000000001hbw
2023-15-1T11:50:39.6887434Z Diablo APPS 439efe26-9a97-420c-a1e1-0c941db1ffd8 Microsoft_BotManagerRuleSet-1.0-BadBots-Bot100200 https://www.diablo-2.net:443/apple-touch-icon.png 136.144.19.64 [{"matchVariableName": "HeaderValue:user-agent","matchVariableValue": "Firefox%20Focus/13915 CFNetwork/1402.0.8 Darwin/22.2.0"}] 20230115T051844Z-bnruq86uc11r582m9wra6mu2nn00000001vg000000002sst
2023-15-1T12:55:39.6887434Z Diablo APPS 439efe26-9a97-420c-a1e1-0c941db1ffd8 Microsoft_DefaultRuleSet-1.1-SQLI-942210 https://www.diablo-2.net:443/api/user/token?t=%7B%5Cid%3A%204%7D 193.43.93.23 [{"matchVariableName": "QueryParamValue:t","matchVariableValue":"{\id: 4}"}] 20230115T051844Z-agrruq86uc11r582m9wra6m52nn00000001vg000000002mmt

This is an example with very few log results. If you have hundreds/thousands of logs, you need to narrow down and you do that by excluding results from the query like this:

| where Rule <> "Microsoft_BotManagerRuleSet-1.0-BadBots-Bot100200"

And then drill down more and maybe you don't immediately recognize a false-positive because you are unaware of the app specifics.

You notice a false-positive - 3rd row. Time to whitelist it. Have in mind that this is an example for a false-positive that is really easy to spot and no further drilling down of the logs is required. However, this is most of the times not the case and you need to work hard to find the exception if you work entirely in Log Analytics interface.

Step 2

You leave the Log Analytics and head towards the WAF Policy itself. You find it, you go to Managed Rules, then you go to Manage exclusions. Now you go to +Add. You choose the SQLI Rule group and then you search in the dropdown for Rule with id 942210. Then you go and whitelist the MatchVariableName by placing a Query string args name Equals t. You save and wait for about a minute for the new exclusion to be saved.

Whitelist in Azure Portal

The challenges with this are the following:

  • You can see the source client IP address in the log but you don't know if the IP is good or bad
  • You don't immediately know if this IP has done other good or bad requests, therefore hard to make a decision if you should whitelist or not
  • If you have multiple WAF policies, you don't have a good overview of how many requests have been triggered without making extra Kusto queries.
  • Sometimes it's not very clear what exactly has been blocked and why
  • You need to keep multiple Azure portal tabs and switch between Log Analytics and the WAF policy blades
  • You don't have any suggestion of maliciousness in the pure log. No log enrichment.

Azure WAF Manager

We solve all of the above challenges in Azure WAF Manager. Here is how the same process goes if preformed from our portal:

Step 1

Go to the Dashboard and then choose Front Door WAF and click Fetch button. Front Door WAF This will query your own Log Analytics workspace, pull the Front Door WAF logs for the last 24 hours, enrich the log and display in a dashboard with multiple charts. It will also suggest which requests are flagged as false-positives.

Filter by Malicious Confidence 0 and whitelist it. Takes around a ~ second to apply to the WAF Policy (in contrast to ~1 minute from the Azure Portal) because the REST API is tens of times faster than the Azure Portal. Whitelisting example

That's it!

Extras

When you whitelist a certiain MatchVariable|selector from our portal, we do a little extra work to find out if that combination of MatchVariable|selector already exists. For example: let's say you are whitelisting a cookie called "theme" which you know can't be responsible for a SQL Injection. Knowing that it's not vulnerable to a SQL injection, you can whitelist this on the entire SQLI group level. If you have previous whitelists on that cookie for individual rule Ids under SQLI group, we will remove them to optimize the exclusions on the WAF policy. This can keep the exclusion count low and not get you close to the limit (100 for Front Door).

Previous - Go to - Reporting