Detection rules › Panther

Databricks Repeated Failed Login Attempts

Status
Experimental
Severity
medium
Group by
userIdentity.email
Log types
Databricks.Audit
Tags
Databricks, Credential Access, Initial Access
Reference
https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
Source
github.com/panther-labs/panther-analysis

Detects repeated failed login attempts within a 60-minute window, which may indicate credential stuffing, brute force attacks, or compromised credentials.

MITRE ATT&CK coverage

TacticTechniques
Initial AccessT1078 Valid Accounts
Credential AccessT1110 Brute Force

Rule body yaml

AnalysisType: rule
Filename: databricks_repeated_failed_login_attempts.py
RuleID: "Databricks.Audit.RepeatedFailedLoginAttempts"
DisplayName: "Databricks Repeated Failed Login Attempts"
Enabled: true
Status: Experimental
LogTypes:
  - Databricks.Audit
Tags:
  - Databricks
  - Credential Access
  - Initial Access
Reports:
  MITRE ATT&CK:
    - TA0006:T1110 # Brute Force
    - TA0001:T1078 # Valid Accounts
Severity: Medium
Threshold: 5
DedupPeriodMinutes: 60
Description: >
  Detects repeated failed login attempts within a 60-minute window, which may indicate
  credential stuffing, brute force attacks, or compromised credentials.
Runbook: |
  1. Count all failed and successful login attempts for this user in the 6 hours around this alert
  2. Check if the source IPs match known VPNs, proxies, or are from unexpected geographic locations
  3. Find if there were successful logins from different IPs immediately after the failed attempts
Reference: https://github.com/andyweaves/system-tables-audit-logs/blob/main/resources/queries_and_alerts.json
SummaryAttributes:
  - login_user
  - source_ip
  - login_action
Tests:
  - Name: Failed SAML Login
    ExpectedResult: true
    Log:
      timestamp: 1704067200000
      serviceName: "accounts"
      actionName: "samlLogin"
      sourceIPAddress: "203.0.113.50"
      userIdentity:
        email: "user@example.com"
      response:
        statusCode: 401
        errorMessage: "Invalid credentials"
  - Name: Failed JWT Login
    ExpectedResult: true
    Log:
      timestamp: 1704067200000
      serviceName: "accounts"
      actionName: "jwtLogin"
      sourceIPAddress: "203.0.113.50"
      requestParams:
        user: "admin@example.com"
      response:
        statusCode: 403
  - Name: Successful Login
    ExpectedResult: false
    Log:
      timestamp: 1704067200000
      serviceName: "accounts"
      actionName: "login"
      userIdentity:
        email: "user@example.com"
      response:
        statusCode: 200
  - Name: Different Action
    ExpectedResult: false
    Log:
      timestamp: 1704067200000
      serviceName: "accounts"
      actionName: "createUser"
      userIdentity:
        email: "admin@example.com"

Detection logic

Condition

actionName in ["aadBrowserLogin", "aadTokenLogin", "certLogin", "jwtLogin", "login", "mfaLogin", "oidcBrowserLogin", "passwordVerifyAuthentication", "samlLogin", "tokenLogin"]
response.statusCode in ["401", "403"]

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
actionNamein
  • aadBrowserLogin
  • aadTokenLogin
  • certLogin
  • jwtLogin
  • login
  • mfaLogin
  • oidcBrowserLogin
  • passwordVerifyAuthentication
  • samlLogin
  • tokenLogin
response.statusCodein
  • 401
  • 403

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
emailuserIdentity.email
sourceIPAddress
actionName