↳ Source GitHubRègle analytiqueMedium
GreyNoise TI Map IP Entity to SigninLogs
Description
'This query maps any GreyNoise IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in SigninLogs.'
- Type de règle
- Scheduled
- Version
- 1.0.1
- Fréquence
- 1h
- Période analysée
- 14d
- Déclenchement
- gt 0
Couverture MITRE déclarée
Sources déclarées
Métadonnées du fichier source. Aucune dépendance déduite du KQL.
Connecteurs
Types de données
Requête KQL
Requête originale, sans modification.
let dt_lookBack = 1h;
let ioc_lookBack = 14d;
let aadFunc = (tableName:string){
ThreatIntelligenceIndicator
| where TimeGenerated >= ago(ioc_lookBack)
| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId
| where Active == true and ExpirationDateTime > now()
| where SourceSystem == 'GreyNoise'
// Picking up only IOC's that contain the entities we want
| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)
// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.
// Taking the first non-empty value based on potential IOC match availability
| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)
| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)
// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated
| join kind=innerunique (
table(tableName) | where TimeGenerated >= ago(dt_lookBack)
| extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)
| extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails), StatusReason = tostring(Status.failureReason)
| extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)
// renaming time column so it is clear the log this came from
| extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type
)
on $left.TI_ipEntity == $right.IPAddress
| where SigninLogs_TimeGenerated < ExpirationDateTime
| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, IPAddress
| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,
TI_ipEntity, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, StatusReason, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type
| extend timestamp = SigninLogs_TimeGenerated, Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
union isfuzzy=true aadSignin, aadNonInt
Entités déclarées
Contenus associés
Liens établis à partir des identifiants déclarés et des manifests des solutions.
Traçabilité de la source
GitHubLes valeurs affichées proviennent des fichiers du dépôt Azure/Azure-Sentinel. Elles décrivent le modèle publié, pas la configuration de votre workspace.
- Commit
9800e51↗- Identifiant source
f6c76cc9-218c-5b76-9b82-8607f09ea1b4
GSTEP / SUIVI DU CATALOGUE
Ajouté au catalogue : 16 sept. 2026 · 05:49 UTC
Dernier changement observé : 16 sept. 2026 · 05:49 UTC