(Updated March 25th, 2021)
When using Azure Sentinel, you are bound to get some false positives. No detection rule is perfect. In this blog post, we will learn how to handle false positives in scheduled analytics rules.
Assuming that a detection rule is built correction, false positives often stem from specific entities such as users or IP addresses which should be excluded. Common scenarios include:
In this article, we learn how to resolve false positives using two methods:
Another important distinction is that Automation Rule based exceptions are often generated by analysts, while Alert Rule based exception is typically limited to SOC engineering.
The simplest way to add an exception is to use the "add automation rule" feature when viewing an incident that is a false positive:
Now that you defined when the rule triggers, you can continue to define what it does;
All you need to do now is press "apply," and the exception is active.
As an alternative, you can create an automation rule from scratch by selecting "automation" on the main left side menu and creating a new automation rule.
Another option is to modify the analytic rule query, either by including the exceptions directly in the rule, or preferably, when possible, including a reference to a watchlist and managing the exception list in the watchlist.
Taking the typical rule preamble. To implement an exception, you can add the blue line towards the beginning of the query:
let timeFrame = 1d;
SigninLogs
| where TimeGenerated >= ago(timeFrame)
| where IPAddress !in ('10.0.0.8', '192.168.12.1')
…
The relevant exception is not limited to IP addresses and might be for specific users (using the UserPrincipalName field) or Apps (using the AppDisplayName).
You can also exclude multiple attributes, excluding an alert that will include either the IP address 10.0.0.8 or the user "user@microsoft.com":
| where IPAddress !in ('10.0.0.8')
| where UserPrincipalName != 'user@microsoft.com'
To implement a more fine-grained exception when applicable, and reduce the chance for false negatives, combine attributes. This will create an exception only if both values appear in the same alert:
| where IPAddress != '10.0.0.8' and UserPrincipalName != 'user@microsoft.com'
The flexibility of in-query exceptions makes it the most complete solution for false positives, at the cost of rules modification.
The third use case described above, excluding IP ranges used by the organization, requires subnet exclusion. The following examples show how to exclude subnets. Note that since the ipv_lookup operator is an enrichment operator and not a filtering operator, the filtering is actually done in the following line by inspecting those events for which a match was not made.
let subnets = datatable(network:string) [ "111.68.128.0/17", "5.8.0.0/19", ...];
let timeFrame = 1d;
SigninLogs
| where TimeGenerated >= ago(timeFrame)
| evaluate ipv4_lookup(subnets, IPAddress, network, return_unmatched = true)
| where isempty(network)
…
You can use a Watchlist to manage the list of exceptions outside of the rule itself. When applicable, this is the preferred solutions and has several advantages:
Using a watchlist is rather similar to using a direct exception:
let timeFrame = 1d;
let logonDiff = 10m;
let allowlist = (_GetWatchlist('ipallowlist') | project IPAddress);
SigninLogs
| where TimeGenerated >= ago(timeFrame)
| where IPAddress !in (allowlist)
…
Subnets filtering can also be done using a watchlist by replacing in the subnets example above, the subnets table definition with a watchlist:
let subnets = _GetWatchlist('subnetallowlist');
I hope you found this useful!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.