22/11/2024 | News release | Distributed by Public on 22/11/2024 19:00
This blog was co-authored by Splunker Jason Swierk.
In September 27, 2024, Okta disclosed a critical vulnerability affecting their Classic environment that created a concerning security gap in identity protection. The vulnerability, active since July 17, 2024, allowed attackers with valid credentials to bypass application-specific sign-on policies by simply modifying their user-agent string. This bypass enabled unauthorized users to circumvent crucial security controls, including network zones, device-type restrictions, and custom authentication requirements.
In this blog post, we will analyze the technical details of the Okta policy bypass vulnerability, explore its detection through existing analytic stories, and provide comprehensive hunting strategies for security teams. We'll examine how organizations can leverage Splunk's detection capabilities to identify both active exploitation attempts and historical incidents that may have occurred during the vulnerability window. Additionally, we'll provide detailed guidance on implementing effective monitoring strategies and establishing behavioral baselines to detect similar bypass attempts in the future.
Let's begin by examining the key aspects of this vulnerability before diving deeper into detection strategies, hunting techniques, and the ways defenders can protect their identity infrastructure.
The vulnerability stems from a flaw in how Okta Classic processes authentication requests from non-standard user-agents. When a request came from a user-agent that Okta classifies as "unknown" (such as Python scripts or uncommon browsers), the system failed to properly enforce application-specific sign-on policies.
This bypass affected several critical security controls:
Figure 1: Flow of Attack (large image here), Splunk 2024
The sequence diagram above illustrates both the exploitation path and detection opportunities for the Okta Classic Application Sign-On Policy bypass vulnerability that existed between July 17 and October 4, 2024. The flow shows how an attacker with valid credentials could bypass application-specific policies simply by using an unknown user-agent string, circumventing critical security controls such as network zones and device restrictions. The right side of the diagram highlights the parallel detection strategies defenders should employ, including user-agent analysis, historical access comparison, failed authentication attempt correlation, and behavioral analytics. These detection methods, when combined, help identify both active exploitation attempts and historical incidents that may have occurred during the vulnerability window.
The exploitation process follows these steps:
1. Credential Acquisition:
2. Policy Identification:
3. Authentication Request:
4. Access Granted:
POST /api/v1/authn HTTP/1.1
Host: customer.okta.com
User-Agent: PythonRequests/2.31.0z
Content-Type: application/json
{
"username": "[email protected]",
"password": "ValidPassword123",
"options": {
"multiOptionalFactorEnroll": false,
"warnBeforePasswordExpired": true
}
}
This seemingly innocuous request, when successful, could bypass carefully crafted security policies due to its non-standard user-agent.
The Splunk Threat Research Team maintains several Okta-focused analytic stories that provide valuable detection coverage for this vulnerability. Three key stories are particularly relevant:
This analytic story focuses on detecting attempts to overwhelm or bypass multi-factor authentication mechanisms. Key detections include:
These detections are particularly relevant to the policy bypass vulnerability, as attackers might attempt MFA exhaustion techniques in conjunction with unknown user-agents to maximize their chances of success.
This comprehensive analytic story includes detections for various account compromise scenarios:
These detections help identify unusual authentication patterns that could indicate exploitation of the policy bypass vulnerability, especially when combined with unknown user-agent strings.
This analytic story provides broader coverage of suspicious behavior:
The real power comes from correlating these detections, which you can do using the following correlation search:
| tstats `security_content_summariesonly`
values(All_Risk.analyticstories) as analyticstories
sum(All_Risk.calculated_risk_score) as risk_score,
count(All_Risk.calculated_risk_score) as
risk_event_count,values(All_Risk.annotations.mitre_attack.mitre_tactic_id)
as annotations.mitre_attack.mitre_tactic_id
WHERE All_Risk.risk_object_type = user All_Risk.analyticstories IN
("Okta Account Takeover", "Suspicious Okta Activity","Okta MFA Exhaustion")
This correlation helps identify:
While our analytic stories provide excellent detection coverage, hunting through Okta logs can uncover subtle patterns and behaviors that might indicate exploitation attempts or suspicious activity. The following hunting queries are designed to help security analysts identify potentially suspicious identity behaviors; however, it's important to note that not all identified behaviors are inherently malicious.
Before diving into specific queries, consider these key points:
1. Environmental Context
2. Baseline Establishment
3. False Positive Reduction
This first query focuses on analyzing authentication patterns and MFA behaviors across your Okta environment.
`okta` earliest=-30d latest=now()
(eventType IN ("user.authentication.auth_via_mfa",
"user.mfa.factor.*", "user.authentication.auth_via_inbound_delauth",
"user.authentication.auth_via_social", "user.authentication.sso"))
| eval time_period=if(_time >= relative_time(now(), "-15d"),
"current", "previous")
| stats
values(eventType) as event_types,
values(client.geographicalContext.country) as countries,
values(client.ipAddress) as ip_addresses,
dc(client.geographicalContext.country) as unique_countries,
values(target{}.type) as target_apps,
values(outcome.result) as outcome_results,
values(outcome.reason) as outcome_reasons,
count(eval(eventType IN ("user.mfa.factor.activate",
"user.mfa.factor.update", "user.mfa.factor.deactivate")))
as mfa_changes,
count(eval(outcome.result="FAILURE")) as failed_auth_attempts,
count(eval(eventType="user.authentication.auth_via_mfa" AND
outcome.result="SUCCESS" AND (client.device="Unknown" OR
client.device="unknown"))) as unknown_device_mfa_success,
count(eval(eventType="user.authentication.sso" AND
outcome.result="SUCCESS" AND (client.device="Unknown" OR
client.device="unknown"))) as unknown_device_sso_success
by user
| where mfa_changes > 0 OR failed_auth_attempts > 0 OR
unknown_device_mfa_success > 0 OR unknown_device_sso_success > 0
| eval geo_anomaly_score = case(
unique_countries > 3, 3,
unique_countries > 1, 2,
1=1, 0
)
| eval suspicion_score = geo_anomaly_score + (mfa_changes * 2) +
(failed_auth_attempts * 1) + (unknown_device_mfa_success * 3) +
(unknown_device_sso_success * 2)
| sort - suspicion_score
| table user, suspicion_score, geo_anomaly_score, mfa_changes,
failed_auth_attempts, unknown_device_mfa_success,
unknown_device_sso_success, event_types, countries, ip_addresses,
outcome_results, outcome_reasons, target_apps
Figure 2: Results over 30 days, Splunk 2024
Purpose: This hunt helps identify users exhibiting unusual authentication patterns by analyzing:
Key Features:
Customization Notes:
The second query provides deeper insight into authentication patterns and potential policy bypass attempts.
`okta`
(eventType="user.authentication.sso" OR
eventType="user.authentication.auth_via_mfa")
| eval is_unknown = if(client.device=="Unknown" OR
client.device=="unknown", 1, 0)
| eval is_success = if(outcome.result=="SUCCESS", 1, 0)
| eval hour = strftime(_time, "%H")
| eval is_odd_hour = if(hour > 24 OR hour < 0, 1, 0)
| stats
count(eval(is_success=1 AND is_unknown=1)) as
successful_unknown_sso,
count(eval(is_success=0)) as failed_attempts,
values(client.userAgent.rawUserAgent) as user_agents,
dc(client.geographicalContext.country) as unique_countries,
values(client.geographicalContext.country) as countries,
dc(client.ipAddress) as unique_ips,
values(client.ipAddress) as ip_addresses,
dc(hour) as unique_hours,
sum(is_odd_hour) as odd_hour_logins,
dc(client.userAgent.rawUserAgent) as unique_user_agents,
values(client.geographicalContext.city) as cities,
dc(client.geographicalContext.city) as unique_cities,
latest(_time) as last_activity,
earliest(_time) as first_activity,
values(target{}.type) as target_apps
by user
| eval time_span = (last_activity - first_activity) / 3600
| eval avg_activity_per_hour = if(time_span > 0,
(successful_unknown_sso + failed_attempts) / time_span, 0)
| eval suspicion_score = 0
| eval suspicion_score = suspicion_score + (successful_unknown_sso * 3)
| eval suspicion_score = suspicion_score + (failed_attempts * 1)
| eval suspicion_score = suspicion_score + (unique_countries * 2)
| eval suspicion_score = suspicion_score + (unique_ips * 1)
| eval suspicion_score = if(unique_hours > 12, suspicion_score + 5,
suspicion_score)
| eval suspicion_score = suspicion_score + (odd_hour_logins * 2)
| eval suspicion_score = suspicion_score + (unique_user_agents * 3)
| eval suspicion_score = if(avg_activity_per_hour > 10,
suspicion_score + 10, suspicion_score)
| eval geo_dispersion = if(unique_countries > 1,
unique_ips / unique_countries, unique_ips)
| eval suspicion_score = suspicion_score + (geo_dispersion * 2)
| eval unusual_ua_score = if(like(user_agents, "%Python%") OR
like(user_agents, "%curl%") OR like(user_agents, "%Postman%"), 15, 0)
| eval suspicion_score = suspicion_score + unusual_ua_score
| eval rapid_auth_score = if(avg_activity_per_hour > 5
AND unique_countries > 1, 20, 0)
| eval suspicion_score = suspicion_score + rapid_auth_score
| eval mfa_bypass_score = if(successful_unknown_sso > 0 AND
failed_attempts > 5, 25, 0)
| eval suspicion_score = suspicion_score + mfa_bypass_score
| eval city_hopping_score = if(unique_cities > (unique_countries *
3), 20, 0)
| eval suspicion_score = suspicion_score + city_hopping_score
| eval credential_stuffing_score = if(failed_attempts > 10 AND
successful_unknown_sso > 0, 30, 0)
| eval suspicion_score = suspicion_score + credential_stuffing_score
| eval policy_bypass_score = if(successful_unknown_sso > 0 AND
unusual_ua_score > 0, 25, 0)
| eval suspicion_score = suspicion_score + policy_bypass_score
| eval sensitive_app_score = if(like(target_apps, "%Office365%") OR
like(target_apps, "%Radius%"), 15, 0)
| eval suspicion_score = suspicion_score + sensitive_app_score
| sort - suspicion_score
| table user, suspicion_score, successful_unknown_sso,
failed_attempts, unique_countries, countries, unique_ips,
ip_addresses, user_agents, unique_hours, odd_hour_logins,
unique_user_agents, avg_activity_per_hour, geo_dispersion,
unusual_ua_score, rapid_auth_score, mfa_bypass_score,
city_hopping_score, credential_stuffing_score, policy_bypass_score,
sensitive_app_score, target_apps, cities
Figure 3: Output from query, Splunk 2024
Purpose: This advanced hunt helps identify sophisticated attack patterns by analyzing:
Key Scoring Components:
Customization Notes:
When analyzing results from these hunts:
Remember that these hunts are starting points; they should be customized to your environment and used as part of a broader detection strategy. Regular tuning and adjustment based on findings will improve their effectiveness over time.
The Okta Classic Application Sign-On Policy Bypass vulnerability (July 17 - October 4, 2024) demonstrates how seemingly simple configuration validations-in this case, user-agent verification-can lead to significant security implications when not properly implemented. While Okta has patched this vulnerability, it serves as a reminder that identity and access management systems require continuous monitoring and multiple layers of detection.
The detection strategy we've outlined combines three complementary approaches:
What makes this vulnerability particularly concerning is its low complexity-requiring only valid credentials and a modified user-agent-combined with its high impact of bypassing critical security controls. Organizations should consider this incident as an opportunity to:
The hunting queries provided offer a starting point for organizations to build their own detection capabilities, but they should be customized based on:
As attackers continue to find creative ways to bypass security controls, the ability to detect and respond to suspicious identity behaviors becomes increasingly crucial. Organizations should combine the detections and hunting approaches outlined here with robust security policies, regular access reviews, and continuous monitoring to maintain a strong security posture.