Reputation: 821
I have the following KQL query built out. I want to only show IPs that are not within the whitelisted subnets at the top.
When I run this I still get the whitelisted subnets in the results. Am I missing something?
let lookup=toscalar(datatable(ip_range:string) ["'X.X.0.0/16', 'X.X.0.0/16" , "X.X.0.0/16" , "X.X.0.0/16"] | summarize l=make_set(ip_range));
CommonSecurityLog
| search *
| extend dIPresult = ipv4_is_private(DestinationIP)
| where DeviceVendor == "Fortinet"
| where AdditionalExtensions !contains "dstcountry=United States"
| where DeviceAction !in~ ("close","server-rst","deny","timeout","client-rst")
| where DestinationPort > 1024 and isnotempty(DestinationPort)
| where dIPresult == false
| where ipv4_is_private(SourceIP)
| mv-apply l=lookup to typeof(string) on (where not(ipv4_is_match(DestinationIP, l)))
| summarize count() by ['DestinationIP'] | sort by count_
Upvotes: 0
Views: 493
Reputation: 108
So your first line has some mix of double/single quotes that I expect is just a copy/paste error, and also lookup
is a KQL keyword so that probably isn't helping.
But I'm pretty sure your issue is your use of the mv-apply
function. From the docs:
The mv-apply operator has the following processing steps:
- Uses the mv-expand operator to expand each record in the input into subtables (order is preserved).
- Applies the subquery for each of the subtables.
- Adds zero or more columns to the resulting subtable. These columns contain the values of the source columns that aren't expanded, and are repeated where needed.
- Returns the union of the results.
So each IP is compared using where not (ipv4_is_match())
against a subtable containing the 3 whitelisted subnets X,Y,Z. If the IP is in subnet X then the whitelist will be applied for that comparison but then it also compares against subnets Y and Z and in those cases the check fails. The results of all three checks get unioned at the end.
Here's a simpler version that's easier to follow
let lookuptable=datatable(ip_range:string) ["10.0.0.0/8", "192.168.0.0/16", "192.168.1.0/24"]
| summarize l=make_set(ip_range);
datatable(IP:string) ["172.16.0.1","10.0.0.1", "192.168.1.1"]
| mv-apply SubnetWhitelist=toscalar(lookuptable) to typeof(string) on (where not(ipv4_is_match(IP, SubnetWhitelist)))
You can see the first IP 172... isn't in any of the whitelists but since the results get unioned it actually shows up 3 times. The 10... IP is in the 10/8 range so that one check gets filtered out. the 192... matches 2 filters but the one it doesn't match still makes it through.
IP | SubnetWhitelist |
---|---|
172.16.0.1 | 10.0.0.0/8 |
172.16.0.1 | 192.168.0.0/16 |
172.16.0.1 | 192.168.1.0/24 |
10.0.0.1 | 192.168.0.0/16 |
10.0.0.1 | 192.168.1.0/24 |
192.168.1.1 | 10.0.0.0/8 |
Upvotes: 1