Azure Domain Federation Settings Modified


Description

Detects modifications to domain federation settings in Microsoft Entra ID, including changes to federation trust configurations and OIDC discovery endpoints. Adversaries who compromise administrative accounts may modify these settings to federate the tenant with attacker-controlled identity providers, enabling unauthorized access and MFA bypass. This technique allows attackers to establish persistent access by redirecting authentication to malicious infrastructure.

Query · python

def rule(event):
    operation_name = event.get("operationName", "")

    # Branch 1: For "Set federation settings on domain" any change is suspicious
    if "set federation settings on domain" in operation_name.lower():
        return True

    # Branch 2: For "Set domain authentication" check if LiveType property changed to Federated
    if "set domain authentication" in operation_name.lower():
        display_names = event.deep_walk(
            "properties", "targetResources", "modifiedProperties", "displayName", default=[]
        )
        new_values = event.deep_walk(
            "properties", "targetResources", "modifiedProperties", "newValue", default=[]
        )

        # Ensure we have lists (deep_walk returns single value if only one result)
        if not isinstance(display_names, list):
            display_names = [display_names] if display_names else []
        if not isinstance(new_values, list):
            new_values = [new_values] if new_values else []

        if len(display_names) != len(new_values):
            # Lists have different lengths; check all values with consistent approach
            if "LiveType" in display_names and any(
                isinstance(val, str) and "Federated" in val for val in new_values
            ):
                return True
            return False

        # Check if the same property has displayName="LiveType" AND newValue contains "Federated"
        for display_name, new_value in zip(display_names, new_values):
            if (
                display_name == "LiveType"
                and isinstance(new_value, str)
                and "Federated" in new_value
            ):
                return True

    return False


def title(event):
    actor = event.deep_get(
        "properties", "initiatedBy", "user", "userPrincipalName", default="<UNKNOWN_ACTOR>"
    )

    return f"Domain Federation Trust Settings Modified by [{actor}] "


def alert_context(event):
    context = {}

    # Add federation-specific context
    context["operation_name"] = event.get("operationName", "<NO_OPERATION>")
    context["activity_display_name"] = event.deep_get(
        "properties", "activityDisplayName", default="<NO_ACTIVITY>"
    )
    context["category"] = event.get("category", "<NO_CATEGORY>")

    # Add initiator details
    context["initiator_user_id"] = event.deep_get(
        "properties", "initiatedBy", "user", "id", default="<NO_USER_ID>"
    )
    context["initiator_display_name"] = event.deep_get(
        "properties", "initiatedBy", "user", "displayName", default="<NO_DISPLAY_NAME>"
    )
    context["initiator_ip"] = event.deep_get(
        "properties", "initiatedBy", "user", "ipAddress", default="<NO_IP>"
    )

    return context

Analyst notes

  1. Query Azure.Audit logs for all federation-related operations by properties:initiatedBy:user:userPrincipalName in the 7 days before and after this change to determine if this modification was part of a broader attack campaign involving administrative credential compromise or privilege escalation
  2. Verify with your identity team and the initiating administrator whether this federation settings change was authorized through proper change management procedures, and review the new OIDC discovery endpoint URL to confirm it points to a legitimate identity provider owned by your organization and not an attacker-controlled domain
  3. Query Azure.Audit logs and sign-in logs for all authentication events using the affected domain in the 24 hours after the federation change to identify any suspicious token issuance or unauthorized access attempts, and if the modification was unauthorized, immediately revert the federation settings, revoke all active sessions for affected users, and review all API access and resource modifications that occurred during the compromise window
Raw source Azure Domain Federation Settings Modified · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: azure_domain_trust_settings_modified.py
RuleID: "Azure.Audit.DomainSettingsModified"
DisplayName: "Azure Domain Federation Settings Modified"
Enabled: true
LogTypes:
  - Azure.Audit
Severity: Medium
Description: >
  Detects modifications to domain federation settings in Microsoft Entra ID, including changes to
  federation trust configurations and OIDC discovery endpoints. Adversaries who compromise administrative
  accounts may modify these settings to federate the tenant with attacker-controlled identity providers,
  enabling unauthorized access and MFA bypass. This technique allows attackers to establish persistent
  access by redirecting authentication to malicious infrastructure.
Tags:
  - Persistence
  - Modify Authentication Process
Reports:
  MITRE ATT&CK:
    - TA0003:T1556
    - TA0003:T1556.006
Runbook: |
  1. Query Azure.Audit logs for all federation-related operations by properties:initiatedBy:user:userPrincipalName in the 7 days before and after this change to determine if this modification was part of a broader attack campaign involving administrative credential compromise or privilege escalation
  2. Verify with your identity team and the initiating administrator whether this federation settings change was authorized through proper change management procedures, and review the new OIDC discovery endpoint URL to confirm it points to a legitimate identity provider owned by your organization and not an attacker-controlled domain
  3. Query Azure.Audit logs and sign-in logs for all authentication events using the affected domain in the 24 hours after the federation change to identify any suspicious token issuance or unauthorized access attempts, and if the modification was unauthorized, immediately revert the federation settings, revoke all active sessions for affected users, and review all API access and resource modifications that occurred during the compromise window
Reference: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Microsoft%20Entra%20ID/Analytic%20Rules/ADFSDomainTrustMods.yaml
SummaryAttributes:
  - properties:initiatedBy:user:userPrincipalName
  - properties:targetResources:displayName
  - properties:initiatedBy:user:ipAddress
Tests:
  - Name: Set Federation Settings
    ExpectedResult: true
    Log:
      {
        "time": "2025-01-15 09:30:25.123",
        "resourceId": "/tenants/tenant-123/providers/Microsoft.aadiam",
        "operationName": "Set federation settings on domain",
        "operationVersion": "1.0",
        "category": "DirectoryManagement",
        "tenantId": "tenant-123",
        "resultSignature": "None",
        "durationMs": 0,
        "callerIpAddress": "2.2.2.2",
        "correlationId": "federation-change-001",
        "Level": "4",
        "properties":
          {
            "result": "success",
            "operationName": "Set federation settings on domain",
            "activityDisplayName": "Set federation settings on domain",
            "activityDateTime": "2025-01-15T09:30:25.1234567Z",
            "loggedByService": "Core Directory",
            "operationType": "Update",
            "initiatedBy":
              {
                "user":
                  {
                    "id": "admin-attacker-123",
                    "displayName": "Compromised Admin",
                    "userPrincipalName": "frodo@lotr.com",
                    "ipAddress": "2.2.2.2",
                  },
              },
          },
        "p_event_time": "2025-01-15 09:30:25.123",
        "p_log_type": "Azure.Audit",
      }
  - Name: Different Values Changed
    ExpectedResult: false
    Log:
      {
        "time": "2025-01-15 11:15:30.789",
        "resourceId": "/tenants/tenant-789/providers/Microsoft.aadiam",
        "operationName": "Set domain authentication",
        "operationVersion": "1.0",
        "category": "DirectoryManagement",
        "tenantId": "tenant-789",
        "resultSignature": "None",
        "durationMs": 0,
        "callerIpAddress": "203.0.113.100",
        "correlationId": "auth-change-002",
        "Level": "4",
        "properties":
          {
            "result": "success",
            "operationName": "Set domain authentication",
            "activityDisplayName": "Set domain authentication",
            "activityDateTime": "2025-01-15T11:15:30.7890123Z",
            "loggedByService": "Core Directory",
            "operationType": "Update",
            "initiatedBy":
              {
                "user":
                  {
                    "id": "admin-benign-456",
                    "displayName": "Legitimate Admin",
                    "userPrincipalName": "admin@company.com",
                    "ipAddress": "203.0.113.100",
                  },
              },
            "targetResources":
              [
                {
                  "id": "domain-normal-123",
                  "displayName": "normal.company.com",
                  "type": "Domain",
                  "modifiedProperties":
                    [
                      {
                        "displayName": "SomeOtherProperty",
                        "oldValue": "\"value1\"",
                        "newValue": "\"value2\"",
                      },
                    ],
                },
              ],
          },
        "p_event_time": "2025-01-15 11:15:30.789",
        "p_log_type": "Azure.Audit",
      }

# ------ paired body: azure_domain_trust_settings_modified.py ------

def rule(event):
    operation_name = event.get("operationName", "")

    # Branch 1: For "Set federation settings on domain" any change is suspicious
    if "set federation settings on domain" in operation_name.lower():
        return True

    # Branch 2: For "Set domain authentication" check if LiveType property changed to Federated
    if "set domain authentication" in operation_name.lower():
        display_names = event.deep_walk(
            "properties", "targetResources", "modifiedProperties", "displayName", default=[]
        )
        new_values = event.deep_walk(
            "properties", "targetResources", "modifiedProperties", "newValue", default=[]
        )

        # Ensure we have lists (deep_walk returns single value if only one result)
        if not isinstance(display_names, list):
            display_names = [display_names] if display_names else []
        if not isinstance(new_values, list):
            new_values = [new_values] if new_values else []

        if len(display_names) != len(new_values):
            # Lists have different lengths; check all values with consistent approach
            if "LiveType" in display_names and any(
                isinstance(val, str) and "Federated" in val for val in new_values
            ):
                return True
            return False

        # Check if the same property has displayName="LiveType" AND newValue contains "Federated"
        for display_name, new_value in zip(display_names, new_values):
            if (
                display_name == "LiveType"
                and isinstance(new_value, str)
                and "Federated" in new_value
            ):
                return True

    return False


def title(event):
    actor = event.deep_get(
        "properties", "initiatedBy", "user", "userPrincipalName", default="<UNKNOWN_ACTOR>"
    )

    return f"Domain Federation Trust Settings Modified by [{actor}] "


def alert_context(event):
    context = {}

    # Add federation-specific context
    context["operation_name"] = event.get("operationName", "<NO_OPERATION>")
    context["activity_display_name"] = event.deep_get(
        "properties", "activityDisplayName", default="<NO_ACTIVITY>"
    )
    context["category"] = event.get("category", "<NO_CATEGORY>")

    # Add initiator details
    context["initiator_user_id"] = event.deep_get(
        "properties", "initiatedBy", "user", "id", default="<NO_USER_ID>"
    )
    context["initiator_display_name"] = event.deep_get(
        "properties", "initiatedBy", "user", "displayName", default="<NO_DISPLAY_NAME>"
    )
    context["initiator_ip"] = event.deep_get(
        "properties", "initiatedBy", "user", "ipAddress", default="<NO_IP>"
    )

    return context

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.