(UB3.C2.K1 – Sign-in attempts from anywhere)

New Threat Detection: Monitoring Sign-In Attempts from Airport Networks

  1. Traveling Tracking: Utilize IP geolocation to assess the legitimacy of sign-in attempts. If an account experiences a sign-in from an airport, we can track them to verify if is traveling to risk countries where their users, device or data could be in risk.
let Airport_Data = externaldata(AirportName:string, maxLatitude: decimal, minLatitude:decimal, maxLongitude:decimal, minLongitude:decimal,iata:string, country: string,maxlatindicator:int)[@"https://raw.githubusercontent.com/Sergio-Albea-Git/Threat-Hunting-KQL-Queries/refs/heads/main/Security-Lists/Airport_polygon.csv"] with (format="csv", ignoreFirstRecord=True);
AADSignInEventsBeta
// filtering by just success sign attempts
| where ErrorCode == 0
| extend Latitude0 = todecimal(Latitude), Longitude0 = todecimal(Longitude)
| extend IntegerPart = toint(Latitude0)
| join kind=inner   (Airport_Data) on $left.IntegerPart == $right.maxlatindicator
| where Latitude0 < minLatitude and Latitude0 < maxLatitude and Longitude0 > minLongitude and Longitude0  < maxLongitude
| summarize make_set(AirportName),  make_set(country),dcount(AirportName) by AccountDisplayName
let AADTSErrorCode = externaldata(ErrorCode:int, Description:string)[@"https://raw.githubusercontent.com/Sergio-Albea-Git/Threat-Hunting-KQL-Queries/refs/heads/main/Security-Lists/AADSTS%20error%20codes.csv"] with (format="csv", ignoreFirstRecord=True);
let Airport_Data = externaldata(AirportName:string, maxLatitude: decimal, minLatitude:decimal, maxLongitude:decimal, minLongitude:decimal,iata:string, country: string,maxlatindicator:int)[@"https://raw.githubusercontent.com/Sergio-Albea-Git/Threat-Hunting-KQL-Queries/refs/heads/main/Security-Lists/Airport_polygon.csv"] with (format="csv", ignoreFirstRecord=True);
AADSignInEventsBeta
| extend Latitude0 = todecimal(Latitude), Longitude0 = todecimal(Longitude)
| extend IntegerPart = toint(Latitude0)
| join kind=inner   (Airport_Data) on $left.IntegerPart == $right.maxlatindicator
| where Latitude0 < minLatitude and Latitude0 < maxLatitude and Longitude0 > minLongitude and Longitude0  < maxLongitude
| join kind=inner ( AADTSErrorCode) on $left.ErrorCode == $right.ErrorCode
| summarize count() by ErrorCode, Description, AirportName, Country
let Airport_Data = externaldata(AirportName:string, maxLatitude: decimal, minLatitude:decimal, maxLongitude:decimal, minLongitude:decimal,iata:string, country: string,maxlatindicator:int)[@"https://raw.githubusercontent.com/Sergio-Albea-Git/Threat-Hunting-KQL-Queries/refs/heads/main/Security-Lists/Airport_polygon.csv"] with (format="csv", ignoreFirstRecord=True);
AADSignInEventsBeta
| extend Latitude0 = todecimal(Latitude), Longitude0 = todecimal(Longitude)
| extend IntegerPart = toint(Latitude0)
| join kind=inner   (Airport_Data) on $left.IntegerPart == $right.maxlatindicator
| where Latitude0 < minLatitude and Latitude0 < maxLatitude and Longitude0 > minLongitude and Longitude0  < maxLongitude
| summarize make_set(Application), make_set(ClientAppUsed) by  AirportName, IPAddress, AccountDisplayName
let Airport_Data = externaldata(AirportName:string, maxLatitude: decimal, minLatitude:decimal, maxLongitude:decimal, minLongitude:decimal,iata:string, country: string,maxlatindicator:int)[@"https://raw.githubusercontent.com/Sergio-Albea-Git/Threat-Hunting-KQL-Queries/refs/heads/main/Security-Lists/Airport_polygon.csv"] with (format="csv", ignoreFirstRecord=True);
AADSignInEventsBeta
| extend Latitude0 = todecimal(Latitude), Longitude0 = todecimal(Longitude)
| extend IntegerPart = toint(Latitude0)
| join kind=inner   (Airport_Data) on $left.IntegerPart == $right.maxlatindicator
| join kind=inner ( AlertEvidence) on $left.IPAddress == $right.RemoteIP
| where Latitude0 < minLatitude and Latitude0 < maxLatitude and Longitude0 > minLongitude and Longitude0  < maxLongitude
| summarize count() by AlertId, Country, IPAddress, DetectionSource, Title, AccountDisplayName