From 1788541f29e326696985c76e5e6dfff86656c9f6 Mon Sep 17 00:00:00 2001 From: research-bot Date: Tue, 19 Nov 2024 12:24:48 -0800 Subject: [PATCH 1/4] updating detection after test --- ...e_and_response_for_verify_push_request.yml | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml index 7833aa0843..1dd266717e 100644 --- a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml +++ b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml @@ -1,14 +1,33 @@ name: Okta Mismatch Between Source and Response for Verify Push Request id: 8085b79b-9b85-4e67-ad63-351c9e9a5e9a -version: 3 -date: '2024-10-17' -author: John Murphy and Jordan Ruocco, Okta, Michael Haag, Splunk +version: 4 +date: '2024-11-19' +author: John Murphy and Jordan Ruocco, Okta, Michael Haag, Bhavin Patel, Splunk type: TTP status: experimental data_source: - Okta description: The following analytic identifies discrepancies between the source and response events for Okta Verify Push requests, indicating potential suspicious behavior. It leverages Okta System Log events, specifically `system.push.send_factor_verify_push` and `user.authentication.auth_via_mfa` with the factor "OKTA_VERIFY_PUSH." The detection groups events by SessionID, calculates the ratio of successful sign-ins to push requests, and checks for session roaming and new device/IP usage. This activity is significant as it may indicate push spam or unauthorized access attempts. If confirmed malicious, attackers could bypass MFA, leading to unauthorized access to sensitive systems. -search: '`okta` eventType IN (system.push.send_factor_verify_push) OR (eventType IN (user.authentication.auth_via_mfa) debugContext.debugData.factor="OKTA_VERIFY_PUSH") | eval groupby="authenticationContext.externalSessionId" | eval group_push_time=_time | bin span=2s group_push_time | fillnull value=NULL | stats min(_time) as _time by authenticationContext.externalSessionId eventType debugContext.debugData.factor outcome.result actor.alternateId client.device client.ipAddress client.userAgent.rawUserAgent debugContext.debugData.behaviors group_push_time groupby | iplocation client.ipAddress | fields - lat, lon, group_push_time | stats min(_time) as _time dc(client.ipAddress) as dc_ip sum(eval(if(eventType="system.push.send_factor_verify_push" AND "outcome.result"="SUCCESS",1,0))) as total_pushes sum(eval(if(eventType="user.authentication.auth_via_mfa" AND "outcome.result"="SUCCESS",1,0))) as total_successes sum(eval(if(eventType="user.authentication.auth_via_mfa" AND "outcome.result"="FAILURE",1,0))) as total_rejected sum(eval(if(eventType="system.push.send_factor_verify_push" AND "debugContext.debugData.behaviors" LIKE "%New Device=POSITIVE%",1,0))) as suspect_device_from_source sum(eval(if(eventType="system.push.send_factor_verify_push" AND "debugContext.debugData.behaviors" LIKE "%New IP=POSITIVE%",0,0))) as suspect_ip_from_source values(eval(if(eventType="system.push.send_factor_verify_push","client.ipAddress",""))) as src values(eval(if(eventType="user.authentication.auth_via_mfa","client.ipAddress",""))) as dest values(*) as * by groupby | eval ratio = round(total_successes/total_pushes,2) | search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' +search: '`okta` eventType IN (system.push.send_factor_verify_push) OR (eventType IN (user.authentication.auth_via_mfa) debugContext.debugData.factor="OKTA_VERIFY_PUSH") +| eval groupby="authenticationContext.externalSessionId" +| eval group_push_time=_time +| bin span=2s group_push_time +| fillnull value=NULL +| stats min(_time) as _time by authenticationContext.externalSessionId eventType debugContext.debugData.factor outcome.result actor.alternateId client.device client.ipAddress client.userAgent.rawUserAgent debugContext.debugData.behaviors group_push_time +| iplocation client.ipAddress +| fields - lat, lon, group_push_time +| stats min(_time) as _time + dc(client.ipAddress) as dc_ip + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $outcome.result$="SUCCESS", 1, 0))) as total_pushes + sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="SUCCESS", 1, 0))) as total_successes + sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="FAILURE", 1, 0))) as total_rejected + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New Device=POSITIVE%", 1, 0))) as suspect_device_from_source + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New IP=POSITIVE%", 1, 0))) as suspect_ip_from_source + values(eval(if(eventType="system.push.send_factor_verify_push", $client.ipAddress$, ""))) as src + values(eval(if(eventType="user.authentication.auth_via_mfa", $client.ipAddress$, ""))) as dest + values(*) as * by authenticationContext.externalSessionId +| eval ratio = round(total_successes / total_pushes, 2) +| search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' how_to_implement: The analytic leverages Okta OktaIm2 logs to be ingested using the Splunk Add-on for Okta Identity Cloud (https://splunkbase.splunk.com/app/6553). known_false_positives: False positives may be present based on organization size and configuration of Okta. Monitor, tune and filter as needed. references: From 18164e93709ac2c0bb33af4bd803c4b2ca270b9b Mon Sep 17 00:00:00 2001 From: research-bot Date: Tue, 19 Nov 2024 12:56:19 -0800 Subject: [PATCH 2/4] updating to prod --- ...source_and_response_for_verify_push_request.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml index 1dd266717e..dd7f4eb409 100644 --- a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml +++ b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml @@ -4,7 +4,7 @@ version: 4 date: '2024-11-19' author: John Murphy and Jordan Ruocco, Okta, Michael Haag, Bhavin Patel, Splunk type: TTP -status: experimental +status: production data_source: - Okta description: The following analytic identifies discrepancies between the source and response events for Okta Verify Push requests, indicating potential suspicious behavior. It leverages Okta System Log events, specifically `system.push.send_factor_verify_push` and `user.authentication.auth_via_mfa` with the factor "OKTA_VERIFY_PUSH." The detection groups events by SessionID, calculates the ratio of successful sign-ins to push requests, and checks for session roaming and new device/IP usage. This activity is significant as it may indicate push spam or unauthorized access attempts. If confirmed malicious, attackers could bypass MFA, leading to unauthorized access to sensitive systems. @@ -27,7 +27,7 @@ search: '`okta` eventType IN (system.push.send_factor_verify_push) OR (eventType values(eval(if(eventType="user.authentication.auth_via_mfa", $client.ipAddress$, ""))) as dest values(*) as * by authenticationContext.externalSessionId | eval ratio = round(total_successes / total_pushes, 2) -| search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' +| search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 |rename actor.alternateId as user | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' how_to_implement: The analytic leverages Okta OktaIm2 logs to be ingested using the Splunk Add-on for Okta Identity Cloud (https://splunkbase.splunk.com/app/6553). known_false_positives: False positives may be present based on organization size and configuration of Okta. Monitor, tune and filter as needed. references: @@ -40,11 +40,11 @@ tags: asset_type: Okta Tenant confidence: 80 impact: 80 - message: A mismatch between source and response for verifying a push request has occurred for $actor.alternateId$ + message: A mismatch between source and response for verifying a push request has occurred for $user$ mitre_attack_id: - T1621 observable: - - name: actor.alternateId + - name: user type: User role: - Victim @@ -66,3 +66,9 @@ tags: - group_push_time risk_score: 64 security_domain: access +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1556.006/okta_mfa_method_disabled/okta_mfa_method_disabled.log + source: Okta + sourcetype: OktaIM2:log From f605a70b33271b282f4589ccf6c53a1501c2edbf Mon Sep 17 00:00:00 2001 From: research-bot Date: Tue, 19 Nov 2024 13:14:11 -0800 Subject: [PATCH 3/4] updating drilldown --- ...e_and_response_for_verify_push_request.yml | 47 +++++++++++-------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml index dd7f4eb409..df824df6d4 100644 --- a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml +++ b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml @@ -9,27 +9,36 @@ data_source: - Okta description: The following analytic identifies discrepancies between the source and response events for Okta Verify Push requests, indicating potential suspicious behavior. It leverages Okta System Log events, specifically `system.push.send_factor_verify_push` and `user.authentication.auth_via_mfa` with the factor "OKTA_VERIFY_PUSH." The detection groups events by SessionID, calculates the ratio of successful sign-ins to push requests, and checks for session roaming and new device/IP usage. This activity is significant as it may indicate push spam or unauthorized access attempts. If confirmed malicious, attackers could bypass MFA, leading to unauthorized access to sensitive systems. search: '`okta` eventType IN (system.push.send_factor_verify_push) OR (eventType IN (user.authentication.auth_via_mfa) debugContext.debugData.factor="OKTA_VERIFY_PUSH") -| eval groupby="authenticationContext.externalSessionId" -| eval group_push_time=_time -| bin span=2s group_push_time -| fillnull value=NULL -| stats min(_time) as _time by authenticationContext.externalSessionId eventType debugContext.debugData.factor outcome.result actor.alternateId client.device client.ipAddress client.userAgent.rawUserAgent debugContext.debugData.behaviors group_push_time -| iplocation client.ipAddress -| fields - lat, lon, group_push_time -| stats min(_time) as _time - dc(client.ipAddress) as dc_ip - sum(eval(if(eventType="system.push.send_factor_verify_push" AND $outcome.result$="SUCCESS", 1, 0))) as total_pushes - sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="SUCCESS", 1, 0))) as total_successes - sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="FAILURE", 1, 0))) as total_rejected - sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New Device=POSITIVE%", 1, 0))) as suspect_device_from_source - sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New IP=POSITIVE%", 1, 0))) as suspect_ip_from_source - values(eval(if(eventType="system.push.send_factor_verify_push", $client.ipAddress$, ""))) as src - values(eval(if(eventType="user.authentication.auth_via_mfa", $client.ipAddress$, ""))) as dest - values(*) as * by authenticationContext.externalSessionId -| eval ratio = round(total_successes / total_pushes, 2) -| search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 |rename actor.alternateId as user | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' + | eval groupby="authenticationContext.externalSessionId" + | eval group_push_time=_time + | bin span=2s group_push_time + | fillnull value=NULL + | stats min(_time) as _time by authenticationContext.externalSessionId eventType debugContext.debugData.factor outcome.result actor.alternateId client.device client.ipAddress client.userAgent.rawUserAgent debugContext.debugData.behaviors group_push_time + | iplocation client.ipAddress + | fields - lat, lon, group_push_time + | stats min(_time) as _time + dc(client.ipAddress) as dc_ip + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $outcome.result$="SUCCESS", 1, 0))) as total_pushes + sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="SUCCESS", 1, 0))) as total_successes + sum(eval(if(eventType="user.authentication.auth_via_mfa" AND $outcome.result$="FAILURE", 1, 0))) as total_rejected + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New Device=POSITIVE%", 1, 0))) as suspect_device_from_source + sum(eval(if(eventType="system.push.send_factor_verify_push" AND $debugContext.debugData.behaviors$ LIKE "%New IP=POSITIVE%", 1, 0))) as suspect_ip_from_source + values(eval(if(eventType="system.push.send_factor_verify_push", $client.ipAddress$, ""))) as src + values(eval(if(eventType="user.authentication.auth_via_mfa", $client.ipAddress$, ""))) as dest + values(*) as * by authenticationContext.externalSessionId + | eval ratio = round(total_successes / total_pushes, 2) + | search ((ratio < 0.5 AND total_pushes > 1) OR (total_rejected > 0)) AND dc_ip > 1 AND suspect_device_from_source > 0 AND suspect_ip_from_source > 0 |rename actor.alternateId as user | `okta_mismatch_between_source_and_response_for_verify_push_request_filter`' how_to_implement: The analytic leverages Okta OktaIm2 logs to be ingested using the Splunk Add-on for Okta Identity Cloud (https://splunkbase.splunk.com/app/6553). known_false_positives: False positives may be present based on organization size and configuration of Okta. Monitor, tune and filter as needed. +drilldown_searches: +- name: View the detection results for - "$user$" + search: '%original_detection_search% | search user = "$user$"' + earliest_offset: $info_min_time$ + latest_offset: $info_max_time$ +- name: View risk events for the last 7 days for - "$user$" + search: '| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$user$") starthoursago=168 | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`' + earliest_offset: $info_min_time$ + latest_offset: $info_max_time$ references: - https://attack.mitre.org/techniques/T1621 - https://splunkbase.splunk.com/app/6553 From 7f109d5ecc342f325f2dc89096733dbc138ea770 Mon Sep 17 00:00:00 2001 From: research-bot Date: Tue, 19 Nov 2024 14:02:59 -0800 Subject: [PATCH 4/4] updating dataset link --- ...ch_between_source_and_response_for_verify_push_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml index df824df6d4..30bfd5dfeb 100644 --- a/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml +++ b/detections/application/okta_mismatch_between_source_and_response_for_verify_push_request.yml @@ -49,7 +49,7 @@ tags: asset_type: Okta Tenant confidence: 80 impact: 80 - message: A mismatch between source and response for verifying a push request has occurred for $user$ + message: A mismatch between source and response for verifying a push request has occurred for $user$ mitre_attack_id: - T1621 observable: @@ -78,6 +78,6 @@ tags: tests: - name: True Positive Test attack_data: - - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1556.006/okta_mfa_method_disabled/okta_mfa_method_disabled.log + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1621/okta_mismatch/okta_mismatch.log source: Okta sourcetype: OktaIM2:log