id: 66fb97d1-55c3-4268-ac22-b9742d0fdccc name: Rare domains seen in Cloud Logs description: | 'This will identify rare domain accounts accessing or attempting to access cloud resources by examining the AuditLogs, OfficeActivity and SigninLogs Rare does not mean malicious, but it may be something you would be interested in investigating further Additionally, it is possible that there may be many domains if you have allowed access by 3rd party domain accounts. Lower the domainLimit value as needed. For example, if you only want to see domains that have an access attempt count of 2 or less, then set domainLimit = 2 below. If you need to set it lower only for a given log, then use customLimit in the same way and uncomment that line in the script.' requiredDataConnectors: - connectorId: AzureActiveDirectory dataTypes: - SigninLogs - AuditLogs - connectorId: Office365 dataTypes: - OfficeActivity tactics: - InitialAccess - Discovery - Collection relevantTechniques: - T1190 - T1087 - T1114 query: | // Provide customLimit value with default above domainLimit value so it will not block unless changed let customLimit = 11; let domainLimit = 10; let domainLookback = union isfuzzy=true (AuditLogs | extend UserPrincipalName = tolower(tostring(TargetResources.[0].userPrincipalName)) // parse out AuditLog values for various locations where UPN could be | extend UserPrincipalName = iff(isnotempty(UserPrincipalName), UserPrincipalName, iif((tostring(InitiatedBy.user.userPrincipalName)=='unknown'), extract("Email: ([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+)", 1, tostring(parse_json(TargetResources)[0].displayName)), InitiatedBy.user.userPrincipalName)) | where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY" | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | where isnotempty(RareDomain) | summarize RareDomainCount = count() by Type, RareDomain | where RareDomainCount <= domainLimit | extend AccountCustomEntity = UserPrincipalName // remove comment from below if you would like to have a lower limit for RareDomainCount specific to AuditLog //| where RareDomainCount <= customLimit ), (OfficeActivity | extend UserPrincipalName = tolower(UserId) | where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY" | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | summarize RareDomainCount = count() by Type, RareDomain | where RareDomainCount <= domainLimit | extend AccountCustomEntity = UserPrincipalName // remove comment from below if you would like to have a lower limit for RareDomainCount specific to OfficeActivity //| where RareDomainCount <= customLimit ), (SigninLogs | where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY" | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | summarize RareDomainCount = count() by Type, RareDomain | where RareDomainCount <= domainLimit // remove comment from below if you would like to have a lower limit for RareDomainCount specific to SigninLogs //| where RareDomainCount <= customLimit ); let AuditLogsRef = domainLookback | join ( AuditLogs | extend UserPrincipalName = tolower(tostring(TargetResources.[0].userPrincipalName)) | extend UserPrincipalName = iff(isempty(UserPrincipalName), tostring(InitiatedBy.user.userPrincipalName), UserPrincipalName) | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | where isnotempty(RareDomain) | summarize UPNRefCount = count() by TimeGenerated, Type, RareDomain, UserPrincipalName, OperationName, Category, Result | extend AccountCustomEntity = UserPrincipalName ) on Type, RareDomain; let OfficeActivityRef = domainLookback | join ( OfficeActivity | extend UserPrincipalName = tolower(UserId) | where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY" | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | summarize UPNRefCount = count() by TimeGenerated, Type, RareDomain, UserPrincipalName, OperationName = Operation, Category = OfficeWorkload, Result = ResultStatus | extend AccountCustomEntity = UserPrincipalName ) on Type, RareDomain; let SigninLogsRef = domainLookback | join ( SigninLogs | extend UserPrincipalName = tolower(UserId) | where UserPrincipalName has "@" or UserPrincipalName startswith "NT AUTHORITY" | extend RareDomain = toupper(tostring(split(UserPrincipalName, "@")[-1])) | summarize UPNRefCount = count() by TimeGenerated, Type, RareDomain, UserPrincipalName, OperationName, Category = AppDisplayName, Result = ResultType | extend AccountCustomEntity = UserPrincipalName ) on Type, RareDomain; let Results = union isfuzzy=true AuditLogsRef,OfficeActivityRef,SigninLogsRef; Results | project TimeGenerated, Type, RareDomain, UserPrincipalName, OperationName, Category, Result, UPNRefCount | order by TimeGenerated asc | extend timestamp = TimeGenerated, AccountCustomEntity = UserPrincipalName