Okta Successful Login After Credential Attack
Correlates Okta credential attack alerts with subsequent successful authentication for the same user account, identifying potential compromise following brute force, password spray, or credential stuffing attempts.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/02/12"
3integration = ["okta"]
4maturity = "production"
5updated_date = "2026/02/19"
6
7[rule]
8author = ["Elastic"]
9description = """
10Correlates Okta credential attack alerts with subsequent successful authentication for the same user account,
11identifying potential compromise following brute force, password spray, or credential stuffing attempts.
12"""
13false_positives = [
14 "A user experiencing legitimate login issues (forgotten password, typos) may trigger credential attack alerts before successfully authenticating.",
15 "Automated password reset flows where a user fails multiple times then succeeds after resetting their password.",
16]
17from = "now-6h"
18interval = "30m"
19language = "esql"
20license = "Elastic License v2"
21name = "Okta Successful Login After Credential Attack"
22note = """## Triage and analysis
23
24### Investigating Okta Successful Login After Credential Attack
25
26This rule correlates credential attack alerts with subsequent successful authentication for the same user account. The correlation is user-centric, capturing IP rotation scenarios where attackers may login from a different IP after obtaining credentials.
27
28#### Possible investigation steps
29- Identify the user account and review the timeline between the attack and successful login.
30- Compare the attack source IPs versus the login source IP to identify potential IP rotation.
31- Review the original credential attack alert to understand the scope and nature of the attack.
32- Check the authentication method used and whether MFA was required and satisfied.
33- Review the session activity following the successful login for signs of account takeover.
34- Verify with the user if the login was legitimate.
35
36### False positive analysis
37- Users experiencing legitimate login issues may trigger attack alerts before successfully authenticating.
38- Automated password reset flows where a user fails multiple times then succeeds after resetting may trigger this rule.
39- The rule correlates on user identity only, so it fires when a user is targeted and later logs in, even if from different IPs.
40
41### Response and remediation
42- If compromise is suspected, reset the user's password and revoke all active sessions.
43- Reset MFA if the attacker may have enrolled their own device.
44- Block the source IP at the network perimeter.
45- Review the user's recent activity for signs of lateral movement or data access.
46- Check for persistence mechanisms such as new OAuth apps, API tokens, or enrolled devices.
47"""
48references = [
49 "https://support.okta.com/help/s/article/Troubleshooting-Distributed-Brute-Force-andor-Password-Spray-attacks-in-Okta",
50 "https://www.okta.com/identity-101/brute-force/",
51 "https://developer.okta.com/docs/reference/api/system-log/",
52 "https://developer.okta.com/docs/reference/api/event-types/",
53 "https://www.elastic.co/security-labs/testing-okta-visibility-and-detection-dorothy",
54 "https://www.elastic.co/security-labs/monitoring-okta-threats-with-elastic-security",
55 "https://www.elastic.co/security-labs/starter-guide-to-understanding-okta",
56]
57risk_score = 73
58rule_id = "50742e15-c5ef-49c8-9a2d-31221d45af58"
59setup = """## Setup
60
61This rule requires the following:
621. The Okta Fleet integration, Filebeat module, or similarly structured data for Okta System Logs.
632. The correlated credential attack detection rules must be enabled (at least one):
64 - Potential Okta Credential Stuffing (Single Source) (94e734c0-2cda-11ef-84e1-f661ea17fbce)
65 - Potential Okta Password Spray (Single Source) (42bf698b-4738-445b-8231-c834ddefd8a0)
66 - Potential Okta Brute Force (Device Token Rotation) (23f18264-2d6d-11ef-9413-f661ea17fbce)
67 - Potential Okta Brute Force (Multi-Source) (5889760c-9858-4b4b-879c-e299df493295)
68 - Potential Okta Password Spray (Multi-Source) (2d3c27d5-d133-4152-8102-8d051619ec4a)
693. Alerts from these rules must be written to the `.alerts-security.*` indices.
70
71The rule queries both alert indices and Okta log indices to correlate attack alerts with successful logins."""
72severity = "high"
73tags = [
74 "Domain: Identity",
75 "Use Case: Identity and Access Audit",
76 "Use Case: Threat Detection",
77 "Data Source: Okta",
78 "Data Source: Okta System Logs",
79 "Tactic: Credential Access",
80 "Tactic: Initial Access",
81 "Resources: Investigation Guide",
82 "Rule Type: Higher-Order Rule",
83]
84timestamp_override = "event.ingested"
85type = "esql"
86
87query = '''
88FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index
89// Filter for credential attack alerts OR successful Okta authentications
90| WHERE
91 (
92 // Credential attack alerts from the five correlated rules
93 kibana.alert.rule.rule_id IN (
94 "94e734c0-2cda-11ef-84e1-f661ea17fbce", // Credential Stuffing
95 "42bf698b-4738-445b-8231-c834ddefd8a0", // Password Spraying
96 "23f18264-2d6d-11ef-9413-f661ea17fbce", // DT Brute Force
97 "5889760c-9858-4b4b-879c-e299df493295", // Distributed Brute Force
98 "2d3c27d5-d133-4152-8102-8d051619ec4a" // Distributed Spray
99 )
100 )
101 OR (
102 // Successful Okta authentication events
103 event.dataset == "okta.system"
104 AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start")
105 AND okta.outcome.result == "SUCCESS"
106 AND okta.actor.alternate_id IS NOT NULL
107 )
108// correlation - alerts may store user/IP in different fields than raw logs
109| EVAL
110 Esql.user = COALESCE(okta.actor.alternate_id, user.name, user.email),
111 Esql.source_ip = COALESCE(okta.client.ip, client.ip, source.ip)
112// Must have user identity to correlate
113| WHERE Esql.user IS NOT NULL
114// Classify events and capture timestamps/IPs by event type
115| EVAL
116 Esql.is_attack_alert = CASE(
117 kibana.alert.rule.rule_id IN (
118 "94e734c0-2cda-11ef-84e1-f661ea17fbce",
119 "42bf698b-4738-445b-8231-c834ddefd8a0",
120 "23f18264-2d6d-11ef-9413-f661ea17fbce",
121 "5889760c-9858-4b4b-879c-e299df493295",
122 "2d3c27d5-d133-4152-8102-8d051619ec4a"
123 ), 1, 0
124 ),
125 Esql.is_success_login = CASE(
126 event.dataset == "okta.system"
127 AND okta.outcome.result == "SUCCESS", 1, 0
128 ),
129 Esql.attack_ip = CASE(
130 kibana.alert.rule.rule_id IN (
131 "94e734c0-2cda-11ef-84e1-f661ea17fbce",
132 "42bf698b-4738-445b-8231-c834ddefd8a0",
133 "23f18264-2d6d-11ef-9413-f661ea17fbce",
134 "5889760c-9858-4b4b-879c-e299df493295",
135 "2d3c27d5-d133-4152-8102-8d051619ec4a"
136 ), Esql.source_ip, null
137 ),
138 Esql.login_ip = CASE(
139 event.dataset == "okta.system"
140 AND okta.outcome.result == "SUCCESS", Esql.source_ip, null
141 ),
142 Esql.attack_ts = CASE(
143 kibana.alert.rule.rule_id IN (
144 "94e734c0-2cda-11ef-84e1-f661ea17fbce",
145 "42bf698b-4738-445b-8231-c834ddefd8a0",
146 "23f18264-2d6d-11ef-9413-f661ea17fbce",
147 "5889760c-9858-4b4b-879c-e299df493295",
148 "2d3c27d5-d133-4152-8102-8d051619ec4a"
149 ), @timestamp, null
150 ),
151 Esql.login_ts = CASE(
152 event.dataset == "okta.system"
153 AND okta.outcome.result == "SUCCESS", @timestamp, null
154 )
155// Aggregate by user (catches IP rotation: spray from IP A, login from IP B)
156| STATS
157 Esql.attack_count = SUM(Esql.is_attack_alert),
158 Esql.login_count = SUM(Esql.is_success_login),
159 Esql.earliest_attack = MIN(Esql.attack_ts),
160 Esql.latest_attack = MAX(Esql.attack_ts),
161 Esql.earliest_login = MIN(Esql.login_ts),
162 Esql.latest_login = MAX(Esql.login_ts),
163 Esql.attack_source_ips = VALUES(Esql.attack_ip),
164 Esql.login_source_ips = VALUES(Esql.login_ip),
165 Esql.all_source_ips = VALUES(Esql.source_ip),
166 Esql.alert_rule_ids = VALUES(kibana.alert.rule.rule_id),
167 Esql.alert_rule_names = VALUES(kibana.alert.rule.name),
168 Esql.event_action_values = VALUES(event.action),
169 Esql.geo_country_values = VALUES(client.geo.country_name),
170 Esql.geo_city_values = VALUES(client.geo.city_name),
171 Esql.source_asn_values = VALUES(source.as.number),
172 Esql.source_asn_org_values = VALUES(source.as.organization.name),
173 Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent),
174 Esql.device_values = VALUES(okta.client.device),
175 Esql.is_proxy_values = VALUES(okta.security_context.is_proxy)
176 BY Esql.user
177// Calculate time gap between latest attack and earliest subsequent login
178| EVAL Esql.attack_to_login_minutes = DATE_DIFF("minute", Esql.latest_attack, Esql.earliest_login)
179// Correlation: attack BEFORE login + success within reasonable window (3 hours)
180| WHERE
181 Esql.attack_count > 0
182 AND Esql.login_count > 0
183 AND Esql.latest_attack < Esql.earliest_login
184 AND Esql.attack_to_login_minutes <= 180
185| SORT Esql.login_count DESC
186| KEEP Esql.*
187'''
188
189
190[[rule.threat]]
191framework = "MITRE ATT&CK"
192[[rule.threat.technique]]
193id = "T1110"
194name = "Brute Force"
195reference = "https://attack.mitre.org/techniques/T1110/"
196[[rule.threat.technique.subtechnique]]
197id = "T1110.001"
198name = "Password Guessing"
199reference = "https://attack.mitre.org/techniques/T1110/001/"
200
201[[rule.threat.technique.subtechnique]]
202id = "T1110.003"
203name = "Password Spraying"
204reference = "https://attack.mitre.org/techniques/T1110/003/"
205
206[[rule.threat.technique.subtechnique]]
207id = "T1110.004"
208name = "Credential Stuffing"
209reference = "https://attack.mitre.org/techniques/T1110/004/"
210
211
212
213[rule.threat.tactic]
214id = "TA0006"
215name = "Credential Access"
216reference = "https://attack.mitre.org/tactics/TA0006/"
217[[rule.threat]]
218framework = "MITRE ATT&CK"
219[[rule.threat.technique]]
220id = "T1078"
221name = "Valid Accounts"
222reference = "https://attack.mitre.org/techniques/T1078/"
223[[rule.threat.technique.subtechnique]]
224id = "T1078.004"
225name = "Cloud Accounts"
226reference = "https://attack.mitre.org/techniques/T1078/004/"
227
228
229
230[rule.threat.tactic]
231id = "TA0001"
232name = "Initial Access"
233reference = "https://attack.mitre.org/tactics/TA0001/"
Triage and analysis
Investigating Okta Successful Login After Credential Attack
This rule correlates credential attack alerts with subsequent successful authentication for the same user account. The correlation is user-centric, capturing IP rotation scenarios where attackers may login from a different IP after obtaining credentials.
Possible investigation steps
- Identify the user account and review the timeline between the attack and successful login.
- Compare the attack source IPs versus the login source IP to identify potential IP rotation.
- Review the original credential attack alert to understand the scope and nature of the attack.
- Check the authentication method used and whether MFA was required and satisfied.
- Review the session activity following the successful login for signs of account takeover.
- Verify with the user if the login was legitimate.
False positive analysis
- Users experiencing legitimate login issues may trigger attack alerts before successfully authenticating.
- Automated password reset flows where a user fails multiple times then succeeds after resetting may trigger this rule.
- The rule correlates on user identity only, so it fires when a user is targeted and later logs in, even if from different IPs.
Response and remediation
- If compromise is suspected, reset the user's password and revoke all active sessions.
- Reset MFA if the attacker may have enrolled their own device.
- Block the source IP at the network perimeter.
- Review the user's recent activity for signs of lateral movement or data access.
- Check for persistence mechanisms such as new OAuth apps, API tokens, or enrolled devices.
References
Related rules
- Potential Okta Brute Force (Multi-Source)
- Potential Okta Password Spray (Multi-Source)
- Potential Okta Credential Stuffing (Single Source)
- Potential Okta Password Spray (Single Source)
- Okta AiTM Session Cookie Replay