From 693ee6c03deaf7a1c82ad2fc4d941fc928ee866c Mon Sep 17 00:00:00 2001 From: Kumar Sharad Date: Tue, 21 Jun 2022 14:40:19 +0200 Subject: [PATCH 1/4] model to detect risky commands --- ...ting_interpreter_detect_risky_spl_mltk.yml | 57 +++++++++++++++++++ lookups/__mlspl_DetectRiskySPL.yml | 6 ++ ...interpreter_detect_risky_spl_mltk.test.yml | 14 +++++ 3 files changed, 77 insertions(+) create mode 100644 detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml create mode 100644 lookups/__mlspl_DetectRiskySPL.yml create mode 100644 tests/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.test.yml diff --git a/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml b/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml new file mode 100644 index 0000000000..bfe691c333 --- /dev/null +++ b/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml @@ -0,0 +1,57 @@ +name: Splunk Command and Scripting Interpreter Detect Risky SPL MLTK +id: b4aefb5f-1037-410d-a149-1e091288ba33 +version: 1 +date: '2022-06-16' +author: Abhinav Mishra, Kumar Sharad, Namratha Sreekanta and Xiao Lin, Splunk +type: Anomaly +datamodel: +- Splunk_Audit +description: 'The following analytic uses a pre-trained machine learning text classifier to detect potentially risky commands. A command is deemed risky based on the presence of certain trigger keywords, along with the context and the role of the user (please see references). The model takes as input the command text, user and search type and outputs a risk score between [0,1]. A high score indicates higher likelihood of a command being risky.' +search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Splunk_Audit.Search_Activity by Search_Activity.search Search_Activity.info Search_Activity.total_run_time Search_Activity.user Search_Activity.savedsearch_name Search_Activity.search_type + | eval spl_text = 'Search_Activity.search'. " " .'Search_Activity.user'. " " .'Search_Activity.search_type' + | apply DetectRiskySPL + | table Search_Activity.search, Search_Activity.user, Search_Activity.search_type, risk_score + |`splunk_command_and_scripting_interpreter_detect_risky_spl_mltk_filter`' +how_to_implement: This detection depends on the MLTK app which can be found here - https://splunkbase.splunk.com/app/2890/ and the Splunk Audit datamodel which can be found here - https://splunkbase.splunk.com/app/1621/. Additionally, you need to be ingesting logs which include Search_Activity.search, Search_Activity.user, Search_Activity.search_type from your endpoints. +known_false_positives: False positives may be present if suspicious behavior is observed, as determined by frequent usage of risky keywords. +references: +- https://docs.splunk.com/Documentation/Splunk/latest/Security/SPLsafeguards#Commands_that_trigger_the_warning +tags: + analytic_story: + - Splunk Vulnerabilities + asset_type: Web Server + cis20: + - CIS 3 + - CIS 6 + confidence: 40 + cve: + - CVE-2022-32154 + context: + - Source:Endpoint + dataset: + - https://github.com/splunk/attack_data/raw/master/datasets/attack_techniques/T1203/search_activity.txt + impact: 50 + kill_chain_phases: + - Actions on Objectives + message: A potentially risky Splunk command has been run by $(Search_Activity.user), kindly review. + mitre_attack_id: + - T1059 + nist: + - DE.AE + observable: + - name: user + type: User + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Search_Activity.search + - Search_Activity.user + - Search_Activity.search_type + risk_score: 20 + security_domain: audit + diff --git a/lookups/__mlspl_DetectRiskySPL.yml b/lookups/__mlspl_DetectRiskySPL.yml new file mode 100644 index 0000000000..f4361bd161 --- /dev/null +++ b/lookups/__mlspl_DetectRiskySPL.yml @@ -0,0 +1,6 @@ +description: An MLTK model for detecting malicious commandlines +filename: __mlspl_DetectRiskySPL.mlmodel.mlmodel +name: __mlspl_DetectRiskySPL.mlmodel +case_sensitive_match: 'false' +min_matches: 1 +default_match: 'false' diff --git a/tests/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.test.yml b/tests/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.test.yml new file mode 100644 index 0000000000..bc3f68a213 --- /dev/null +++ b/tests/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.test.yml @@ -0,0 +1,14 @@ +name: Splunk Command and Scripting Interpreter Detect Risky SPL MLTK Unit Test +tests: +- name: Splunk Command and Scripting Interpreter Detect Risky SPL MLTK + file: application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml + pass_condition: '| stats count | where count > 0' + earliest_time: -10y + latest_time: now + attack_data: + - file_name: search_activity.txt + data: https://github.com/splunk/attack_data/raw/master/datasets/attack_techniques/T1203/search_activity.txt + source: audittrail + sourcetype: audittrail + update_timestamp: true + custom_index: _audit From 8228c36d18c10a0edd4c4402e366ccaba4f87603 Mon Sep 17 00:00:00 2001 From: Kumar Sharad Date: Tue, 21 Jun 2022 15:39:48 +0200 Subject: [PATCH 2/4] model to detect risky commands --- ..._command_and_scripting_interpreter_detect_risky_spl_mltk.yml | 1 + lookups/__mlspl_DetectRiskySPL.mlmodel | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 lookups/__mlspl_DetectRiskySPL.mlmodel diff --git a/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml b/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml index bfe691c333..ccbb6bec07 100644 --- a/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml +++ b/detections/application/splunk_command_and_scripting_interpreter_detect_risky_spl_mltk.yml @@ -9,6 +9,7 @@ datamodel: description: 'The following analytic uses a pre-trained machine learning text classifier to detect potentially risky commands. A command is deemed risky based on the presence of certain trigger keywords, along with the context and the role of the user (please see references). The model takes as input the command text, user and search type and outputs a risk score between [0,1]. A high score indicates higher likelihood of a command being risky.' search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Splunk_Audit.Search_Activity by Search_Activity.search Search_Activity.info Search_Activity.total_run_time Search_Activity.user Search_Activity.savedsearch_name Search_Activity.search_type | eval spl_text = 'Search_Activity.search'. " " .'Search_Activity.user'. " " .'Search_Activity.search_type' + | dedup spl_text | apply DetectRiskySPL | table Search_Activity.search, Search_Activity.user, Search_Activity.search_type, risk_score |`splunk_command_and_scripting_interpreter_detect_risky_spl_mltk_filter`' diff --git a/lookups/__mlspl_DetectRiskySPL.mlmodel b/lookups/__mlspl_DetectRiskySPL.mlmodel new file mode 100644 index 0000000000..b217d05f0b --- /dev/null +++ b/lookups/__mlspl_DetectRiskySPL.mlmodel @@ -0,0 +1,2 @@ +algo,model,options +DetectRiskySPL,"{""__mlspl_type"": [""algos.DetectRiskySPL"", ""DetectRiskySPL""], ""dict"": {""classes"": null, ""target_variable"": [""risk_score""], ""feature_variables"": [""spl_text""], ""columns"": [""spl_text""], ""estimator"": {""__mlspl_type"": [""sklearn.pipeline"", ""Pipeline""], ""dict"": {""steps"": [[""features"", {""__mlspl_type"": [""sklearn.feature_extraction.text"", ""CountVectorizer""], ""dict"": {""input"": ""content"", ""encoding"": ""utf-8"", ""decode_error"": ""strict"", ""strip_accents"": null, ""preprocessor"": null, ""tokenizer"": null, ""analyzer"": ""word"", ""lowercase"": true, ""token_pattern"": ""collect|delete|fit|outputcsv|outputlookup|adhoc|sendalert|sendemail|splunk\\-system\\-user|tscollect|run|script|runshellscript"", ""stop_words"": null, ""max_df"": 1.0, ""min_df"": 1, ""max_features"": null, ""ngram_range"": [1, 1], ""vocabulary"": null, ""binary"": false, ""dtype"": {""__mlspl_type"": [""builtins"", ""type""], ""type"": [""numpy"", ""int64""]}, ""fixed_vocabulary_"": false, ""_stop_words_id"": 94700205837760, ""stop_words_"": {""__mlspl_type"": [""builtins"", ""set""], ""set"": []}, ""vocabulary_"": {""run"": 6, ""script"": 7, ""splunk-system-user"": 10, ""adhoc"": 0, ""delete"": 2, ""collect"": 1, ""outputlookup"": 5, ""sendemail"": 9, ""outputcsv"": 4, ""fit"": 3, ""sendalert"": 8, ""tscollect"": 11}}}], [""predictor"", {""__mlspl_type"": [""sklearn.linear_model._logistic"", ""LogisticRegression""], ""dict"": {""penalty"": ""l2"", ""dual"": false, ""tol"": 0.0001, ""C"": 1.0, ""fit_intercept"": true, ""intercept_scaling"": 1, ""class_weight"": {""0"": 1, ""1"": 3}, ""random_state"": null, ""solver"": ""liblinear"", ""max_iter"": 100, ""multi_class"": ""auto"", ""verbose"": 0, ""warm_start"": false, ""n_jobs"": null, ""l1_ratio"": null, ""n_features_in_"": 12, ""classes_"": {""__mlspl_type"": [""numpy"", ""ndarray""], ""npy"": ""k05VTVBZAQB2AHsnZGVzY3InOiAnPGk4JywgJ2ZvcnRyYW5fb3JkZXInOiBGYWxzZSwgJ3NoYXBlJzogKDIsKSwgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoAAAAAAAAAAAEAAAAAAAAA""}, ""coef_"": {""__mlspl_type"": [""numpy"", ""ndarray""], ""npy"": ""k05VTVBZAQB2AHsnZGVzY3InOiAnPGY4JywgJ2ZvcnRyYW5fb3JkZXInOiBGYWxzZSwgJ3NoYXBlJzogKDEsIDEyKSwgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoJ2Llwab8rQCiu/el44vc/na1wqPt5BUBS9m4eUPILQBonfIHA8+a/Q0WJRaS/+T/DP5bBdcwNQLrfbPF6Pf0/omPwe8XB/D+FXV6Y32kDQIhuphupZSTA/h5iZ49Q8D8=""}, ""intercept_"": {""__mlspl_type"": [""numpy"", ""ndarray""], ""npy"": ""k05VTVBZAQB2AHsnZGVzY3InOiAnPGY4JywgJ2ZvcnRyYW5fb3JkZXInOiBGYWxzZSwgJ3NoYXBlJzogKDEsKSwgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAriY5zOOr0qwA==""}, ""n_iter_"": {""__mlspl_type"": [""numpy"", ""ndarray""], ""npy"": ""k05VTVBZAQB2AHsnZGVzY3InOiAnPGk0JywgJ2ZvcnRyYW5fb3JkZXInOiBGYWxzZSwgJ3NoYXBlJzogKDEsKSwgfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKAAAA""}}}]], ""memory"": null, ""verbose"": false}}}}","{""args"": [""risk_score"", ""spl_text""], ""target_variable"": [""risk_score""], ""feature_variables"": [""spl_text""], ""model_name"": ""DetectRiskySPL"", ""algo_name"": ""LogisticRegression"", ""mlspl_limits"": {""handle_new_cat"": ""default"", ""max_distinct_cat_values"": ""100"", ""max_distinct_cat_values_for_classifiers"": ""100"", ""max_distinct_cat_values_for_scoring"": ""100"", ""max_fit_time"": ""600"", ""max_inputs"": ""100000"", ""max_memory_usage_mb"": ""1024"", ""max_model_size_mb"": ""15"", ""max_score_time"": ""600"", ""streaming_apply"": ""false"", ""use_sampling"": ""true""}, ""kfold_cv"": null}" From f45aadfb8e94b1ea509781049e56ae205d75603b Mon Sep 17 00:00:00 2001 From: Kumar Sharad Date: Tue, 21 Jun 2022 17:43:49 +0200 Subject: [PATCH 3/4] model to detect risky commands --- lookups/__mlspl_DetectRiskySPL.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lookups/__mlspl_DetectRiskySPL.yml b/lookups/__mlspl_DetectRiskySPL.yml index f4361bd161..24993c579b 100644 --- a/lookups/__mlspl_DetectRiskySPL.yml +++ b/lookups/__mlspl_DetectRiskySPL.yml @@ -1,4 +1,4 @@ -description: An MLTK model for detecting malicious commandlines +description: An MLTK model for detecting risky SPL filename: __mlspl_DetectRiskySPL.mlmodel.mlmodel name: __mlspl_DetectRiskySPL.mlmodel case_sensitive_match: 'false' From 7bb299490f5b253ca42c35e598a39dfba7ac0eaf Mon Sep 17 00:00:00 2001 From: Kumar Sharad Date: Tue, 21 Jun 2022 17:47:31 +0200 Subject: [PATCH 4/4] model to detect risky commands --- lookups/__mlspl_DetectRiskySPL.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lookups/__mlspl_DetectRiskySPL.yml b/lookups/__mlspl_DetectRiskySPL.yml index 24993c579b..db6ad8d752 100644 --- a/lookups/__mlspl_DetectRiskySPL.yml +++ b/lookups/__mlspl_DetectRiskySPL.yml @@ -1,4 +1,4 @@ -description: An MLTK model for detecting risky SPL +description: An MLTK model for detecting Risky SPL filename: __mlspl_DetectRiskySPL.mlmodel.mlmodel name: __mlspl_DetectRiskySPL.mlmodel case_sensitive_match: 'false'