Detection rules › Kusto

Changes to Application Logout URL

Severity
low
Time window
1d
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

Detects changes to an applications sign out URL. Look for any modifications to a sign out URL. Blank entries or entries to non-existent locations would stop a user from terminating a session. Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-applications#logout-url-modified-or-removed

MITRE ATT&CK coverage

Event coverage

Rules detecting the same action

Other rules on this platform that filter on the same API call or operation.

Rule body kusto

id: 492fbe35-cbac-4a8c-9059-826782e6915a
name: Changes to Application Logout URL
description: |
  'Detects changes to an applications sign out URL.
    Look for any modifications to a sign out URL. Blank entries or entries to non-existent locations would stop a user from terminating a session.
    Ref: https://docs.microsoft.com/azure/active-directory/fundamentals/security-operations-applications#logout-url-modified-or-removed'
severity: Low
requiredDataConnectors:
  - connectorId: AzureActiveDirectory
    dataTypes:
      - AuditLogs
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
  - PrivilegeEscalation
relevantTechniques:
  - T1078.004
tags:
  - AADSecOpsGuide
query: |
  AuditLogs
    | where Category =~ "ApplicationManagement"
    | where OperationName has_any ("Update Application", "Update Service principal")
    | 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(InitiatedBy.user.ipAddress)
    | extend TargetAppName = tostring(TargetResources[0].displayName)
    | extend mod_props = TargetResources[0].modifiedProperties
    | mv-expand mod_props
    | extend Action = tostring(mod_props.displayName)
    | where Action contains "Url"
    | extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
    | extend OldURL = tostring(mod_props.oldValue)
    | extend NewURL = tostring(mod_props.newValue)
    | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])
    | project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress, UpdatedBy
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: InitiatingUserPrincipalName
      - identifier: Name
        columnName: InitiatingAccountName
      - identifier: UPNSuffix
        columnName: InitiatingAccountUPNSuffix
  - entityType: Account
    fieldMappings:
      - identifier: AadUserId
        columnName: InitiatingAadUserId
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: OldURL
  - entityType: URL
    fieldMappings:
      - identifier: Url
        columnName: NewURL
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: InitiatingIPAddress
version: 1.1.1
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Stage 1: source

AuditLogs

Stage 2: where

| where Category =~ "ApplicationManagement"

Stage 3: where

| where OperationName has_any ("Update Application", "Update Service principal")

Stage 4: extend (7 consecutive steps)

| 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(InitiatedBy.user.ipAddress)
| extend TargetAppName = tostring(TargetResources[0].displayName)
| extend mod_props = TargetResources[0].modifiedProperties

Stage 5: mv-expand

| mv-expand mod_props

Stage 6: extend

| extend Action = tostring(mod_props.displayName)

Stage 7: where

| where Action contains "Url"

Stage 8: extend (4 consecutive steps)

| extend UpdatedBy = iif(isnotempty(InitiatingAppName), InitiatingAppName, InitiatingUserPrincipalName)
| extend OldURL = tostring(mod_props.oldValue)
| extend NewURL = tostring(mod_props.newValue)
| extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1])

Stage 9: project-reorder

| project-reorder TimeGenerated, InitiatingAppName, InitiatingAppServicePrincipalId, InitiatingAadUserId, InitiatingUserPrincipalName, InitiatingIPAddress, UpdatedBy

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
Actioncontains
  • Url
Categoryeq
  • ApplicationManagement
OperationNamematch
  • Update Application
  • Update Service principal

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
InitiatingAppNameextend
InitiatingAppServicePrincipalIdextend
InitiatingUserPrincipalNameextend
InitiatingAadUserIdextend
InitiatingIPAddressextend
TargetAppNameextend
mod_propsextend
Actionextend
UpdatedByextend
OldURLextend
NewURLextend
InitiatingAccountNameextend
InitiatingAccountUPNSuffixextend