Detection rules › Kusto

Possible SignIn from Azure Backdoor

Severity
medium
Time window
1h
Group by
DomainName, InitiatedBy, UserDomain
Source
github.com/Azure/Azure-Sentinel

Identifies when a user adds an unverified domain as an authentication method, followed by a sign-in from a user the newly added domain. Threat actors may add custom domains to create a backdoor to your tenant. It's important to monitor whenever custom domains are added to the tenant.

MITRE ATT&CK coverage

TacticTechniques
Persistence

Telemetry coverage

Rules detecting the same action

These rules filter on the same operation.

Rule body

id: fa00014c-c5f4-4715-8f5b-ba567e19e41e
name: Possible SignIn from Azure Backdoor
description: |
  'Identifies when a user adds an unverified domain as an authentication method, followed by a sign-in from a user the newly added domain. Threat actors may add custom domains to create a backdoor to your tenant. It's important to monitor whenever custom domains are added to the tenant.'
severity: Medium
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - SigninLogs
      - AuditLogs 
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
relevantTechniques:
  - T1098
query: |
  // Microsoft Entra ID  Backdoors: Identity Federation
  //Ref: https://www.inversecos.com/2021/11/how-to-detect-azure-active-directory.html
  AuditLogs
  | where OperationName == "Add unverified domain"
  | where Result == "success"
  | extend InitiatedBy = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)
  | extend DomainName = tostring(TargetResources[0].displayName)
  | summarize DomainAddedTime = min(TimeGenerated), ModifiedProperties = make_set(parse_json(TargetResources[0].modifiedProperties),1048576) by InitiatedBy, DomainName
  | join kind=inner (
  SigninLogs
  | where ResultType == "0"
  | extend UserDomain = tostring(parse_json(split(UserPrincipalName,"@",1)[0]))
  | summarize SignInTime = min(TimeGenerated)  by UserPrincipalName, IPAddress, tostring(LocationDetails),AppDisplayName,ResourceDisplayName,UserDomain
  ) on $left.DomainName == $right.UserDomain
  // Getting UserName and Domain
  | extend Name = split(UserPrincipalName,"@",0), Domain = split(UserPrincipalName,"@",1)
  | mv-expand Name,Domain
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: NTDomain
        columnName: UserDomain
      - identifier: FullName
        columnName: UserPrincipalName
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: IPAddress
customDetails:
  AppDisplayName: AppDisplayName
  ResourceDisplayName: ResourceDisplayName
  DomainAdded: DomainName
  InitiatedBy: InitiatedBy
  ModifiedProperties: ModifiedProperties
  DomainAddedTime: DomainAddedTime
  SignInTime: SignInTime
version: 1.0.0
kind: Scheduled

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where OperationName == "Add unverified domain"

Stage 3: where

| where Result == "success"

Stage 4: extend

| extend InitiatedBy = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)

Stage 5: extend

| extend DomainName = tostring(TargetResources[0].displayName)

Stage 6: summarize

| summarize DomainAddedTime = min(TimeGenerated), ModifiedProperties = make_set(parse_json(TargetResources[0].modifiedProperties),1048576) by InitiatedBy, DomainName

Stage 7: join

| join kind=inner (
SigninLogs
| where ResultType == "0"
| extend UserDomain = tostring(parse_json(split(UserPrincipalName,"@",1)[0]))
| summarize SignInTime = min(TimeGenerated)  by UserPrincipalName, IPAddress, tostring(LocationDetails),AppDisplayName,ResourceDisplayName,UserDomain
) on $left.DomainName == $right.UserDomain

Stage 8: extend

| extend Name = split(UserPrincipalName,"@",0), Domain = split(UserPrincipalName,"@",1)

Stage 9: mv-expand

| mv-expand Name,Domain

Indicators

These rows show field, operator, and value matches.

Output fields

These fields are emitted when the rule matches.

FieldSource
DomainAddedTimesummarize
DomainNamesummarize
InitiatedBysummarize
ModifiedPropertiessummarize
Domainextend
Nameextend