Potential Okta Brute Force (Device Token Rotation)

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

Potential Okta Brute Force (Device Token Rotation)

edit

Detects potential brute force attacks against a single Okta user account where excessive unique device token hashes are generated, indicating automated tooling that fails to persist browser cookies between attempts.

Rule type: esql

Rule indices: None

Severity: low

Risk score: 21

Runs every: 5m

Searches indices from: now-30m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References:

Tags:

  • Domain: Identity
  • Use Case: Identity and Access Audit
  • Data Source: Okta
  • Tactic: Credential Access
  • Resources: Investigation Guide

Version: 210

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

Triage and analysis

Investigating Potential Okta Brute Force (Device Token Rotation)

This rule identifies excessive unique device token hashes generated for a single user account, indicating automated brute force tooling that fails to persist browser cookies between authentication attempts.

Possible investigation steps

  • Identify the targeted user account and determine if it has elevated privileges or sensitive access.
  • Review the source IP and check if it belongs to known proxy, VPN, or cloud infrastructure.
  • Examine user agent strings for signs of automation, scripting tools, or inconsistent browser fingerprints.
  • Check if Okta flagged the source as a known threat or proxy.
  • Determine if any authentication attempts succeeded following the failed attempts.
  • Review the user’s recent activity for signs of account compromise.

False positive analysis

  • Users experiencing login issues may generate multiple device tokens through repeated legitimate attempts.
  • Automated testing or monitoring tools that do not persist cookies may trigger this rule.
  • Browser extensions or privacy tools that clear cookies between requests may cause device token rotation.

Response and remediation

  • If attack is confirmed, reset the user’s password immediately.
  • Block the source IP at the network perimeter.
  • Review and potentially reset MFA for the targeted account.
  • Monitor for any successful authentication that may indicate compromise.
  • Contact the user to verify if they experienced legitimate login issues.

Setup

edit

The Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.

Rule query

edit
FROM logs-okta.system-* METADATA _id, _version, _index
| WHERE
    event.dataset == "okta.system"
    AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start")
    AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT")
    AND okta.actor.alternate_id IS NOT NULL
    // Primary authn endpoint; sessions API provides additional coverage
    AND (
        okta.debug_context.debug_data.request_uri == "/api/v1/authn"
        OR okta.debug_context.debug_data.request_uri LIKE "/api/v1/sessions*"
    )
// Track whether each event has a device token
| EVAL has_dt_hash = CASE(okta.debug_context.debug_data.dt_hash IS NOT NULL, 1, 0)
// Aggregate by IP + user to detect single-user brute force
| STATS
    Esql.unique_dt_hashes = COUNT_DISTINCT(okta.debug_context.debug_data.dt_hash),
    Esql.total_attempts = COUNT(*),
    Esql.attempts_with_dt = SUM(has_dt_hash),
    Esql.unique_user_agents = COUNT_DISTINCT(okta.client.user_agent.raw_user_agent),
    Esql.first_seen = MIN(@timestamp),
    Esql.last_seen = MAX(@timestamp),
    Esql.dt_hash_values = VALUES(okta.debug_context.debug_data.dt_hash),
    Esql.event_action_values = VALUES(event.action),
    Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent),
    Esql.device_values = VALUES(okta.client.device),
    Esql.is_proxy_values = VALUES(okta.security_context.is_proxy),
    Esql.geo_country_values = VALUES(client.geo.country_name),
    Esql.geo_city_values = VALUES(client.geo.city_name),
    Esql.source_asn_values = VALUES(source.as.number),
    Esql.source_asn_org_values = VALUES(source.as.organization.name),
    Esql.threat_suspected_values = VALUES(okta.debug_context.debug_data.threat_suspected),
    Esql.risk_level_values = VALUES(okta.debug_context.debug_data.risk_level),
    Esql.risk_reasons_values = VALUES(okta.debug_context.debug_data.risk_reasons)
  BY okta.client.ip, okta.actor.alternate_id
// Calculate automation detection metrics (float-safe division)
| EVAL Esql.dt_coverage = Esql.attempts_with_dt * 1.0 / Esql.total_attempts,
       Esql.dt_per_attempt = Esql.unique_dt_hashes * 1.0 / Esql.total_attempts
// Detection branches:
//   A) Many unique DT hashes relative to attempts = tooling generating new tokens per attempt
//   B) High attempts + very low DT coverage = cookie-less automation (no DT sent at all)
//   C) Multiple user agents for same user = evasion or automation
| WHERE
    (Esql.unique_dt_hashes >= 7 AND Esql.total_attempts >= 10 AND Esql.dt_per_attempt >= 0.5)
    OR (Esql.total_attempts >= 12 AND Esql.dt_coverage < 0.15)
    OR (Esql.total_attempts >= 10 AND Esql.unique_user_agents >= 5)
| SORT Esql.total_attempts DESC
| KEEP Esql.*, okta.client.ip, okta.actor.alternate_id

Framework: MITRE ATT&CKTM