Potential Okta Brute Force (Device Token Rotation)
editPotential Okta Brute Force (Device Token Rotation)
editDetects 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:
- https://support.okta.com/help/s/article/Troubleshooting-Distributed-Brute-Force-andor-Password-Spray-attacks-in-Okta
- https://www.okta.com/identity-101/brute-force/
- https://support.okta.com/help/s/article/How-does-the-Device-Token-work?language=en_US
- https://developer.okta.com/docs/reference/api/event-types/
- https://www.elastic.co/security-labs/testing-okta-visibility-and-detection-dorothy
- https://sec.okta.com/articles/2023/08/cross-tenant-impersonation-prevention-and-detection
- https://www.okta.com/resources/whitepaper-how-adaptive-mfa-can-help-in-mitigating-brute-force-attacks/
- https://www.elastic.co/security-labs/monitoring-okta-threats-with-elastic-security
- https://www.elastic.co/security-labs/starter-guide-to-understanding-okta
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
editTriage 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
editThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.
Rule query
editFROM 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
-
Tactic:
- Name: Credential Access
- ID: TA0006
- Reference URL: https://attack.mitre.org/tactics/TA0006/
-
Technique:
- Name: Brute Force
- ID: T1110
- Reference URL: https://attack.mitre.org/techniques/T1110/