From d1cb61f15968c570d20db96a4995e9286b2b2e2c Mon Sep 17 00:00:00 2001 From: bpatel Date: Tue, 13 Oct 2020 16:20:47 -0700 Subject: [PATCH 1/4] api calls search mltk --- ...loud_infrastructure_api_calls_per_user.yml | 18 ++++++----- ...mber_of_cloud_infrastructure_api_calls.yml | 30 +++++++++++-------- 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml b/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml index 510ce22781..8a4648de83 100644 --- a/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml +++ b/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml @@ -18,14 +18,16 @@ how_to_implement: 'You must have Enterprise Security 6.0 or later, if not you wi which may give you better results. You may also want to periodically re-run this search to rebuild the model with the latest data.' author: David Dorsey, Splunk -search: '| tstats count as api_calls from datamodel=Change where - All_Changes.user!=unknown All_Changes.status=success - by All_Changes.user _time span=1h - | `drop_dm_object_name("All_Changes")` - | eval HourOfDay=strftime(_time, "%H") | eval HourOfDay=floor(HourOfDay/4)*4 | eval DayOfWeek=strftime(_time, "%w") | eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) - | table _time api_calls, user, HourOfDay, isWeekend - | eventstats dc(api_calls) as count by user, HourOfDay, isWeekend | where count > 1 - | fit DensityFunction api_calls by "user,HourOfDay,isWeekend" into cloud_excessive_api_calls_v1 dist=norm show_density=true' +search: '| tstats count as api_calls from datamodel=Change where All_Changes.user!=unknown All_Changes.status=success by All_Changes.user _time span=1h +| `drop_dm_object_name("All_Changes")` +| eval HourOfDay=strftime(_time, "%H") +| eval HourOfDay=floor(HourOfDay/4)*4 +| eval DayOfWeek=strftime(_time, "%w") +| eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) +| table _time api_calls, user, HourOfDay, isWeekend +| eventstats dc(api_calls) as api_calls by user, HourOfDay, isWeekend +| where api_calls > 1 +| fit DensityFunction api_calls by "user,HourOfDay,isWeekend" into cloud_excessive_api_calls_v1 dist=norm show_density=true' tags: analytics_story: - Suspicious Cloud User Activities diff --git a/detections/abnormally_high_number_of_cloud_infrastructure_api_calls.yml b/detections/abnormally_high_number_of_cloud_infrastructure_api_calls.yml index 4eba428d4b..a27f29845e 100644 --- a/detections/abnormally_high_number_of_cloud_infrastructure_api_calls.yml +++ b/detections/abnormally_high_number_of_cloud_infrastructure_api_calls.yml @@ -9,19 +9,23 @@ how_to_implement: You must be ingesting your cloud infrastructure logs. You also type: ESCU references: [] author: David Dorsey, Splunk -search: '| tstats count as api_calls values(All_Changes.command) as command from datamodel=Change where All_Changes.user!=unknown All_Changes.status=success - by All_Changes.user _time span=1h - | `drop_dm_object_name("All_Changes")` - | eval HourOfDay=strftime(_time, "%H") | eval HourOfDay=floor(HourOfDay/4)*4 | eval DayOfWeek=strftime(_time, "%w") | eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) - | join HourOfDay isWeekend [summary cloud_excessive_api_calls_v1] - | where cardinality >=16 - | apply cloud_excessive_api_calls_v1 threshold=0.005 | rename "IsOutlier(api_calls)" as isOutlier - | where isOutlier=1 - | eval expected_upper_threshold = mvindex(split(mvindex(BoundaryRanges, -1), ":"), 0) - | where api_calls > expected_upper_threshold - | eval distance_from_threshold = api_calls - expected_upper_threshold - | table _time, user, command, api_calls, expected_upper_threshold, distance_from_threshold - | `abnormally_high_number_of_cloud_infrastructure_api_calls_filter`' +search: '| tstats count as api_calls values(All_Changes.command) as command from datamodel=Change where All_Changes.user!=unknown All_Changes.status=success by All_Changes.user _time span=1h +| `drop_dm_object_name("All_Changes")` +| eval HourOfDay=strftime(_time, "%H") +| eval HourOfDay=floor(HourOfDay/4)*4 +| eval DayOfWeek=strftime(_time, "%w") +| eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) +| join user HourOfDay isWeekend + [ summary cloud_excessive_api_calls_v1] +| where cardinality >=16 +| apply cloud_excessive_api_calls_v1 threshold=0.005 +| rename "IsOutlier(api_calls)" as isOutlier +| where isOutlier=1 +| eval expected_upper_threshold = mvindex(split(mvindex(BoundaryRanges, -1), ":"), 0) +| where api_calls > expected_upper_threshold +| eval distance_from_threshold = api_calls - expected_upper_threshold +| table _time, user, command, api_calls, expected_upper_threshold, distance_from_threshold +| `abnormally_high_number_of_cloud_infrastructure_api_calls_filter`' known_false_positives: '' tags: analytics_story: From c84795fd8010a0be0155a1a5722f715c2cd6af4b Mon Sep 17 00:00:00 2001 From: bpatel Date: Tue, 13 Oct 2020 17:08:25 -0700 Subject: [PATCH 2/4] security api calls mltk --- ...loud_security_group_api_calls_per_user.yml | 18 ++++++----- ...mber_of_cloud_security_group_api_calls.yml | 31 ++++++++++--------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/baselines/baseline_of_cloud_security_group_api_calls_per_user.yml b/baselines/baseline_of_cloud_security_group_api_calls_per_user.yml index d7718620cb..f77290031e 100644 --- a/baselines/baseline_of_cloud_security_group_api_calls_per_user.yml +++ b/baselines/baseline_of_cloud_security_group_api_calls_per_user.yml @@ -15,14 +15,16 @@ how_to_implement: 'You must have Enterprise Security 6.0 or later, if not you wi which may give you better results. You may also want to periodically re-run this search to rebuild the model with the latest data.' author: David Dorsey, Splunk -search: '| tstats count as security_group_api_calls from datamodel=Change where - All_Changes.object_category=firewall All_Changes.status=success - by All_Changes.user _time span=1h - | `drop_dm_object_name("All_Changes")` - | eval HourOfDay=strftime(_time, "%H") | eval HourOfDay=floor(HourOfDay/4)*4 | eval DayOfWeek=strftime(_time, "%w") | eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) - | table _time security_group_api_calls, user, HourOfDay, isWeekend - | eventstats dc(security_group_api_calls) as count by user, HourOfDay, isWeekend | where count > 1 - | fit DensityFunction security_group_api_calls by "user,HourOfDay,isWeekend" into cloud_excessive_security_group_api_calls_v1 dist=norm show_density=true' +search: '| tstats count as security_group_api_calls from datamodel=Change where All_Changes.object_category=firewall All_Changes.status=success by All_Changes.user _time span=1h +| `drop_dm_object_name("All_Changes")` +| eval HourOfDay=strftime(_time, "%H") +| eval HourOfDay=floor(HourOfDay/4)*4 +| eval DayOfWeek=strftime(_time, "%w") +| eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) +| table _time security_group_api_calls, user, HourOfDay, isWeekend +| eventstats dc(security_group_api_calls) as security_group_api_calls by user, HourOfDay, isWeekend +| where security_group_api_calls >= 1 +| fit DensityFunction security_group_api_calls by "user,HourOfDay,isWeekend" into cloud_excessive_security_group_api_calls_v1 dist=norm show_density=true' tags: analytics_story: - Suspicious Cloud User Activities diff --git a/detections/abnormally_high_number_of_cloud_security_group_api_calls.yml b/detections/abnormally_high_number_of_cloud_security_group_api_calls.yml index 0ab0a41fe3..35fd1f2008 100644 --- a/detections/abnormally_high_number_of_cloud_security_group_api_calls.yml +++ b/detections/abnormally_high_number_of_cloud_security_group_api_calls.yml @@ -9,20 +9,23 @@ how_to_implement: You must be ingesting your cloud infrastructure logs. You also type: ESCU references: [] author: David Dorsey, Splunk -search: '| tstats count as security_group_api_calls values(All_Changes.command) as command from datamodel=Change where - All_Changes.object_category=firewall AND All_Changes.status=success - by All_Changes.user _time span=1h - | `drop_dm_object_name("All_Changes")` - | eval HourOfDay=strftime(_time, "%H") | eval HourOfDay=floor(HourOfDay/4)*4 | eval DayOfWeek=strftime(_time, "%w") | eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) - | join HourOfDay isWeekend [summary cloud_excessive_security_group_api_calls_v1] - | where cardinality >=16 - | apply cloud_excessive_security_group_api_calls_v1 threshold=0.005 | rename "IsOutlier(security_group_api_calls)" as isOutlier - | where isOutlier=1 - | eval expected_upper_threshold = mvindex(split(mvindex(BoundaryRanges, -1), ":"), 0) - | where security_group_api_calls > expected_upper_threshold - | eval distance_from_threshold = security_group_api_calls - expected_upper_threshold - | table _time, user, command, security_group_api_calls, expected_upper_threshold, distance_from_threshold - | `abnormally_high_number_of_cloud_security_group_api_calls_filter`' +search: '| tstats count as security_group_api_calls values(All_Changes.command) as command from datamodel=Change where All_Changes.object_category=firewall AND All_Changes.status=success by All_Changes.user _time span=1h +| `drop_dm_object_name("All_Changes")` +| eval HourOfDay=strftime(_time, "%H") +| eval HourOfDay=floor(HourOfDay/4)*4 +| eval DayOfWeek=strftime(_time, "%w") +| eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) +| join user HourOfDay isWeekend + [ summary cloud_excessive_security_group_api_calls_v1] +| where cardinality >=16 +| apply cloud_excessive_security_group_api_calls_v1 threshold=0.005 +| rename "IsOutlier(security_group_api_calls)" as isOutlier +| where isOutlier=1 +| eval expected_upper_threshold = mvindex(split(mvindex(BoundaryRanges, -1), ":"), 0) +| where security_group_api_calls > expected_upper_threshold +| eval distance_from_threshold = security_group_api_calls - expected_upper_threshold +| table _time, user, command, security_group_api_calls, expected_upper_threshold, distance_from_threshold +| `abnormally_high_number_of_cloud_security_group_api_calls_filter`' known_false_positives: '' tags: analytics_story: From dbd9314b1cb15ff0cbc12dc74c98d96187497838 Mon Sep 17 00:00:00 2001 From: bpatel Date: Wed, 14 Oct 2020 14:43:16 -0700 Subject: [PATCH 3/4] spl updates --- ...eviously_seen_cloud_api_calls_per_user_role_initial.yml | 2 +- .../cloud_api_calls_from_previously_unseen_user_roles.yml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/baselines/previously_seen_cloud_api_calls_per_user_role_initial.yml b/baselines/previously_seen_cloud_api_calls_per_user_role_initial.yml index cabce8af2c..5acc42482f 100644 --- a/baselines/previously_seen_cloud_api_calls_per_user_role_initial.yml +++ b/baselines/previously_seen_cloud_api_calls_per_user_role_initial.yml @@ -10,7 +10,7 @@ author: David Dorsey, Splunk search: '| tstats earliest(_time) as firstTimeSeen, latest(_time) as lastTimeSeen from datamodel=Change where All_Changes.user_type=AssumedRole AND All_Changes.status=success by All_Changes.user, All_Changes.command | `drop_dm_object_name("All_Changes")` - eventstats min(firstTimeSeen) as globalFirstTime + | eventstats min(firstTimeSeen) as globalFirstTime | eval enough_data = if(globalFirstTime <= relative_time(now(), "-7d@d"), 1, 0) | table user, command, firstTimeSeen, lastTimeSeen, enough_data | outputlookup previously_seen_cloud_api_calls_per_user_role' diff --git a/detections/cloud_api_calls_from_previously_unseen_user_roles.yml b/detections/cloud_api_calls_from_previously_unseen_user_roles.yml index b1c3b54077..7859e4af83 100644 --- a/detections/cloud_api_calls_from_previously_unseen_user_roles.yml +++ b/detections/cloud_api_calls_from_previously_unseen_user_roles.yml @@ -22,10 +22,11 @@ search: '| tstats earliest(_time) as firstTime, latest(_time) as lastTime from d where All_Changes.user_type=AssumedRole AND All_Changes.status=success by All_Changes.user, All_Changes.command | `drop_dm_object_name("All_Changes")` | lookup previously_seen_cloud_api_calls_per_user_role user as user, command as command OUTPUT firstTimeSeen, enough_data + | eventstats max(enough_data) as enough_data | where enough_data=1 - | eval firstTimeSeenSrc=min(firstTimeSeen) - | where isnull(firstTimeSeenSrc) OR firstTime > relative_time(now(), `cloud_api_calls_from_previously_unseen_user_roles_activity_window`) - | table firstTime, src, user, object, command + | eval firstTimeSeenUserApiCall=min(firstTimeSeen) + | where isnull(firstTimeSeenUserApiCall) OR firstTimeSeenUserApiCall > relative_time(now(), `cloud_api_calls_from_previously_unseen_user_roles_activity_window`) + | table firstTime, user, object, command | `cloud_api_calls_from_previously_unseen_user_roles_filter`' known_false_positives: "." tags: From 1ace7057bdf5ccc05e2181f62e82f566249de1f9 Mon Sep 17 00:00:00 2001 From: bpatel Date: Wed, 14 Oct 2020 15:09:39 -0700 Subject: [PATCH 4/4] adding >= --- .../baseline_of_cloud_infrastructure_api_calls_per_user.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml b/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml index 8a4648de83..706647ec1b 100644 --- a/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml +++ b/baselines/baseline_of_cloud_infrastructure_api_calls_per_user.yml @@ -26,7 +26,7 @@ search: '| tstats count as api_calls from datamodel=Change where All_Changes.use | eval isWeekend=if(DayOfWeek >= 1 AND DayOfWeek <= 5, 0, 1) | table _time api_calls, user, HourOfDay, isWeekend | eventstats dc(api_calls) as api_calls by user, HourOfDay, isWeekend -| where api_calls > 1 +| where api_calls >= 1 | fit DensityFunction api_calls by "user,HourOfDay,isWeekend" into cloud_excessive_api_calls_v1 dist=norm show_density=true' tags: analytics_story: