SOLVED

Search Incidents for entries from an IP Range

Brass Contributor

Hi,

I'm trying to perform some retrospective investigations and would like to be able to list any Sentinel Incident that contained an entity from a specific IP range.

I'm not great at KQL, so trying to figure it out - any assistance\pointers would be greatly appreciated & educational!!  Many thanks

 

**I've found one of the example queries I'm going to try and butcher and see what happens.  Will update if I solve it :)

7 Replies

@CodnChips Take a look at the KQL function "ipv4_is_in_range" ipv4_is_in_range() - Azure Data Explorer | Microsoft Docs   and see if that will work for you.

Hey Gary, thanks for your response.
Yes, I've stumbled across that and am trying to mash that up with the built in query for "Alerts involving a user" - but replacing the "user bits" with the IP address\host\entity

@CodnChips 

 

let rangeToCheck = "10.20.60.1/24";
SecurityAlert
| extend AlertEntities = parse_json(Entities)
| mv-expand AlertEntities
| where isnotempty(AlertEntities)
| where AlertEntities.Type == "ip"
| extend Entity = tostring(AlertEntities.Address)
| extend EntityType = tostring(AlertEntities.Type)
| distinct Entity, EntityType
| extend inRange = ipv4_is_in_range(Entity, rangeToCheck)

Amend line #1 to put the range you are looking for, gives you a true/false

Clive_Watson_0-1643197941991.png

 


 

Hi @Clive_Watson,
Thankyou very much for your code example - this is fantastic and educational.
I'd like to bolt on to this, the incident number & Title that the entity featured in.
Would I need to use a join - like this? (Not my code - taken from the pre-loaded queries):
AlertEvidence
| join AlertInfo on AlertId
| project Timestamp, AlertId, Title, Category , Severity , ServiceSource , DetectionSource , AttackTechniques

best response confirmed by CodnChips (Brass Contributor)
Solution

@CodnChips 

let rangeToCheck = "10.0.0.1/24";
SecurityIncident
| summarize arg_max(TimeGenerated,*) by IncidentNumber
| extend Alerts = extract("\\[(.*?)\\]", 1, tostring(AlertIds))
| mv-expand AlertIds to typeof(string)
| join 
(
    SecurityAlert
    | extend AlertEntities = parse_json(Entities)
    | mv-expand AlertEntities
    | where isnotempty(AlertEntities)
    | where AlertEntities.Type == "ip"
    | extend EntityIP = tostring(AlertEntities.Address)
    | extend EntityType = tostring(AlertEntities.Type)
    | extend inRange = ipv4_is_in_range(EntityIP, rangeToCheck)
) on $left.AlertIds == $right.SystemAlertId
| project IncidntName = Title, IncidentNumber=IncidentNumber, inRange, EntityIP, EntityType, AlertId = AlertIds, AlertName = AlertName
I reckon I'm in the wrong schema - going to try this one:
SecurityIncident

https://docs.microsoft.com/en-us/azure/sentinel/manage-soc-with-incident-metrics
WOOOAH - You've done it!!
That's is AMZING @Clive_Watson!!
Thanks so much - I will learn where I was going wrong (Everywhere!! :):):) )
1 best response

Accepted Solutions
best response confirmed by CodnChips (Brass Contributor)
Solution

@CodnChips 

let rangeToCheck = "10.0.0.1/24";
SecurityIncident
| summarize arg_max(TimeGenerated,*) by IncidentNumber
| extend Alerts = extract("\\[(.*?)\\]", 1, tostring(AlertIds))
| mv-expand AlertIds to typeof(string)
| join 
(
    SecurityAlert
    | extend AlertEntities = parse_json(Entities)
    | mv-expand AlertEntities
    | where isnotempty(AlertEntities)
    | where AlertEntities.Type == "ip"
    | extend EntityIP = tostring(AlertEntities.Address)
    | extend EntityType = tostring(AlertEntities.Type)
    | extend inRange = ipv4_is_in_range(EntityIP, rangeToCheck)
) on $left.AlertIds == $right.SystemAlertId
| project IncidntName = Title, IncidentNumber=IncidentNumber, inRange, EntityIP, EntityType, AlertId = AlertIds, AlertName = AlertName

View solution in original post