Detection rules › Splunk

Okta Multiple Failed Requests to Access Applications

Status
experimental
Group by
"actor.alternateId", "authenticationContext.externalSessionId", "client.ipAddress", targets
Author
John Murphy, Okta, Michael Haag, Splunk
Source
github.com/splunk/security_content

The following analytic detects multiple failed attempts to access applications in Okta, potentially indicating the reuse of a stolen web session cookie. It leverages Okta logs to evaluate policy and SSO events, aggregating data by user, session, and IP. The detection triggers when more than half of the app sign-on attempts are unsuccessful across multiple applications. This activity is significant as it may indicate an attempt to bypass authentication mechanisms. If confirmed malicious, it could lead to unauthorized access to sensitive applications and data, posing a significant security risk.

MITRE ATT&CK coverage

Rules detecting the same action

Other rules on this platform that filter on the same API call or operation.

Rule body splunk

name: Okta Multiple Failed Requests to Access Applications
id: 1c21fed1-7000-4a2e-9105-5aaafa437247
version: 6
creation_date: '2023-04-11'
modification_date: '2026-05-13'
author: John Murphy, Okta, Michael Haag, Splunk
status: experimental
type: Hunting
description: The following analytic detects multiple failed attempts to access applications in Okta, potentially indicating the reuse of a stolen web session cookie. It leverages Okta logs to evaluate policy and SSO events, aggregating data by user, session, and IP. The detection triggers when more than half of the app sign-on attempts are unsuccessful across multiple applications. This activity is significant as it may indicate an attempt to bypass authentication mechanisms. If confirmed malicious, it could lead to unauthorized access to sensitive applications and data, posing a significant security risk.
data_source:
    - Okta
search: "`okta` target{}.type=AppInstance (eventType=policy.evaluate_sign_on outcome.result=CHALLENGE) OR (eventType=user.authentication.sso outcome.result=SUCCESS) | eval targets=mvzip('target{}.type', 'target{}.displayName', \": \") | eval targets=mvfilter(targets LIKE \"AppInstance%\") | stats count min(_time) as _time values(outcome.result) as outcome.result dc(eval(if(eventType=\"policy.evaluate_sign_on\",targets,NULL))) as total_challenges sum(eval(if(eventType=\"user.authentication.sso\",1,0))) as total_successes by authenticationContext.externalSessionId targets actor.alternateId client.ipAddress | search total_challenges > 0 | stats min(_time) as _time values(*) as * sum(total_challenges) as total_challenges sum(total_successes) as total_successes values(eval(if(\"outcome.result\"=\"SUCCESS\",targets,NULL))) as success_apps values(eval(if(\":outcome.result\"!=\"SUCCESS\",targets,NULL))) as no_success_apps by authenticationContext.externalSessionId actor.alternateId client.ipAddress | fillnull | eval ratio=round(total_successes/total_challenges,2), severity=\"HIGH\", mitre_technique_id=\"T1538\", description=\"actor.alternateId\". \" from \" . \"client.ipAddress\" . \" seen opening \" . total_challenges . \" chiclets/apps with \" . total_successes . \" challenges successfully passed\" | fields - count, targets | search ratio < 0.5 total_challenges > 2 | `okta_multiple_failed_requests_to_access_applications_filter`"
how_to_implement: This analytic is specific to Okta and requires Okta:im2 logs to be ingested.
known_false_positives: False positives may be present based on organization size and configuration of Okta.
references:
    - https://attack.mitre.org/techniques/T1538
    - https://attack.mitre.org/techniques/T1550/004
analytic_story:
    - Okta Account Takeover
asset_type: Okta Tenant
mitre_attack_id:
    - T1550.004
    - T1538
product:
    - Splunk Enterprise
    - Splunk Enterprise Security
    - Splunk Cloud
category: application
security_domain: access

Stages and Predicates

Stage 1: search

`okta` target{}.type=AppInstance (eventType=policy.evaluate_sign_on outcome.result=CHALLENGE) OR (eventType=user.authentication.sso outcome.result=SUCCESS)

Stage 2: eval

| eval targets=mvzip('target{}.type', 'target{}.displayName', ": ")

Stage 3: eval

| eval targets=mvfilter(targets LIKE "AppInstance%")

Stage 4: stats

| stats count min(_time) as _time values(outcome.result) as outcome.result dc(eval(if(eventType="policy.evaluate_sign_on",targets,NULL))) as total_challenges sum(eval(if(eventType="user.authentication.sso",1,0))) as total_successes by authenticationContext.externalSessionId targets actor.alternateId client.ipAddress

Stage 5: search

| search total_challenges > 0

Stage 6: stats

| stats min(_time) as _time values(*) as * sum(total_challenges) as total_challenges sum(total_successes) as total_successes values(eval(if("outcome.result"="SUCCESS",targets,NULL))) as success_apps values(eval(if(":outcome.result"!="SUCCESS",targets,NULL))) as no_success_apps by authenticationContext.externalSessionId actor.alternateId client.ipAddress

Stage 7: fillnull

| fillnull

Stage 8: eval

| eval ratio=round(total_successes/total_challenges,2), severity="HIGH", mitre_technique_id="T1538", description="actor.alternateId". " from " . "client.ipAddress" . " seen opening " . total_challenges . " chiclets/apps with " . total_successes . " challenges successfully passed"

Stage 9: fields

| fields - count, targets

Stage 10: search

| search ratio < 0.5 total_challenges > 2

Stage 11: search

| `okta_multiple_failed_requests_to_access_applications_filter`

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
eventTypeeq
  • policy.evaluate_sign_on
  • user.authentication.sso
outcome.resulteq
  • CHALLENGE
  • SUCCESS
ratiolt
  • 0.5
sourcetypeeq
  • OktaIM2:log
target{}.typeeq
  • AppInstance
total_challengesgt
  • 0
  • 2