Detection rules › Kusto

Modified domain federation trust settings

Status
available
Severity
high
Time window
1d
Source
github.com/Azure/Azure-Sentinel

This will alert when a user or application modifies the federation settings on the domain or Update domain authentication from Managed to Federated. For example, this alert will trigger when a new Active Directory Federated Service (ADFS) TrustedRealm object, such as a signing certificate, is added to the domain. Modification to domain federation settings should be rare. Confirm the added or modified target domain/URL is legitimate administrator behavior. To understand why an authorized user may update settings for a federated domain in Office 365, Azure, or Intune, see: https://docs.microsoft.com/office365/troubleshoot/active-directory/update-federated-domain-office-365. For details on security realms that accept security tokens, see the ADFS Proxy Protocol (MS-ADFSPP) specification: https://docs.microsoft.com/openspecs/windows_protocols/ms-adfspp/e7b9ea73-1980-4318-96a6-da559486664b. For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.

MITRE ATT&CK coverage

TacticTechniques
PersistenceT1098 Account Manipulation
Privilege EscalationT1098 Account Manipulation
Credential AccessT1555 Credentials from Password Stores

Event coverage

Rule body kusto

id: 95dc4ae3-e0f2-48bd-b996-cdd22b90f9af
name: Modified domain federation trust settings
description: |
  'This will alert when a user or application modifies the federation settings on the domain or Update domain authentication from Managed to Federated.
  For example, this alert will trigger when a new Active Directory Federated Service (ADFS) TrustedRealm object, such as a signing certificate, is added to the domain.
  Modification to domain federation settings should be rare. Confirm the added or modified target domain/URL is legitimate administrator behavior.
  To understand why an authorized user may update settings for a federated domain in Office 365, Azure, or Intune, see: https://docs.microsoft.com/office365/troubleshoot/active-directory/update-federated-domain-office-365.
  For details on security realms that accept security tokens, see the ADFS Proxy Protocol (MS-ADFSPP) specification: https://docs.microsoft.com/openspecs/windows_protocols/ms-adfspp/e7b9ea73-1980-4318-96a6-da559486664b.
  For further information on AuditLogs please see https://docs.microsoft.com/azure/active-directory/reports-monitoring/reference-audit-activities.'
severity: High
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
status: Available
tactics:
  - CredentialAccess
  - Persistence
  - PrivilegeEscalation
relevantTechniques:
  - T1555
  - T1098
query: |
  (union isfuzzy=true
  (
  AuditLogs
  | where OperationName =~ "Set federation settings on domain"
  //| where Result =~ "success"   // commenting out, as it may be interesting to capture failed attempts
  | mv-expand TargetResources
  | extend modifiedProperties = parse_json(TargetResources).modifiedProperties
  | mv-expand modifiedProperties
  | extend targetDisplayName = tostring(parse_json(modifiedProperties).displayName)
  ),
  (
  AuditLogs
  | where OperationName =~ "Set domain authentication"
  //| where Result =~ "success"   // commenting out, as it may be interesting to capture failed attempts
  | mv-expand TargetResources
  | extend modifiedProperties = parse_json(TargetResources).modifiedProperties
  | mv-expand modifiedProperties
  | mv-apply Property = modifiedProperties on
    (
        where Property.displayName =~ "LiveType"
        | extend targetDisplayName = tostring(Property.displayName),
                 NewDomainValue = tostring(Property.newValue)
    )
  | where NewDomainValue has "Federated"
  )
  )
  | mv-apply AdditionalDetail = AdditionalDetails on
    (
        where AdditionalDetail.key =~ "User-Agent"
        | extend UserAgent = tostring(AdditionalDetail.value)
    )
  | extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
  | extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
  | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
  | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
  | extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
  | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
  | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
  | project-reorder TimeGenerated, OperationName, InitiatingUserOrApp, AADOperationType, targetDisplayName, Result, InitiatingIpAddress, UserAgent, CorrelationId, TenantId, AADTenantId
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: InitiatingAppName
      - identifier: AadUserId
        columnName: InitiatingAppServicePrincipalId
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: InitiatingUserPrincipalName
      - identifier: Name
        columnName: InitiatingAccountName
      - identifier: UPNSuffix
        columnName: InitiatingAccountUPNSuffix
  - entityType: Account
    fieldMappings:
      - identifier: AadUserId
        columnName: InitiatingAadUserId
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: InitiatingIpAddress
version: 1.1.2
kind: Scheduled

Stages and Predicates

union isfuzzy=true (2 sources)

Each leg below queries one source; the rule matches if any leg does. Sources: AuditLogs, AuditLogs

Leg 1: AuditLogs

AuditLogs
| where OperationName =~ "Set federation settings on domain"
| mv-expand TargetResources
| extend modifiedProperties = parse_json(TargetResources).modifiedProperties
| mv-expand modifiedProperties
| extend targetDisplayName = tostring(parse_json(modifiedProperties).displayName)

Leg 2: AuditLogs

AuditLogs
| where OperationName =~ "Set domain authentication"
| mv-expand TargetResources
| extend modifiedProperties = parse_json(TargetResources).modifiedProperties
| mv-expand modifiedProperties
| mv-apply Property = modifiedProperties on
  (
      where Property.displayName =~ "LiveType"
      | extend targetDisplayName = tostring(Property.displayName),
               NewDomainValue = tostring(Property.newValue)
  )
| where NewDomainValue has "Federated"

Applied to the combined result

| mv-apply AdditionalDetail = AdditionalDetails on
  (
      where AdditionalDetail.key =~ "User-Agent"
      | extend UserAgent = tostring(AdditionalDetail.value)
  )
| extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName))
| extend InitiatingAppName = tostring(InitiatedBy.app.displayName)
| extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId)
| extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName)
| extend InitiatingAadUserId = tostring(InitiatedBy.user.id)
| extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress))
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
| project-reorder TimeGenerated, OperationName, InitiatingUserOrApp, AADOperationType, targetDisplayName, Result, InitiatingIpAddress, UserAgent, CorrelationId, TenantId, AADTenantId

Indicators

Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.

FieldKindValues
NewDomainValuematch
  • Federated transforms: term
OperationNameeq
  • Set domain authentication
  • Set federation settings on domain
displayNameeq
  • LiveType
keyeq
  • User-Agent

Output fields

Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.

FieldSource
modifiedPropertiesextend
targetDisplayNameextend
InitiatingUserOrAppextend
InitiatingAppNameextend
InitiatingAppServicePrincipalIdextend
InitiatingUserPrincipalNameextend
InitiatingAadUserIdextend
InitiatingIpAddressextend
InitiatingAccountNameextend
InitiatingAccountUPNSuffixextend