96 строки
5.1 KiB
YAML
96 строки
5.1 KiB
YAML
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 |