StealthTalk - Login outside work zone
| Id | a7c3e9b1-4f5d-4e2a-9b8c-1d2e3f4a5b6c |
| Rulename | StealthTalk - Login outside work zone |
| Description | Identifies a single StealthTalk authentication originating from a country or city that does not match the user’s assigned (expected) geographic zone. Each individual mismatch is treated as an incident - there is no aggregation threshold, since a single login from an unexpected country is high-confidence evidence of a credential issue. An incident fires when LoginCountry differs from AssignedCountry OR LoginCity differs from AssignedCity. Source IPv4, raw event ID, and both the observed and expected geo-locations are surfaced as entities and custom details for the SOC analyst. |
| Severity | High |
| Tactics | InitialAccess DefenseEvasion CredentialAccess |
| Techniques | T1078 |
| Required data connectors | StealthTalkAnomalousAuth |
| Kind | Scheduled |
| Query frequency | 15m |
| Query period | 1h |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/StealthTalk/Analytic Rules/LoginOutsideWorkZone.yaml |
| Version | 1.0.0 |
| Arm template | a7c3e9b1-4f5d-4e2a-9b8c-1d2e3f4a5b6c.json |
let LookbackPeriod = 1h;
StealthTalkAnomalousAuth_CL
| where TimeGenerated >= ago(LookbackPeriod)
| where EventType == "GeoAnomalyLogin"
| where LoginCountry != AssignedCountry
or LoginCity != AssignedCity
| extend
CountryMismatch = LoginCountry != AssignedCountry,
CityMismatch = LoginCity != AssignedCity,
AlertName = "LoginOutsideWorkZone",
AlertDetails = strcat(
"User ", UserId,
" logged in from ", LoginCity, " (", LoginCountry, ")",
" - assigned zone: ", AssignedCity, " (", AssignedCountry, ").",
" Source IP: ", IpAddress, ".",
" Country mismatch: ", tostring(LoginCountry != AssignedCountry), ".",
" City mismatch: ", tostring(LoginCity != AssignedCity), "."
)
| project
TimeGenerated, UserId, DeviceId,
LoginCountry, LoginCity, AssignedCountry, AssignedCity,
CountryMismatch, CityMismatch, IpAddress,
AppVersion, RawEventId, AlertName, AlertDetails
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: UserId
- entityType: Host
fieldMappings:
- identifier: HostName
columnName: DeviceId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IpAddress
tactics:
- InitialAccess
- DefenseEvasion
- CredentialAccess
suppressionEnabled: false
suppressionDuration: 1h
requiredDataConnectors:
- dataTypes:
- StealthTalkAnomalousAuth_CL
connectorId: StealthTalkAnomalousAuth
alertDetailsOverride:
alertDisplayNameFormat: 'StealthTalk: Login Outside Work Zone - {{UserId}} from {{LoginCity}} ({{LoginCountry}})'
alertDescriptionFormat: '{{AlertDetails}}'
incidentConfiguration:
groupingConfiguration:
reopenClosedIncident: false
lookbackDuration: 5h
groupByEntities:
- Account
enabled: true
matchingMethod: Selected
createIncident: true
id: a7c3e9b1-4f5d-4e2a-9b8c-1d2e3f4a5b6c
severity: High
status: Available
customDetails:
AssignedCity: AssignedCity
AppVersion: AppVersion
LoginCountry: LoginCountry
AssignedCountry: AssignedCountry
EventReference: RawEventId
CountryMismatch: CountryMismatch
LoginCity: LoginCity
CityMismatch: CityMismatch
query: |
let LookbackPeriod = 1h;
StealthTalkAnomalousAuth_CL
| where TimeGenerated >= ago(LookbackPeriod)
| where EventType == "GeoAnomalyLogin"
| where LoginCountry != AssignedCountry
or LoginCity != AssignedCity
| extend
CountryMismatch = LoginCountry != AssignedCountry,
CityMismatch = LoginCity != AssignedCity,
AlertName = "LoginOutsideWorkZone",
AlertDetails = strcat(
"User ", UserId,
" logged in from ", LoginCity, " (", LoginCountry, ")",
" - assigned zone: ", AssignedCity, " (", AssignedCountry, ").",
" Source IP: ", IpAddress, ".",
" Country mismatch: ", tostring(LoginCountry != AssignedCountry), ".",
" City mismatch: ", tostring(LoginCity != AssignedCity), "."
)
| project
TimeGenerated, UserId, DeviceId,
LoginCountry, LoginCity, AssignedCountry, AssignedCity,
CountryMismatch, CityMismatch, IpAddress,
AppVersion, RawEventId, AlertName, AlertDetails
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/StealthTalk/Analytic Rules/LoginOutsideWorkZone.yaml
kind: Scheduled
queryPeriod: 1h
version: 1.0.0
name: StealthTalk - Login outside work zone
queryFrequency: 15m
triggerThreshold: 0
relevantTechniques:
- T1078
description: |
Identifies a single StealthTalk authentication originating from a country or city that does
not match the user's assigned (expected) geographic zone. Each individual mismatch is
treated as an incident - there is no aggregation threshold, since a single login from an
unexpected country is high-confidence evidence of a credential issue.
An incident fires when LoginCountry differs from AssignedCountry OR LoginCity differs
from AssignedCity. Source IPv4, raw event ID, and both the observed and expected
geo-locations are surfaced as entities and custom details for the SOC analyst.
triggerOperator: gt