Azure High-Risk Sign-In


Description

Detects high-risk sign-in attempts flagged by Microsoft Entra ID Protection. These alerts indicate potential account compromise where Microsoft's machine learning has identified suspicious authentication patterns. High-risk sign-ins may result from credential theft, impossible travel, or unfamiliar locations.

Query · python

from panther_azuresignin_helpers import actor_user, azure_signin_alert_context, is_sign_in_event


def rule(event):
    if not is_sign_in_event(event):
        return False

    risk_state = event.deep_get("properties", "riskState", default="").lower()
    if risk_state in ["dismissed", "remediated"]:
        return False

    risk_level_during_signin = event.deep_get(
        "properties", "riskLevelDuringSignIn", default=""
    ).lower()
    risk_level_aggregated = event.deep_get("properties", "riskLevelAggregated", default="").lower()

    return risk_level_during_signin == "high" or risk_level_aggregated == "high"


def title(event):
    principal = actor_user(event)
    if principal is None:
        principal = "<NO_PRINCIPALNAME>"

    ip_address = event.deep_get("properties", "ipAddress", default="<UNKNOWN_IP>")

    return f"High-Risk Sign-In Detected: [{principal}] from [{ip_address}]"


def alert_context(event):
    context = azure_signin_alert_context(event)
    return context

Analyst notes

  1. Query Azure.Audit sign-in logs for all authentication events by properties:userPrincipalName in the 24 hours before and after the alert to establish normal sign-in patterns
  2. Check if callerIpAddress has been used by this user in the past 30 days and verify if the location matches expected geographic regions for the user
  3. Find other high-risk or failed sign-in attempts for this user or from this IP address in the past 7 days to identify potential credential compromise patterns
Raw source Azure High-Risk Sign-In · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: azure_high_risk_signin.py
RuleID: "Azure.Audit.HighRiskSignIn"
DisplayName: "Azure High-Risk Sign-In"
Enabled: true
LogTypes:
  - Azure.Audit
Severity: High
DedupPeriodMinutes: 60
Description: >
  Detects high-risk sign-in attempts flagged by Microsoft Entra ID Protection. These alerts indicate potential account compromise where Microsoft's machine learning has identified suspicious authentication patterns. High-risk sign-ins may result from credential theft, impossible travel, or unfamiliar locations.
Reports:
  MITRE ATT&CK:
    - TA0001:T1078
Runbook: |
  1. Query Azure.Audit sign-in logs for all authentication events by properties:userPrincipalName in the 24 hours before and after the alert to establish normal sign-in patterns
  2. Check if callerIpAddress has been used by this user in the past 30 days and verify if the location matches expected geographic regions for the user
  3. Find other high-risk or failed sign-in attempts for this user or from this IP address in the past 7 days to identify potential credential compromise patterns
Reference: https://learn.microsoft.com/en-us/entra/id-protection/howto-identity-protection-configure-risk-policies
SummaryAttributes:
  - properties:userPrincipalName
  - properties:servicePrincipalName
  - callerIpAddress
  - properties:riskLevelAggregated
  - properties:riskLevelDuringSignIn
  - properties:riskEventTypes
Tests:
  - Name: High Risk During Sign-In
    ExpectedResult: true
    Log:
      {
        "callerIpAddress": "4.4.4.4",
        "category": "SignInLogs",
        "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "durationMs": 0,
        "Level": "4",
        "location": "RU",
        "operationName": "Sign-in activity",
        "operationVersion": "1.0",
        "p_event_time": "2025-01-15 14:23:10.123",
        "p_log_type": "Azure.Audit",
        "properties":
          {
            "userId": "user123-456-789",
            "userPrincipalName": "john@justice.org",
            "appId": "00000002-0000-0ff1-ce00-111111111111",
            "authenticationProtocol": "oAuth2",
            "conditionalAccessStatus": "success",
            "correlationId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
            "createdDateTime": "2025-01-15T14:23:10.1234567Z",
            "ipAddress": "4.4.4.4",
            "isInteractive": true,
            "location":
              {
                "city": "Moscow",
                "countryOrRegion": "RU",
                "geoCoordinates": { "latitude": 55.7558, "longitude": 37.6173 },
                "state": "Moscow",
              },
            "resourceDisplayName": "Microsoft 365",
            "resourceId": "00000002-0000-0ff1-ce00-111111111111",
            "riskDetail": "aiConfirmedSigninSafe",
            "riskLevelAggregated": "none",
            "riskLevelDuringSignIn": "high",
            "riskState": "atRisk",
            "riskEventTypes": ["unfamiliarFeatures", "anonymizedIPAddress"],
            "status": { "errorCode": 0 },
            "tokenIssuerType": "AzureAD",
            "clientAppUsed": "Browser",
          },
        "resourceId": "/tenants/tenant-id-123/providers/Microsoft.aadiam",
        "resultSignature": "SUCCESS",
        "resultType": "0",
        "tenantId": "tenant-id-123",
        "time": "2025-01-15 14:23:10.123",
      }
  - Name: High Risk Dismissed
    ExpectedResult: false
    Log:
      {
        "callerIpAddress": "4.4.4.4",
        "category": "SignInLogs",
        "correlationId": "d4e5f6a7-b8c9-0123-def0-333333333333",
        "durationMs": 0,
        "Level": "4",
        "location": "US",
        "operationName": "Sign-in activity",
        "operationVersion": "1.0",
        "p_event_time": "2025-01-15 17:10:15.234",
        "p_log_type": "Azure.Audit",
        "properties":
          {
            "userId": "user234-567-890",
            "userPrincipalName": "cross@lotr.com",
            "appId": "00000002-0000-0ff1-ce00-111111111111",
            "authenticationProtocol": "oAuth2",
            "conditionalAccessStatus": "success",
            "correlationId": "d4e5f6a7-b8c9-0123-def0-333333333333",
            "createdDateTime": "2025-01-15T17:10:15.2345678Z",
            "ipAddress": "4.4.4.4",
            "isInteractive": true,
            "resourceDisplayName": "Microsoft 365",
            "resourceId": "00000002-0000-0ff1-ce00-111111111111",
            "riskDetail": "adminDismissedAllRiskForUser",
            "riskLevelAggregated": "high",
            "riskLevelDuringSignIn": "high",
            "riskState": "dismissed",
            "status": { "errorCode": 0 },
            "tokenIssuerType": "AzureAD",
          },
        "resourceId": "/tenants/tenant-id-012/providers/Microsoft.aadiam",
        "resultSignature": "SUCCESS",
        "resultType": "0",
        "tenantId": "tenant-id-012",
        "time": "2025-01-15 17:10:15.234",
      }

# ------ paired body: azure_high_risk_signin.py ------

from panther_azuresignin_helpers import actor_user, azure_signin_alert_context, is_sign_in_event


def rule(event):
    if not is_sign_in_event(event):
        return False

    risk_state = event.deep_get("properties", "riskState", default="").lower()
    if risk_state in ["dismissed", "remediated"]:
        return False

    risk_level_during_signin = event.deep_get(
        "properties", "riskLevelDuringSignIn", default=""
    ).lower()
    risk_level_aggregated = event.deep_get("properties", "riskLevelAggregated", default="").lower()

    return risk_level_during_signin == "high" or risk_level_aggregated == "high"


def title(event):
    principal = actor_user(event)
    if principal is None:
        principal = "<NO_PRINCIPALNAME>"

    ip_address = event.deep_get("properties", "ipAddress", default="<UNKNOWN_IP>")

    return f"High-Risk Sign-In Detected: [{principal}] from [{ip_address}]"


def alert_context(event):
    context = azure_signin_alert_context(event)
    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.