Azure SignIn via Legacy Authentication Protocol


Description

This detection looks for Successful Logins that have used legacy authentication protocols

Query · python

import json
from unittest.mock import MagicMock

from panther_azuresignin_helpers import actor_user, azure_signin_alert_context, is_sign_in_event

LEGACY_AUTH_USERAGENTS = ["BAV2ROPC", "CBAInPROD"]  # CBAInPROD is reported to be IMAP

# Add ServicePrincipalName/UserPrincipalName to
# KNOWN_EXCEPTIONS to prevent these Principals from Alerting
KNOWN_EXCEPTIONS = []


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

    global KNOWN_EXCEPTIONS  # pylint: disable=global-statement
    if isinstance(KNOWN_EXCEPTIONS, MagicMock):
        KNOWN_EXCEPTIONS = json.loads(KNOWN_EXCEPTIONS())  # pylint: disable=not-callable

    if actor_user(event) in KNOWN_EXCEPTIONS:
        return False
    user_agent = event.deep_get("properties", "userAgent", default="")
    error_code = event.deep_get("properties", "status", "errorCode", default=0)

    return all([user_agent in LEGACY_AUTH_USERAGENTS, error_code == 0])


def title(event):
    principal = actor_user(event)
    if principal is None:
        principal = "<NO_PRINCIPALNAME>"
    return f"AzureSignIn: Principal [{principal}] authenticated with a legacy auth protocol"


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


def alert_context(event):
    a_c = azure_signin_alert_context(event)
    a_c["userAgent"] = event.deep_get("properties", "userAgent", "<NO_USERAGENT>")
    return a_c

Analyst notes

Based on Microsoft's analysis more than 97 percent of credential stuffing attacks use legacy authentication and more than 99 percent of password spray attacks use legacy authentication protocols. These attacks would stop with basic authentication disabled or blocked. see https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication If you are aware of this Legacy Auth need, and need to continue using this mechanism, add the principal name to KNOWN_EXCEPTIONS. The Reference link contains additional material hosted on Microsoft.com

Raw source Azure SignIn via Legacy Authentication Protocol · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: azure_legacyauth.py
RuleID: "Azure.Audit.LegacyAuth"
DisplayName: "Azure SignIn via Legacy Authentication Protocol"
Enabled: true
Threshold: 1
DedupPeriodMinutes: 10
LogTypes:
  - Azure.Audit
Severity: Medium
Description: >
  This detection looks for Successful Logins that have used legacy authentication protocols
Reference: https://learn.microsoft.com/en-us/azure/active-directory/reports-monitoring/workbook-legacy-authentication
Runbook: >
  Based on Microsoft's analysis more than 97 percent of credential stuffing attacks use legacy authentication and more than 99 percent
  of password spray attacks use legacy authentication protocols. These attacks would stop with basic authentication disabled or blocked.
  see https://learn.microsoft.com/en-us/azure/active-directory/conditional-access/block-legacy-authentication

  If you are aware of this Legacy Auth need, and need to continue using this mechanism, add the principal name to KNOWN_EXCEPTIONS.
  The Reference link contains additional material hosted on Microsoft.com
SummaryAttributes:
  - properties:ServicePrincipalName
  - properties:UserPrincipalName
  - properties:ipAddress
Tests:
  - Name: Failed Sign-In
    ExpectedResult: False
    Log:
      {
        "calleripaddress": "12.12.12.12",
        "category": "ServicePrincipalSignInLogs",
        "correlationid": "e1f237ef-6548-4172-be79-03818c04c06e",
        "durationms": 0,
        "Level": "4",
        "location": "IE",
        "operationname": "Sign-in activity",
        "operationversion": 1,
        "p_event_time": "2023-07-26 23:00:20.889",
        "p_log_type": "Azure.Audit",
        "properties":
          {
            "appId": "cfceb902-8fab-4f8c-88ba-374d3c975c3a",
            "authenticationProcessingDetails":
              [{ "key": "Azure AD App Authentication Library", "value": "" }],
            "authenticationProtocol": "none",
            "clientCredentialType": "none",
            "conditionalAccessStatus": "notApplied",
            "correlationId": "5889315c-c4ac-4807-99da-e17417eae786",
            "createdDateTime": "2023-07-26 22:58:30.983201900",
            "crossTenantAccessType": "none",
            "flaggedForReview": false,
            "id": "36658c78-02d9-4d8f-84ee-5ca4a3fdefef",
            "incomingTokenType": "none",
            "ipAddress": "12.12.12.12",
            "isInteractive": false,
            "isTenantRestricted": false,
            "location":
              {
                "city": "Dublin",
                "countryOrRegion": "IE",
                "geoCoordinates":
                  {
                    "latitude": 51.35555555555555,
                    "longitude": -5.244444444444444,
                  },
                "state": "Dublin",
              },
            "managedIdentityType": "none",
            "processingTimeInMilliseconds": 0,
            "resourceDisplayName": "Azure Storage",
            "resourceId": "037694de-8c7d-498d-917d-edb650090fa5",
            "resourceServicePrincipalId": "a225221f-8cc5-411a-9cc7-5e1394b8a5b8",
            "riskDetail": "none",
            "riskLevelAggregated": "low",
            "riskLevelDuringSignIn": "low",
            "riskState": "none",
            "servicePrincipalId": "b1c34143-e405-4058-8e29-84596ad737b8",
            "servicePrincipalName": "some-service-principal",
            "status": { "errorCode": 7000215 },
            "tokenIssuerType": "AzureAD",
            "uniqueTokenIdentifier": "NDDDDDDDDDDDDDDDDDD_DD",
          },
        "resourceid": "/tenants/c0dd2fa0-71be-4df8-b2a6-24cee7de069a/providers/Microsoft.aadiam",
        "resultsignature": "None",
        "resulttype": 7000215,
        "tenantid": "a2aa49aa-2c0c-49d2-af87-f402c421df0b",
        "time": "2023-07-26 23:00:20.889",
      }
  - Name: Sign-In with legacy auth
    ExpectedResult: True
    Log:
      {
        "calleripaddress": "1.2.3.4",
        "category": "SignInLogs",
        "correlationid": "1043d312-230b-4f85-89de-2438df7ad2e9",
        "durationms": 0,
        "identity": "Some Identity",
        "Level": "4",
        "location": "US",
        "operationname": "Sign-in activity",
        "operationversion": 1,
        "p_event_time": "2023-07-21 05:05:12.056",
        "p_log_type": "Azure.Audit",
        "properties":
          {
            "appDisplayName": "Office 365 Exchange Online",
            "appId": "975c4feb-8c6b-4ed8-82e2-f0952ecc64d4",
            "appliedConditionalAccessPolicies": [],
            "authenticationContextClassReferences": [],
            "authenticationDetails":
              [
                {
                  "authenticationMethod": "Password",
                  "authenticationMethodDetail": "Password in the cloud",
                  "authenticationStepDateTime": "2023-01-11T11:11:11",
                  "authenticationStepRequirement": "",
                  "authenticationStepResultDetail": "Correct password",
                  "succeeded": true,
                },
              ],
            "authenticationProcessingDetails": [],
            "authenticationProtocol": "rpoc",
            "authenticationRequirement": "singleFactorAuthentication",
            "authenticationRequirementPolicies": [],
            "authenticationStrengths": [],
            "autonomousSystemNumber": 1234,
            "clientAppUsed": "Authenticated SMTP",
            "clientCredentialType": "clientAssertion",
            "conditionalAccessStatus": "notApplied",
            "correlationId": "9d5f7dd3-46a7-475a-9cc3-96160551ce49",
            "createdDateTime": "2023-07-21 05:03:52.160562400",
            "crossTenantAccessType": "none",
            "deviceDetail":
              { "deviceId": "", "displayName": "", "operatingSystem": "MacOs" },
            "flaggedForReview": false,
            "homeTenantId": "4328f0a8-06da-4457-b0d0-2c8e115e52cc",
            "id": "d9ae0e20-c959-42a3-ba74-00f59ac9f6c6",
            "incomingTokenType": "none",
            "ipAddress": "12.12.12.12",
            "isInteractive": true,
            "isTenantRestricted": false,
            "location":
              {
                "city": "Springfield",
                "countryOrRegion": "US",
                "geoCoordinates":
                  {
                    "latitude": 34.55555555555555,
                    "longitude": -74.4444444444444,
                  },
                "state": "Virginia",
              },
            "mfaDetail": {},
            "networkLocationDetails": [],
            "originalRequestId": "51755ad1-bc0d-4694-acb2-a21f054869ab",
            "privateLinkDetails": {},
            "processingTimeInMilliseconds": 343,
            "resourceDisplayName": "Office 365 Exchange Online",
            "resourceId": "b54c474b-4d74-4920-b0c3-7a8d2f2c4e95",
            "resourceServicePrincipalId": "d8f787f8-7f22-40d4-b057-6fc59c49ca43",
            "resourceTenantId": "fc66a38e-bcba-4fe9-b2de-c67918514cc5",
            "riskDetail": "none",
            "riskEventTypes": [],
            "riskEventTypes_v2": [],
            "riskLevelAggregated": "none",
            "riskLevelDuringSignIn": "none",
            "riskState": "none",
            "rngcStatus": 0,
            "servicePrincipalId": "",
            "sessionLifetimePolicies": [],
            "ssoExtensionVersion": "",
            "status":
              {
                "additionalDetails": "MFA requirement satisfied by claim in the token",
                "errorCode": 0,
              },
            "tenantId": "237c496d-1ca2-4b13-aa0f-69e44d745a27",
            "tokenIssuerName": "",
            "tokenIssuerType": "AzureAD",
            "uniqueTokenIdentifier": "hhhhhhhhhhhhhhhhhhhhhh",
            "userAgent": "BAV2ROPC",
            "userDisplayName": "A User Display Name",
            "userId": "8105c513-d24b-4b8d-9035-f8d48854d703",
            "userPrincipalName": "eve@lexcorp.com",
            "userType": "Member",
          },
        "resourceid": "/tenants/ef3a1b35-97d6-474b-a9de-94d21d4ee71b/providers/Microsoft.aadiam",
        "resultsignature": "None",
        "resulttype": 0,
        "tenantid": "c5fd010a-2972-4be2-9c67-986ceca2a042",
        "time": "2023-07-21 05:05:12.056",
      }
  - Name: Sign-In with legacy auth, KNOWN_EXCEPTION
    ExpectedResult: False
    Mocks:
      - objectName: KNOWN_EXCEPTIONS
        returnValue: >-
          [
            "homer.simpson@springfield.org"
          ]
    Log:
      {
        "calleripaddress": "173.53.70.163",
        "category": "SignInLogs",
        "correlationid": "1043d312-230b-4f85-89de-2438df7ad2e9",
        "durationms": 0,
        "identity": "Some Identity",
        "Level": "4",
        "location": "US",
        "operationname": "Sign-in activity",
        "operationversion": 1,
        "p_event_time": "2023-07-21 05:05:12.056",
        "p_log_type": "Azure.Audit",
        "properties":
          {
            "appDisplayName": "Office 365 Exchange Online",
            "appId": "975c4feb-8c6b-4ed8-82e2-f0952ecc64d4",
            "appliedConditionalAccessPolicies": [],
            "authenticationContextClassReferences": [],
            "authenticationDetails":
              [
                {
                  "authenticationMethod": "Password",
                  "authenticationMethodDetail": "Password in the cloud",
                  "authenticationStepDateTime": "2023-01-11T11:11:11",
                  "authenticationStepRequirement": "",
                  "authenticationStepResultDetail": "Correct password",
                  "succeeded": true,
                },
              ],
            "authenticationProcessingDetails": [],
            "authenticationProtocol": "rpoc",
            "authenticationRequirement": "singleFactorAuthentication",
            "authenticationRequirementPolicies": [],
            "authenticationStrengths": [],
            "autonomousSystemNumber": 1234,
            "clientAppUsed": "Authenticated SMTP",
            "clientCredentialType": "clientAssertion",
            "conditionalAccessStatus": "notApplied",
            "correlationId": "9d5f7dd3-46a7-475a-9cc3-96160551ce49",
            "createdDateTime": "2023-07-21 05:03:52.160562400",
            "crossTenantAccessType": "none",
            "deviceDetail":
              { "deviceId": "", "displayName": "", "operatingSystem": "MacOs" },
            "flaggedForReview": false,
            "homeTenantId": "4328f0a8-06da-4457-b0d0-2c8e115e52cc",
            "id": "d9ae0e20-c959-42a3-ba74-00f59ac9f6c6",
            "incomingTokenType": "none",
            "ipAddress": "12.12.12.12",
            "isInteractive": true,
            "isTenantRestricted": false,
            "location":
              {
                "city": "Springfield",
                "countryOrRegion": "US",
                "geoCoordinates":
                  {
                    "latitude": 34.55555555555555,
                    "longitude": -74.4444444444444,
                  },
                "state": "Virginia",
              },
            "mfaDetail": {},
            "networkLocationDetails": [],
            "originalRequestId": "51755ad1-bc0d-4694-acb2-a21f054869ab",
            "privateLinkDetails": {},
            "processingTimeInMilliseconds": 343,
            "resourceDisplayName": "Office 365 Exchange Online",
            "resourceId": "b54c474b-4d74-4920-b0c3-7a8d2f2c4e95",
            "resourceServicePrincipalId": "d8f787f8-7f22-40d4-b057-6fc59c49ca43",
            "resourceTenantId": "fc66a38e-bcba-4fe9-b2de-c67918514cc5",
            "riskDetail": "none",
            "riskEventTypes": [],
            "riskEventTypes_v2": [],
            "riskLevelAggregated": "none",
            "riskLevelDuringSignIn": "none",
            "riskState": "none",
            "rngcStatus": 0,
            "servicePrincipalId": "",
            "sessionLifetimePolicies": [],
            "ssoExtensionVersion": "",
            "status":
              {
                "additionalDetails": "MFA requirement satisfied by claim in the token",
                "errorCode": 0,
              },
            "tenantId": "237c496d-1ca2-4b13-aa0f-69e44d745a27",
            "tokenIssuerName": "",
            "tokenIssuerType": "AzureAD",
            "uniqueTokenIdentifier": "hhhhhhhhhhhhhhhhhhhhhh",
            "userAgent": "BAV2ROPC",
            "userDisplayName": "A User Display Name",
            "userId": "8105c513-d24b-4b8d-9035-f8d48854d703",
            "userPrincipalName": "homer.simpson@springfield.org",
            "userType": "Member",
          },
        "resourceid": "/tenants/ef3a1b35-97d6-474b-a9de-94d21d4ee71b/providers/Microsoft.aadiam",
        "resultsignature": "None",
        "resulttype": 0,
        "tenantid": "c5fd010a-2972-4be2-9c67-986ceca2a042",
        "time": "2023-07-21 05:05:12.056",
      }

# ------ paired body: azure_legacyauth.py ------

import json
from unittest.mock import MagicMock

from panther_azuresignin_helpers import actor_user, azure_signin_alert_context, is_sign_in_event

LEGACY_AUTH_USERAGENTS = ["BAV2ROPC", "CBAInPROD"]  # CBAInPROD is reported to be IMAP

# Add ServicePrincipalName/UserPrincipalName to
# KNOWN_EXCEPTIONS to prevent these Principals from Alerting
KNOWN_EXCEPTIONS = []


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

    global KNOWN_EXCEPTIONS  # pylint: disable=global-statement
    if isinstance(KNOWN_EXCEPTIONS, MagicMock):
        KNOWN_EXCEPTIONS = json.loads(KNOWN_EXCEPTIONS())  # pylint: disable=not-callable

    if actor_user(event) in KNOWN_EXCEPTIONS:
        return False
    user_agent = event.deep_get("properties", "userAgent", default="")
    error_code = event.deep_get("properties", "status", "errorCode", default=0)

    return all([user_agent in LEGACY_AUTH_USERAGENTS, error_code == 0])


def title(event):
    principal = actor_user(event)
    if principal is None:
        principal = "<NO_PRINCIPALNAME>"
    return f"AzureSignIn: Principal [{principal}] authenticated with a legacy auth protocol"


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


def alert_context(event):
    a_c = azure_signin_alert_context(event)
    a_c["userAgent"] = event.deep_get("properties", "userAgent", "<NO_USERAGENT>")
    return a_c

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.