This article is contributed. See the original author and article here.

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.


Understanding false positives


In most cases, false positives stem from specific entities such as users or IP addresses which should be excluded.  Common scenarios are:

  • During his normal activity, a user may often exhibit a pattern that can be viewed as suspected. This would often be a service principal.

  • An intentional security scanning activity coming from known IP addresses is often detected as malicious. 

  • A rule excludes private IP addresses. However, some internal IP addresses are not private and should also be excluded. 


Implementing false positive handling


The solution is to modify the rule queries, 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, you can add the blue line at the beginning of the query:


let timeFrame = 1d;
let logonDiff = 10m;
| where TimeGenerated >= ago(timeFrame)
| where IPAddress in (‘’, ‘’)


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:


| where IPAddress in (‘’, ‘’)
| where UserPrincipalName == ‘’ 


Or, to implement a more fine-grained exception when applicable, to reduce the chance for false negatives, by combining attributes:


  | where IPAddress == ‘’ and UserPrincipalName == ‘’


Excluding subnets


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) [ “”, “”, …];
let timeFrame = 1d;
let logonDiff = 10m;
| where TimeGenerated >= ago(timeFrame)
| evaluate ipv4_lookup(subnets, IPAddress, network, return_unmatched = true)
| where not(isempty(network))
| where ResultType == “0”


Using Watchlists to handle false positives outside of the rule itself


You can use a Watchlist to manage the list of IP addresses outside of the rule itself. When applicable, this is the preferred solutions and has several advantages:

  • This enables an analyst to add exceptions without editing the rule, which better follows SOC best practices.

  • The same watchlist can apply to multiple rules, enabling central exception management.


Using a watchlist is rather similar to using a direct exception:


let timeFrame = 1d;
let logonDiff = 10m;
let allowlist = (_GetWatchlist(‘ipallowlist’) | project IPAddress);
| 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!


Brought to you by Dr. Ware, Microsoft Office 365 Silver Partner, Charleston SC.

%d bloggers like this: