mirror of
https://github.com/splunk/security_content
synced 2026-06-08 17:32:49 +00:00
Branch was auto-updated.
This commit is contained in:
@@ -67,6 +67,7 @@ tags:
|
||||
mitre_attack_id:
|
||||
- T1505
|
||||
- T1505.003
|
||||
- T1190
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
name: Linux File Creation In Init Boot Directory
|
||||
id: 97d9cfb2-61ad-11ec-bb2d-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for suspicious file creation on init system directories
|
||||
for automatic execution of script or file upon boot up. This technique is commonly
|
||||
abuse by adversaries, malware author and red teamer to persist on the targeted or
|
||||
compromised host. This behavior can be executed or use by an administrator or network
|
||||
operator to add script files or binary files as part of a task or automation.
|
||||
filter is needed.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime FROM datamodel=Endpoint.Filesystem where Filesystem.file_path IN ("*/etc/init.d/*",
|
||||
"*/etc/rc.d/*", "*/sbin/init.d/*", "*/etc/rc.local*") by Filesystem.dest Filesystem.file_name
|
||||
Filesystem.process_guid Filesystem.file_path | `drop_dm_object_name(Filesystem)`
|
||||
| `security_content_ctime(lastTime)` | `security_content_ctime(firstTime)` | `linux_file_creation_in_init_boot_directory_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the file name, file path, and process_guid executions from your endpoints.
|
||||
If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase
|
||||
known_false_positives: Administrator or network operator can create file in this folders
|
||||
for automation purposes. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://www.intezer.com/blog/research/kaiji-new-chinese-linux-malware-turning-to-golang/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1546.004/linux_init_profile/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1037.004
|
||||
- T1037
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Filesystem.dest
|
||||
- Filesystem.file_create_time
|
||||
- Filesystem.file_name
|
||||
- Filesystem.process_guid
|
||||
- Filesystem.file_path
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: A file $file_name$ is created in $file_path$ on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,70 @@
|
||||
name: Linux File Creation In Profile Directory
|
||||
id: 46ba0082-61af-11ec-9826-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for suspicious file creation in /etc/profile.d directory
|
||||
to automatically execute scripts by shell upon boot up of a linux machine. This technique is
|
||||
commonly abused by adversaries, malware and red teamers as a persistence mechanism
|
||||
to the targeted or compromised host. This Anomaly detection is a good indicator
|
||||
that someone wants to run a code after boot up which can be done also by the administrator
|
||||
or network operator for automation purposes.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime FROM datamodel=Endpoint.Filesystem where Filesystem.file_path IN ("*/etc/profile.d/*")
|
||||
by Filesystem.dest Filesystem.file_create_time Filesystem.file_name Filesystem.process_guid
|
||||
Filesystem.file_path | `drop_dm_object_name(Filesystem)` | `security_content_ctime(lastTime)`
|
||||
| `security_content_ctime(firstTime)` | `linux_file_creation_in_profile_directory_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the file name, file path, and process_guid executions from your endpoints.
|
||||
If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can create file in profile.d
|
||||
folders for automation purposes. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://attack.mitre.org/techniques/T1546/004/
|
||||
- https://www.intezer.com/blog/research/kaiji-new-chinese-linux-malware-turning-to-golang/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1546.004/linux_init_profile/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1546.004
|
||||
- T1546
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Filesystem.dest
|
||||
- Filesystem.file_create_time
|
||||
- Filesystem.file_name
|
||||
- Filesystem.process_guid
|
||||
- Filesystem.file_path
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 80
|
||||
risk_score: 56
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: A file $file_name$ is created in $file_path$ on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,76 @@
|
||||
name: Linux Service File Created In Systemd Directory
|
||||
id: c7495048-61b6-11ec-9a37-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for suspicious file creation in systemd timer directory
|
||||
in linux platform. systemd is a system and service manager for Linux distributions.
|
||||
From the Windows perspective, this process fulfills the duties of wininit.exe and
|
||||
services.exe combined. At the risk of simplifying the functionality of systemd,
|
||||
it initializes a Linux system and starts relevant services that are defined in service
|
||||
unit files. Adversaries, malware and red teamers may abuse this this feature by
|
||||
stashing systemd service file to persist on the targetted or compromised host.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime FROM datamodel=Endpoint.Filesystem where Filesystem.file_name = *.service
|
||||
Filesystem.file_path IN ("*/etc/systemd/system*", "*/lib/systemd/system*", "*/usr/lib/systemd/system*",
|
||||
"*/run/systemd/system*", "*~/.config/systemd/*", "*~/.local/share/systemd/*","*/etc/systemd/user*",
|
||||
"*/lib/systemd/user*", "*/usr/lib/systemd/user*", "*/run/systemd/user*") by Filesystem.dest
|
||||
Filesystem.file_create_time Filesystem.file_name Filesystem.process_guid Filesystem.file_path
|
||||
| `drop_dm_object_name(Filesystem)` | `security_content_ctime(lastTime)` | `security_content_ctime(firstTime)`
|
||||
| `linux_service_file_created_in_systemd_directory_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the file name, file path, and process_guid executions from your endpoints.
|
||||
If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can create file in systemd
|
||||
folders for automation purposes. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://attack.mitre.org/techniques/T1053/006/
|
||||
- https://www.intezer.com/blog/research/kaiji-new-chinese-linux-malware-turning-to-golang/
|
||||
- https://redcanary.com/blog/attck-t1501-understanding-systemd-service-persistence/
|
||||
- https://github.com/microsoft/MSTIC-Sysmon/blob/main/linux/configs/attack-based/persistence/T1053.003_Cron_Activity.xml
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1053.006
|
||||
- T1053
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Filesystem.dest
|
||||
- Filesystem.file_create_time
|
||||
- Filesystem.file_name
|
||||
- Filesystem.process_guid
|
||||
- Filesystem.file_path
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 80
|
||||
risk_score: 64
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: A service file named as $file_path$ is created in systemd folder on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,76 @@
|
||||
name: Linux Service Restarted
|
||||
id: 084275ba-61b8-11ec-8d64-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for restarted or re-enable services in linux platform.
|
||||
This technique can be executed or performed using systemctl or service tool application.
|
||||
Adversaries may create or modify Windows services to repeatedly execute malicious
|
||||
payloads as part of persistence. When Windows boots up, it starts programs or applications
|
||||
called services that perform background system functions. Administrator may also
|
||||
create a legitimated service for a specific tool or normal application as part of
|
||||
task or automation, in this scenario it is suggested to look for the service path
|
||||
of the actual script or executable that register as service and who created the
|
||||
service for further verification.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where (Processes.process_name IN ("systemctl",
|
||||
"service") OR Processes.process IN ("*systemctl *", "*service *")) Processes.process
|
||||
IN ("*restart*", "*reload*", "*reenable*") by Processes.dest Processes.user Processes.parent_process_name
|
||||
Processes.process_name Processes.process Processes.process_id Processes.parent_process_id
|
||||
Processes.process_guid | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)` | `linux_service_restarted_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and commandline executions from your
|
||||
endpoints. If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can use this commandline
|
||||
for automation purposes. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://attack.mitre.org/techniques/T1543/003/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1053.006
|
||||
- T1053
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 50
|
||||
confidence: 50
|
||||
risk_score: 25
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: A commandline $process$ that may create or start a service on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,76 @@
|
||||
name: Linux Service Started Or Enabled
|
||||
id: e0428212-61b7-11ec-88a3-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-20'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for created or enable services in linux platform.
|
||||
This technique can be executed or performed using systemctl or service tool application.
|
||||
Adversaries may create or modify Windows services to repeatedly execute malicious
|
||||
payloads as part of persistence. When Windows boots up, it starts programs or applications
|
||||
called services that perform background system functions. Administrator may also
|
||||
create a legitimated service for a specific tool or normal application as part of
|
||||
task or automation, in this scenario it is suggested to look for the service path
|
||||
of the actual script or executable that register as service and who created the
|
||||
service for further verification.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where (Processes.process_name IN ("systemctl",
|
||||
"service") OR Processes.process IN ("*systemctl *", "*service *")) Processes.process
|
||||
IN ("* start *", "* enable *") by Processes.dest Processes.user Processes.parent_process_name
|
||||
Processes.process_name Processes.process Processes.process_id Processes.parent_process_id
|
||||
Processes.process_guid | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)` | `linux_service_started_or_enabled_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can use this commandline
|
||||
for automation purposes. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://attack.mitre.org/techniques/T1543/003/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1053.006
|
||||
- T1053
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 60
|
||||
confidence: 70
|
||||
risk_score: 42
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: a commandline $process$ that may create or start a service on $dest
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,75 @@
|
||||
name: Linux Setuid Using Chmod Utility
|
||||
id: bf0304b6-6250-11ec-9d7c-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-21'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for suspicious chmod utility execution to enable
|
||||
SUID bit. This allows a user to temporarily gain root access, usually in order to
|
||||
run a program. For example, only the root account is allowed to change the password
|
||||
information contained in the password database; If the SUID bit appears as an s,
|
||||
the file's owner also has execute permission to the file; if it appears as an S,
|
||||
the file's owner does not have execute permission. The second specialty permission
|
||||
is the SGID, or set group id bit. It is similar to the SUID bit, except it can temporarily
|
||||
change group membership, usually to execute a program. The SGID bit is set if an
|
||||
s or an S appears in the group section of permissions.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes WHERE (Processes.process_name = chmod
|
||||
OR Processes.process = "*chmod *") AND Processes.process IN("* g+s *", "* u+s *",
|
||||
"* 4777 *", "* 4577 *") by Processes.dest Processes.user Processes.parent_process_name
|
||||
Processes.process_name Processes.process Processes.process_id Processes.parent_process_id
|
||||
Processes.process_guid | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)` | `linux_setuid_using_chmod_utility_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can execute this command. Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://www.hackingarticles.in/linux-privilege-escalation-using-capabilities/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1548.001/chmod_uid/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1548.001
|
||||
- T1548
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: a commandline $process$ that may set suid or sgid on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,77 @@
|
||||
name: Linux Setuid Using Setcap Utility
|
||||
id: 9d96022e-6250-11ec-9a19-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-21'
|
||||
author: Teoderick Contreras, Splunk
|
||||
type: Anomaly
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: This analytic looks for suspicious setcap utility execution to enable
|
||||
SUID bit. This allows a user to temporarily gain root access, usually in order to
|
||||
run a program. For example, only the root account is allowed to change the password
|
||||
information contained in the password database; If the SUID bit appears as an s,
|
||||
the file's owner also has execute permission to the file; if it appears as an S,
|
||||
the file's owner does not have execute permission. The second specialty permission
|
||||
is the SGID, or set group id bit. It is similar to the SUID bit, except it can temporarily
|
||||
change group membership, usually to execute a program. The SGID bit is set if an
|
||||
s or an S appears in the group section of permissions.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where (Processes.process_name = setcap
|
||||
OR Processes.process = "*setcap *") AND Processes.process IN ("* cap_setuid=ep *",
|
||||
"* cap_setuid+ep *", "* cap_net_bind_service+p *", "* cap_net_raw+ep *", "* cap_dac_read_search+ep
|
||||
*") by Processes.dest Processes.user Processes.parent_process_name Processes.process_name
|
||||
Processes.process Processes.process_id Processes.parent_process_id Processes.process_guid
|
||||
| `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`
|
||||
| `linux_setuid_using_setcap_utility_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name, parent process, and command-line executions from your
|
||||
endpoints. If you are using Sysmon, you can use the Add-on for Linux Sysmon from Splunkbase.
|
||||
known_false_positives: Administrator or network operator can execute this command.
|
||||
Please update the filter macros to remove false positives.
|
||||
references:
|
||||
- https://www.hackingarticles.in/linux-privilege-escalation-using-capabilities/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Linux Privilege Escalation
|
||||
- Linux Persistence Techniques
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1548.001/linux_setcap/sysmon_linux.log
|
||||
kill_chain_phases:
|
||||
- Privilege Escalation
|
||||
mitre_attack_id:
|
||||
- T1548.001
|
||||
- T1548
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 70
|
||||
confidence: 70
|
||||
risk_score: 49
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Privilege Escalation
|
||||
- Stage:Persistence
|
||||
message: A commandline $process$ that may set suid or sgid on $dest$
|
||||
observable:
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
nist:
|
||||
- DE.CM
|
||||
cis20:
|
||||
- CIS 3
|
||||
- CIS 5
|
||||
- CIS 16
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,79 @@
|
||||
name: MSI Module Loaded by Non-System Binary
|
||||
id: ccb98a66-5851-11ec-b91c-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-08'
|
||||
author: Michael Haag, Splunk
|
||||
type: Hunting
|
||||
datamodel: []
|
||||
description: 'The following hunting analytic identifies `msi.dll` being loaded by a binary not located in `system32`, `syswow64`, `winsxs` or `windows` paths. This behavior is most recently related to InstallerFileTakeOver, or CVE-2021-41379, and DLL side-loading.
|
||||
CVE-2021-41379 requires a binary to be dropped and `msi.dll` to be loaded by it. To Successful exploitation of this issue happens in four parts \
|
||||
|
||||
1. Generation of an MSI that will trigger bad behavior. \
|
||||
|
||||
1. Preparing a directory for MSI installation. \
|
||||
|
||||
1. Inducing an error state. \
|
||||
|
||||
1. Racing to introduce a junction and a symlink to trick msiexec.exe to modify the attacker specified file. \
|
||||
|
||||
In addition, `msi.dll` has been abused in DLL side-loading attacks by being loaded by non-system binaries.'
|
||||
search: '`sysmon` EventCode=7 ImageLoaded="*\\msi.dll" NOT (Image IN ("*\\System32\\*","*\\syswow64\\*","*\\windows\\*", "*\\winsxs\\*"))
|
||||
| stats count min(_time) as firstTime max(_time) as lastTime
|
||||
by Image ImageLoaded process_name Computer EventCode ProcessId
|
||||
| `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)`
|
||||
| `msi_module_loaded_by_non_system_binary_filter`'
|
||||
how_to_implement: To successfully implement this search, you need to be ingesting
|
||||
logs with the process name and imageloaded executions from your endpoints. If you
|
||||
are using Sysmon, you must have at least version 6.0.4 of the Sysmon TA.
|
||||
known_false_positives: It is possible some Administrative utilities will load msi.dll outside of normal system paths, filter as needed.
|
||||
references:
|
||||
- https://attackerkb.com/topics/7LstI2clmF/cve-2021-41379/rapid7-analysis
|
||||
- https://github.com/klinix5/InstallerFileTakeOver
|
||||
- https://github.com/mandiant/red_team_tool_countermeasures/blob/master/rules/PGF/supplemental/hxioc/msi.dll%20Hijack%20(Methodology).ioc
|
||||
cve:
|
||||
- CVE-2021-41379
|
||||
tags:
|
||||
analytic_story:
|
||||
- Windows Privilege Escalation
|
||||
dataset: []
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1574.002
|
||||
- T1574
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Image
|
||||
- ImageLoaded
|
||||
- process_name
|
||||
- Computer
|
||||
- EventCode
|
||||
- ProcessId
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 70
|
||||
# (impact * confidence)/100
|
||||
risk_score: 56
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: The following module $ImageLoaded$ was loaded by $Image$ outside of the normal system paths on endpoint $Computer$, potentally related to DLL side-loading.
|
||||
observable:
|
||||
- name: Computer
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: ImageLoaded
|
||||
type: Other
|
||||
role:
|
||||
- Other
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
|
||||
@@ -28,8 +28,11 @@ how_to_implement: To successfully implement this search, you need to be ingestin
|
||||
Sysmon TA.
|
||||
known_false_positives: network admin can resize the shadowstorage for valid purposes.
|
||||
references:
|
||||
- https://www.fireeye.com/blog/threat-research/2020/10/fin11-email-campaigns-precursor-for-ransomware-data-theft.html
|
||||
- https://blog.virustotal.com/2020/11/keep-your-friends-close-keep-ransomware.html
|
||||
- https://www.fireeye.com/blog/threat-research/2020/10/fin11-email-campaigns-precursor-for-ransomware-data-theft.html
|
||||
- https://blog.virustotal.com/2020/11/keep-your-friends-close-keep-ransomware.html
|
||||
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1490/T1490.md
|
||||
- https://redcanary.com/blog/blackbyte-ransomware/
|
||||
- https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/vssadmin-resize-shadowstorage
|
||||
tags:
|
||||
analytic_story:
|
||||
- Clop Ransomware
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Windows DISM Remove Defender
|
||||
id: 8567da9e-47f0-11ec-99a9-acde48001122
|
||||
version: 1
|
||||
date: '2021-11-17'
|
||||
author: Michael Haag, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: The following analytic identifies the use of the Windows Disk Image Utility,
|
||||
`dism.exe`, to remove Windows Defender. Adversaries may use `dism.exe` to disable
|
||||
Defender before completing their objective.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where Processes.process_name=dism.exe
|
||||
(Processes.process="*/online*" AND Processes.process="*/disable-feature*" AND Processes.process="*Windows-Defender*"
|
||||
AND Processes.process="*/remove*") by Processes.dest Processes.user Processes.parent_process_name
|
||||
Processes.process_name Processes.original_file_name Processes.process Processes.process_id
|
||||
Processes.parent_process_id | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)`
|
||||
| `security_content_ctime(lastTime)` | `windows_dism_remove_defender_filter`'
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition,
|
||||
confirm the latest CIM App 4.20 or higher is installed and the latest TA for the
|
||||
endpoint product.
|
||||
known_false_positives: Some legitimate administrative tools leverage `dism.exe` to
|
||||
manipulate packages and features of the operating system. Filter as needed.
|
||||
references:
|
||||
- https://thedfirreport.com/2020/11/23/pysa-mespinoza-ransomware/
|
||||
tags:
|
||||
analytic_story:
|
||||
- Windows Defense Evasion Tactics
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1562.001/atomic_red_team/windows-sysmon_dism.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
- T1562
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.parent_process
|
||||
- Processes.original_file_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_path
|
||||
- Processes.process_path
|
||||
- Processes.parent_process_id
|
||||
security_domain: access
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: An instance of $parent_process_name$ spawning $process_name$ was identified
|
||||
on endpoint $dest$ by user $user$ attempting to disable Windows Defender.
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: parent_process_name
|
||||
type: Parent Process
|
||||
role:
|
||||
- Parent Process
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
automated_detection_testing: passed
|
||||
@@ -0,0 +1,81 @@
|
||||
name: Windows Raccine Scheduled Task Deletion
|
||||
id: c9f010da-57ab-11ec-82bd-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-07'
|
||||
author: Michael Haag, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: The following analytic identifies the Raccine Rules Updater scheduled
|
||||
task being deleted. Adversaries may attempt to remove this task in order to prevent
|
||||
the update of Raccine. Raccine is a "ransomware vaccine" created by security researcher
|
||||
Florian Roth, designed to intercept and prevent precursors and active ransomware
|
||||
behavior.
|
||||
search: '| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime from datamodel=Endpoint.Processes where Processes.process_name=schtasks.exe
|
||||
Processes.process="*delete*" AND Processes.process="*Raccine*" by Processes.dest
|
||||
Processes.user Processes.parent_process_name Processes.process_name Processes.original_file_name
|
||||
Processes.process Processes.process_id Processes.parent_process_id | `drop_dm_object_name(Processes)`
|
||||
| `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `windows_raccine_scheduled_task_deletion_filter`'
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node. In addition,
|
||||
confirm the latest CIM App 4.20 or higher is installed and the latest TA for the
|
||||
endpoint product.
|
||||
known_false_positives: False positives should be limited, however filter as needed.
|
||||
references:
|
||||
- https://redcanary.com/blog/blackbyte-ransomware/
|
||||
- https://github.com/Neo23x0/Raccine
|
||||
tags:
|
||||
analytic_story:
|
||||
- Ransomware
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1562.001/atomic_red_team/windows-sysmon_raccine.log
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
mitre_attack_id:
|
||||
- T1562.001
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Processes.dest
|
||||
- Processes.user
|
||||
- Processes.parent_process_name
|
||||
- Processes.parent_process
|
||||
- Processes.original_file_name
|
||||
- Processes.process_name
|
||||
- Processes.process
|
||||
- Processes.process_id
|
||||
- Processes.parent_process_path
|
||||
- Processes.process_path
|
||||
- Processes.parent_process_id
|
||||
security_domain: endpoint
|
||||
impact: 80
|
||||
confidence: 100
|
||||
risk_score: 80
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Defense Evasion
|
||||
message: An instance of $parent_process_name$ spawning $process_name$ was identified
|
||||
on endpoint $dest$ by user user$ attempting to disable Raccines scheduled task.
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: parent_process_name
|
||||
type: Parent Process
|
||||
role:
|
||||
- Parent Process
|
||||
- name: process_name
|
||||
type: Process
|
||||
role:
|
||||
- Child Process
|
||||
automated_detection_testing: passed
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
name: Microsoft Exchange Mailbox Replication service writing Active Server Pages
|
||||
id: 985f322c-57a5-11ec-b9ac-acde48001122
|
||||
version: 1
|
||||
date: '2021-12-07'
|
||||
author: Michael Haag, Splunk
|
||||
type: TTP
|
||||
datamodel:
|
||||
- Endpoint
|
||||
description: 'The following query identifies suspicious .aspx created in 3 paths identified
|
||||
by Microsoft as known drop locations for Exchange exploitation related to HAFNIUM
|
||||
group and recently disclosed vulnerablity named ProxyShell. Paths include: `\HttpProxy\owa\auth\`,
|
||||
`\inetpub\wwwroot\aspnet_client\`, and `\HttpProxy\OAB\`. The analytic is limited to process name MSExchangeMailboxReplication.exe, which typically does not write .aspx files to disk.
|
||||
Upon triage, the suspicious
|
||||
.aspx file will likely look obvious on the surface. inspect the contents for script
|
||||
code inside. Identify additional log sources, IIS included, to review source and
|
||||
other potential exploitation. It is often the case that a particular threat is only
|
||||
applicable to a specific subset of systems in your environment. Typically analytics
|
||||
to detect those threats are written without the benefit of being able to only target
|
||||
those systems as well. Writing analytics against all systems when those behaviors
|
||||
are limited to identifiable subsets of those systems is suboptimal. Consider the
|
||||
case ProxyShell vulnerability on Microsoft Exchange Servers. With asset information,
|
||||
a hunter can limit their analytics to systems that have been identified as Exchange
|
||||
servers. A hunter may start with the theory that the exchange server is communicating
|
||||
with new systems that it has not previously. If this theory is run against all publicly
|
||||
facing systems, the amount of noise it will generate will likely render this theory
|
||||
untenable. However, using the asset information to limit this analytic to just the
|
||||
Exchange servers will reduce the noise allowing the hunter to focus only on the
|
||||
systems where this behavioral change is relevant.'
|
||||
search: '| tstats `security_content_summariesonly` count FROM datamodel=Endpoint.Processes
|
||||
where Processes.process_name=MSExchangeMailboxReplication.exe by _time span=1h Processes.process_id Processes.process_name Processes.process_guid
|
||||
Processes.dest | `drop_dm_object_name(Processes)` | join process_guid, _time [|
|
||||
tstats `security_content_summariesonly` count min(_time) as firstTime max(_time)
|
||||
as lastTime FROM datamodel=Endpoint.Filesystem where Filesystem.file_path IN ("*\\HttpProxy\\owa\\auth\\*",
|
||||
"*\\inetpub\\wwwroot\\aspnet_client\\*", "*\\HttpProxy\\OAB\\*") Filesystem.file_name="*.aspx"
|
||||
by _time span=1h Filesystem.dest Filesystem.file_create_time Filesystem.file_name
|
||||
Filesystem.file_path | `drop_dm_object_name(Filesystem)` | fields _time dest file_create_time
|
||||
file_name file_path process_name process_path process process_guid] | dedup file_create_time
|
||||
| table dest file_create_time, file_name, file_path, process_name | `microsoft_exchange_mailbox_replication_service_writing_active_server_pages_filter`'
|
||||
how_to_implement: To successfully implement this search you need to be ingesting information
|
||||
on process that include the name of the process responsible for the changes from
|
||||
your endpoints into the `Endpoint` datamodel in the `Processes` node and `Filesystem`
|
||||
node.
|
||||
known_false_positives: The query is structured in a way that `action` (read, create)
|
||||
is not defined. Review the results of this query, filter, and tune as necessary.
|
||||
It may be necessary to generate this query specific to your endpoint product.
|
||||
references:
|
||||
- https://redcanary.com/blog/blackbyte-ransomware/
|
||||
tags:
|
||||
analytic_story:
|
||||
- ProxyShell
|
||||
- Ransomware
|
||||
confidence: 90
|
||||
context:
|
||||
- Source:Endpoint
|
||||
- Stage:Exploitation
|
||||
dataset:
|
||||
- https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1505.003/windows-sysmon_proxylogon.log
|
||||
impact: 90
|
||||
kill_chain_phases:
|
||||
- Exploitation
|
||||
message: A file - $file_name$ was written to disk that is related to IIS exploitation
|
||||
related to ProxyShell. Review further file modifications on endpoint
|
||||
$dest$ by user $user$.
|
||||
mitre_attack_id:
|
||||
- T1505
|
||||
- T1505.003
|
||||
- T1190
|
||||
observable:
|
||||
- name: user
|
||||
type: User
|
||||
role:
|
||||
- Victim
|
||||
- name: dest
|
||||
type: Hostname
|
||||
role:
|
||||
- Victim
|
||||
- name: file_name
|
||||
type: File Name
|
||||
role:
|
||||
- Victim
|
||||
product:
|
||||
- Splunk Enterprise
|
||||
- Splunk Enterprise Security
|
||||
- Splunk Cloud
|
||||
required_fields:
|
||||
- _time
|
||||
- Filesystem.file_path
|
||||
- Filesystem.process_id
|
||||
- Filesystem.file_name
|
||||
- Filesystem.file_hash
|
||||
- Filesystem.user
|
||||
- Filesystem.process_guid
|
||||
- Processes.process_name
|
||||
- Processes.process_id
|
||||
- Processes.process_name
|
||||
- Processes.process_guid
|
||||
risk_score: 81
|
||||
security_domain: endpoint
|
||||
|
||||
|
||||
@@ -60,8 +60,8 @@ sidebar:
|
||||
| [Attempt To Delete Services](/endpoint/attempt_to_delete_services/) | [Service Stop](/tags/#service-stop), [Create or Modify System Process](/tags/#create-or-modify-system-process), [Windows Service](/tags/#windows-service) | TTP |
|
||||
| [Attempt To Disable Services](/endpoint/attempt_to_disable_services/) | [Service Stop](/tags/#service-stop) | TTP |
|
||||
| [Attempt To Stop Security Service](/endpoint/attempt_to_stop_security_service/) | [Disable or Modify Tools](/tags/#disable-or-modify-tools), [Impair Defenses](/tags/#impair-defenses) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [OS Credential Dumping](/tags/#os-credential-dumping), [Security Account Manager](/tags/#security-account-manager) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [Security Account Manager](/tags/#security-account-manager), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [OS Credential Dumping](/tags/#os-credential-dumping), [Security Account Manager](/tags/#security-account-manager) | TTP |
|
||||
| [Auto Admin Logon Registry Entry](/endpoint/auto_admin_logon_registry_entry/) | [Credentials in Registry](/tags/#credentials-in-registry), [Unsecured Credentials](/tags/#unsecured-credentials) | TTP |
|
||||
| [BCDEdit Failure Recovery Modification](/endpoint/bcdedit_failure_recovery_modification/) | [Inhibit System Recovery](/tags/#inhibit-system-recovery) | TTP |
|
||||
| [BCDEdit Failure Recovery Modification](/endpoint/bcdedit_failure_recovery_modification/) | [Inhibit System Recovery](/tags/#inhibit-system-recovery) | TTP |
|
||||
|
||||
@@ -11,8 +11,10 @@ sidebar:
|
||||
| Name | Detections | Type |
|
||||
| --------| ---------- | ----------- |
|
||||
| [Active Directory Reset password](/playbooks/active_directory_reset_password/)| None | Response |
|
||||
| [Block Indicators](/playbooks/block_indicators/)| None | Response |
|
||||
| [Crowdstrike Malware Triage](/playbooks/crowdstrike_malware_triage/)| None | Response |
|
||||
| [Delete Detected Files](/playbooks/delete_detected_files/)|[Executable File Written in Administrative SMB Share](/endpoint/executable_file_written_in_administrative_smb_share/)| Response |
|
||||
| [Email Notification for Malware](/playbooks/email_notification_for_malware/)| None | Response |
|
||||
| [Internal Host SSH Investigate](/playbooks/internal_host_ssh_investigate/)| None | Investigation |
|
||||
| [Internal Host SSH Log4j Investigate](/playbooks/internal_host_ssh_log4j_investigate/)| None | Investigation |
|
||||
| [Internal Host SSH Log4j Response](/playbooks/internal_host_ssh_log4j_response/)| None | Response |
|
||||
@@ -22,6 +24,7 @@ sidebar:
|
||||
| [Log4j Investigate](/playbooks/log4j_investigate/)|[Curl Download and Bash Execution](/endpoint/curl_download_and_bash_execution/)[Wget Download and Bash Execution](/endpoint/wget_download_and_bash_execution/)[Linux Java Spawning Shell](/endpoint/linux_java_spawning_shell/)[Java Class File download by Java User Agent](/endpoint/java_class_file_download_by_java_user_agent/)[Outbound Network Connection from Java Using Default Ports](/endpoint/outbound_network_connection_from_java_using_default_ports/)[Log4Shell JNDI Payload Injection Attempt](/web/log4shell_jndi_payload_injection_attempt/)[Log4Shell JNDI Payload Injection with Outbound Connection](/web/log4shell_jndi_payload_injection_with_outbound_connection/)[Detect Outbound LDAP Traffic](/network/detect_outbound_ldap_traffic/)| Investigate |
|
||||
| [Log4j Respond](/playbooks/log4j_respond/)|[Curl Download and Bash Execution](/endpoint/curl_download_and_bash_execution/)[Wget Download and Bash Execution](/endpoint/wget_download_and_bash_execution/)[Linux Java Spawning Shell](/endpoint/linux_java_spawning_shell/)[Java Class File download by Java User Agent](/endpoint/java_class_file_download_by_java_user_agent/)[Outbound Network Connection from Java Using Default Ports](/endpoint/outbound_network_connection_from_java_using_default_ports/)[Log4Shell JNDI Payload Injection Attempt](/web/log4shell_jndi_payload_injection_attempt/)[Log4Shell JNDI Payload Injection with Outbound Connection](/web/log4shell_jndi_payload_injection_with_outbound_connection/)[Detect Outbound LDAP Traffic](/network/detect_outbound_ldap_traffic/)| Response |
|
||||
| [Log4j Splunk Investigation](/playbooks/log4j_splunk_investigation/)| None | Investigation |
|
||||
| [Malware Hunt and Contain](/playbooks/malware_hunt_and_contain/)| None | Response |
|
||||
| [Ransomware Investigate and Contain](/playbooks/ransomware_investigate_and_contain/)|[Conti Common Exec parameter](/endpoint/conti_common_exec_parameter/)| Response |
|
||||
| [Risk Notable Block Indicators](/playbooks/risk_notable_block_indicators/)| None | Response |
|
||||
| [Risk Notable Enrich](/playbooks/risk_notable_enrich/)| None | Investigation |
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "Block Indicators"
|
||||
last_modified_at: 2021-01-21
|
||||
toc: true
|
||||
toc_label: ""
|
||||
tags:
|
||||
- Response
|
||||
- Splunk SOAR
|
||||
- Palo Alto Networks Firewall
|
||||
- CarbonBlack Response
|
||||
- OpenDNS Umbrella
|
||||
---
|
||||
|
||||
[Try in Splunk SOAR](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html){: .btn .btn--success}
|
||||
|
||||
#### Description
|
||||
|
||||
This playbook retrieves IP addresses, domains, and file hashes, blocks them on various services, and adds them to specific blocklists as custom lists.
|
||||
|
||||
- **Type**: Response
|
||||
- **Product**: Splunk SOAR
|
||||
- **Apps**: [Palo Alto Networks Firewall](https://splunkbase.splunk.com/apps/#/search/Palo Alto Networks Firewall/product/soar), [CarbonBlack Response](https://splunkbase.splunk.com/apps/#/search/CarbonBlack Response/product/soar), [OpenDNS Umbrella](https://splunkbase.splunk.com/apps/#/search/OpenDNS Umbrella/product/soar)
|
||||
- **Last Updated**: 2021-01-21
|
||||
- **Author**: Philip Royer, Splunk
|
||||
- **ID**: fc0edc76-ff2b-48b0-5f6f-63da6783fd63
|
||||
|
||||
#### Associated Detections
|
||||
|
||||
|
||||
#### How To Implement
|
||||
This playbook uses the following custom lists: ip_address_blocklist, domain_blocklist, filehash_blocklist. This playbook provides an easy, automated, and straightforward solution to maintaining up-to-date IP address, file, and domain blocklists. The playbook looks for any of the required CEF fields within the container. The CEF value is then cross-referenced with their respective Custom Lists. IP addresses are blocked on a Firewall, while domains are blocked using a blocklist service. The blocking of these two will prevent access to the IOCs. Finally, file hashes are blocked using an endpoint protection service, which will prevent the process from running on affected endpoints within a network. After the IOCs are blocked using various apps, they are added to their respective custom lists as to maintain a running blocklist record.
|
||||
|
||||
#### Playbooks
|
||||

|
||||
|
||||
#### Required field
|
||||
* destinationDnsDomain
|
||||
* destinationAddress
|
||||
* fileHash
|
||||
|
||||
|
||||
#### Reference
|
||||
|
||||
|
||||
|
||||
[*source*](https://github.com/splunk/security_content/tree/develop/playbooks/block_indicators.yml) \| *version*: **1**
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: "Email Notification for Malware"
|
||||
last_modified_at: 2021-01-19
|
||||
toc: true
|
||||
toc_label: ""
|
||||
tags:
|
||||
- Response
|
||||
- Splunk SOAR
|
||||
- VirusTotal
|
||||
- WildFire
|
||||
- CarbonBlack Response
|
||||
- SMTP
|
||||
---
|
||||
|
||||
[Try in Splunk SOAR](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html){: .btn .btn--success}
|
||||
|
||||
#### Description
|
||||
|
||||
This playbook tries to determine if a file is malware and whether or not the file is present on any managed machines. VirusTotal "file reputation" and PAN WildFire "detonate file" are used to determine if a file is malware, and CarbonBlack Response "hunt file" is used to search managed machines for the file. The results of these investigations are summarized in an email to the incident response team.
|
||||
|
||||
- **Type**: Response
|
||||
- **Product**: Splunk SOAR
|
||||
- **Apps**: [VirusTotal](https://splunkbase.splunk.com/apps/#/search/VirusTotal/product/soar), [WildFire](https://splunkbase.splunk.com/apps/#/search/WildFire/product/soar), [CarbonBlack Response](https://splunkbase.splunk.com/apps/#/search/CarbonBlack Response/product/soar), [SMTP](https://splunkbase.splunk.com/apps/#/search/SMTP/product/soar)
|
||||
- **Last Updated**: 2021-01-19
|
||||
- **Author**: Philip Royer, Splunk
|
||||
- **ID**: fb3edc76-ff2b-48b0-5f6f-63da6483fd63
|
||||
|
||||
#### Associated Detections
|
||||
|
||||
|
||||
#### How To Implement
|
||||
Be sure to update asset naming to reflect the asset names configured in your environment.
|
||||
|
||||
#### Playbooks
|
||||

|
||||
|
||||
#### Required field
|
||||
* fileHash
|
||||
* vaultId
|
||||
|
||||
|
||||
#### Reference
|
||||
|
||||
|
||||
|
||||
[*source*](https://github.com/splunk/security_content/tree/develop/playbooks/email_notification_for_malware.yml) \| *version*: **1**
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "Malware Hunt and Contain"
|
||||
last_modified_at: 2021-01-21
|
||||
toc: true
|
||||
toc_label: ""
|
||||
tags:
|
||||
- Response
|
||||
- Splunk SOAR
|
||||
- LDAP
|
||||
- ServiceNow
|
||||
- CarbonBlack Response
|
||||
- VirusTotal
|
||||
---
|
||||
|
||||
[Try in Splunk SOAR](https://www.splunk.com/en_us/software/splunk-security-orchestration-and-automation.html){: .btn .btn--success}
|
||||
|
||||
#### Description
|
||||
|
||||
This playbook investigates and remediates malware infections on the endpoint.
|
||||
|
||||
- **Type**: Response
|
||||
- **Product**: Splunk SOAR
|
||||
- **Apps**: [LDAP](https://splunkbase.splunk.com/apps/#/search/LDAP/product/soar), [ServiceNow](https://splunkbase.splunk.com/apps/#/search/ServiceNow/product/soar), [CarbonBlack Response](https://splunkbase.splunk.com/apps/#/search/CarbonBlack Response/product/soar), [VirusTotal](https://splunkbase.splunk.com/apps/#/search/VirusTotal/product/soar)
|
||||
- **Last Updated**: 2021-01-21
|
||||
- **Author**: Philip Royer, Splunk
|
||||
- **ID**: fb3edc76-ff2b-43c0-5f6f-63da4483fd63
|
||||
|
||||
#### Associated Detections
|
||||
|
||||
|
||||
#### How To Implement
|
||||
Be sure to update asset naming to reflect the asset names configured in your environment.
|
||||
|
||||
#### Playbooks
|
||||

|
||||
|
||||
#### Required field
|
||||
* fileHash
|
||||
|
||||
|
||||
#### Reference
|
||||
|
||||
|
||||
|
||||
[*source*](https://github.com/splunk/security_content/tree/develop/playbooks/malware_hunt_and_contain.yml) \| *version*: **1**
|
||||
@@ -25,7 +25,7 @@ tags:
|
||||
|
||||
#### Description
|
||||
|
||||
DynamicWrapperX is an ActiveX component that can be used in a script to call Windows API functions, but it requires the dynwrapx.dll to be installed and registered. With that, registering or loading dynwrapx.dll to a host highly suspect. Why is it needed? In most malicious instances, During triage, review parallel processes and pivot on the process_guid. Review the registry for any suspicious modifications meant to load dynwrapx.dll. Identify any suspicious module loads of dynwrapx.dll. This will identify the process that will invoke vbs/wscript/cscript.
|
||||
DynamicWrapperX is an ActiveX component that can be used in a script to call Windows API functions, but it requires the dynwrapx.dll to be installed and registered. With that, registering or loading dynwrapx.dll to a host is highly suspicious. In most instances when it is used maliciously, the best way to triage is to review parallel processes and pivot on the process_guid. Review the registry for any suspicious modifications meant to load dynwrapx.dll. Identify any suspicious module loads of dynwrapx.dll. This detection will return and identify the processes that invoke vbs/wscript/cscript.
|
||||
|
||||
- **Type**: TTP
|
||||
- **Product**: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud
|
||||
@@ -58,7 +58,7 @@ DynamicWrapperX is an ActiveX component that can be used in a script to call Win
|
||||
|
||||
|
||||
#### How To Implement
|
||||
To successfully implement this search you need to be ingesting information on process that include the name of the process responsible for the changes from your endpoints into the `Endpoint` datamodel in the `Processes` and `Filesystem` node. In addition, confirm the latest CIM App 4.20 or higher is installed and the latest TA for the endpoint product.
|
||||
To successfully implement this search you need to be ingesting information on processes that include the name of the process responsible for the changes from your endpoints into the `Endpoint` datamodel in the `Processes` and `Filesystem` node. In addition, confirm the latest CIM App 4.20 or higher is installed and the latest TA for the endpoint product.
|
||||
|
||||
#### Required field
|
||||
* _time
|
||||
|
||||
@@ -23,7 +23,7 @@ tags:
|
||||
|
||||
#### Description
|
||||
|
||||
This analytic is to detect a suspicious process having a dns query on known abuse text paste web services, or VoIP, instant messaging and digital distribution platform to download some files. This technique is abused by adversaries, malware attacker and red team to download a malicious file on the target host. This is a good TTP indicator for possible initial access technique. Noise and false positive can be seen if the following instant messaging is allowed or common application in corporate network.
|
||||
This analytic detects a suspicious process making a DNS query via known, abused text-paste web services, VoIP, instant messaging, and digital distribution platforms used to download external files. This technique is abused by adversaries, malware actors, and red teams to download a malicious file on the target host. This is a good TTP indicator for possible initial access techniques. A user will experience false positives if the following instant messaging is allowed or common applications like telegram or discord are allowed in the corporate network.
|
||||
|
||||
- **Type**: TTP
|
||||
- **Product**: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud
|
||||
@@ -56,7 +56,7 @@ This analytic is to detect a suspicious process having a dns query on known abus
|
||||
|
||||
|
||||
#### How To Implement
|
||||
his detection relies on sysmon logs with the Event ID 7, Driver loaded. Please tune your sysmon config that you DriverLoad event for SolarWinds.Orion.Core.BusinessLayer.dll is captured by Sysmon. Additionally, you need sysmon logs for Event ID 22, DNS Query. We suggest to run this detection at least once a day over the last 14 days.
|
||||
This detection relies on sysmon logs with the Event ID 22, DNS Query. We suggest you run this detection at least once a day over the last 14 days.
|
||||
|
||||
#### Required field
|
||||
* _time
|
||||
@@ -73,7 +73,7 @@ his detection relies on sysmon logs with the Event ID 7, Driver loaded. Please t
|
||||
|
||||
|
||||
#### Known False Positives
|
||||
Noise and false positive can be seen if the following instant messaging is allowed to use within corporate network. filter is needed.
|
||||
Noise and false positive can be seen if the following instant messaging is allowed to use within corporate network. In this case, a filter is needed.
|
||||
|
||||
|
||||
#### RBA
|
||||
|
||||
@@ -21,7 +21,7 @@ tags:
|
||||
|
||||
#### Description
|
||||
|
||||
This analytic is to detect a suspicious dxdiag.exe process commandline can collect system info of the target host. This technique was seen in remcos, adversaries and other malware to collect information as part of recon or collection phase of attack. Even this behavior is rarely seen in a corporate network this commandline can be used by network administrator to audit host machine specification. Better to check what it did after it pipes out the result to a file for further processing.
|
||||
This analytic is to detect a suspicious dxdiag.exe process command-line execution. Dxdiag is used to collect the system info of the target host. This technique has been used by Remcos RATS, various actors, and other malware to collect information as part of the recon or collection phase of an attack. This behavior should rarely be seen in a corporate network, but this command line can be used by a network administrator to audit host machine specifications. Thus in some rare cases, this detection will contain false positives in its results. To triage further, analyze what commands were passed after it pipes out the result to a file for further processing.
|
||||
|
||||
- **Type**: Hunting
|
||||
- **Product**: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud
|
||||
@@ -75,7 +75,7 @@ To successfully implement this search you need to be ingesting information on pr
|
||||
|
||||
|
||||
#### Known False Positives
|
||||
this commandline can be used by network administrator to audit host machine specification.filter is needed.
|
||||
This commandline can be used by a network administrator to audit host machine specifications. Thus, a filter is needed.
|
||||
|
||||
|
||||
#### RBA
|
||||
|
||||
@@ -23,7 +23,7 @@ tags:
|
||||
|
||||
#### Description
|
||||
|
||||
This analytic will detect a suspicious process contains a commandline parameter related to web browser credential dumper. This technique was used by Remcos RAT malware where it use the techique of Nirsoft webbrowserpassview.exe application to dump web browser credentials. Remcos use the "/stext" commandline to dump the credential in text format. This Hunting query is good indicator to look further for possible remcos infection within the network or possible compromised host. Since the detections is only base on the parameter command and the possible path where it will drop the text credential information, It may catch normal tools that having same command and behavior.
|
||||
This analytic will detect if a suspicious process contains a commandline parameter related to a web browser credential dumper. This technique is used by Remcos RAT malware which uses the Nirsoft webbrowserpassview.exe application to dump web browser credentials. Remcos uses the "/stext" command line to dump the credentials in text format. This Hunting query is a good indicator of hosts suffering from possible Remcos RAT infection. Since the hunting query is based on the parameter command and the possible path where it will save the text credential information, it may catch normal tools that are using the same command and behavior.
|
||||
|
||||
- **Type**: Hunting
|
||||
- **Product**: Splunk Enterprise, Splunk Enterprise Security, Splunk Cloud
|
||||
|
||||
@@ -35,8 +35,8 @@ The detection searches in this Analytic Story monitor access to the Local Securi
|
||||
| Name | Technique | Type |
|
||||
| ----------- | ----------- |--------------|
|
||||
| [Access LSASS Memory for Dump Creation](/endpoint/access_lsass_memory_for_dump_creation/) | [LSASS Memory](/tags/#lsass-memory), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [OS Credential Dumping](/tags/#os-credential-dumping), [Security Account Manager](/tags/#security-account-manager) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [Security Account Manager](/tags/#security-account-manager), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
| [Attempted Credential Dump From Registry via Reg exe](/endpoint/attempted_credential_dump_from_registry_via_reg_exe/) | [OS Credential Dumping](/tags/#os-credential-dumping), [Security Account Manager](/tags/#security-account-manager) | TTP |
|
||||
| [Create Remote Thread into LSASS](/endpoint/create_remote_thread_into_lsass/) | [LSASS Memory](/tags/#lsass-memory), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
| [Creation of Shadow Copy](/endpoint/creation_of_shadow_copy/) | [NTDS](/tags/#ntds), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
| [Creation of Shadow Copy with wmic and powershell](/endpoint/creation_of_shadow_copy_with_wmic_and_powershell/) | [NTDS](/tags/#ntds), [OS Credential Dumping](/tags/#os-credential-dumping) | TTP |
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ feature_row:
|
||||
- image_path: /static/feature_playbooks.png
|
||||
alt: "100% free"
|
||||
title: "Playbooks"
|
||||
excerpt: "See all **23** sets of steps 🐾 to automatically response to a threat."
|
||||
excerpt: "See all **26** sets of steps 🐾 to automatically response to a threat."
|
||||
url: "/playbooks"
|
||||
btn_class: "btn--primary"
|
||||
btn_label: "Explore"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
@@ -0,0 +1,297 @@
|
||||
"""
|
||||
This playbook retrieves IP addresses, domains, and file hashes, blocks them on various services, and adds them to specific blocklists as custom lists.
|
||||
"""
|
||||
|
||||
import phantom.rules as phantom
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
def on_start(container):
|
||||
phantom.debug('on_start() called')
|
||||
|
||||
# call 'filter_1' block
|
||||
filter_1(container=container)
|
||||
|
||||
# call 'filter_2' block
|
||||
filter_2(container=container)
|
||||
|
||||
# call 'filter_3' block
|
||||
filter_3(container=container)
|
||||
|
||||
return
|
||||
|
||||
def block_ip_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('block_ip_1() called')
|
||||
|
||||
# collect data for 'block_ip_1' call
|
||||
filtered_artifacts_data_1 = phantom.collect2(container=container, datapath=['filtered-data:filter_4:condition_1:artifact:*.cef.destinationAddress', 'filtered-data:filter_4:condition_1:artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'block_ip_1' call
|
||||
for filtered_artifacts_item_1 in filtered_artifacts_data_1:
|
||||
if filtered_artifacts_item_1[0]:
|
||||
parameters.append({
|
||||
'ip': filtered_artifacts_item_1[0],
|
||||
'vsys': "",
|
||||
'is_source_address': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_artifacts_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="block ip", parameters=parameters, assets=['pan'], callback=add_to_IP_blocklist, name="block_ip_1")
|
||||
|
||||
return
|
||||
|
||||
def block_hash_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('block_hash_2() called')
|
||||
|
||||
# collect data for 'block_hash_2' call
|
||||
filtered_artifacts_data_1 = phantom.collect2(container=container, datapath=['filtered-data:filter_6:condition_1:artifact:*.cef.fileHash', 'filtered-data:filter_6:condition_1:artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'block_hash_2' call
|
||||
for filtered_artifacts_item_1 in filtered_artifacts_data_1:
|
||||
if filtered_artifacts_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_artifacts_item_1[0],
|
||||
'comment': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_artifacts_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="block hash", parameters=parameters, assets=['carbonblack'], callback=add_to_hash_blocklist, name="block_hash_2")
|
||||
|
||||
return
|
||||
|
||||
def block_domain_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('block_domain_1() called')
|
||||
|
||||
# collect data for 'block_domain_1' call
|
||||
filtered_artifacts_data_1 = phantom.collect2(container=container, datapath=['filtered-data:filter_5:condition_1:artifact:*.cef.destinationDnsDomain', 'filtered-data:filter_5:condition_1:artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'block_domain_1' call
|
||||
for filtered_artifacts_item_1 in filtered_artifacts_data_1:
|
||||
if filtered_artifacts_item_1[0]:
|
||||
parameters.append({
|
||||
'domain': filtered_artifacts_item_1[0],
|
||||
'disable_safeguards': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_artifacts_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="block domain", parameters=parameters, assets=['opendns_umbrella'], callback=add_to_domain_blocklist, name="block_domain_1")
|
||||
|
||||
return
|
||||
|
||||
def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_2() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["artifact:*.cef.destinationDnsDomain", "!=", ""],
|
||||
],
|
||||
name="filter_2:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
filter_5(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_3() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["artifact:*.cef.fileHash", "!=", ""],
|
||||
],
|
||||
name="filter_3:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
filter_6(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Checking to see if this domain address is in the custom list called "domain_blocklist"
|
||||
"""
|
||||
def filter_5(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_5() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["filtered-data:filter_2:condition_1:artifact:*.cef.destinationDnsDomain", "in", "custom_list:domain_blocklist"],
|
||||
],
|
||||
name="filter_5:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
block_domain_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Checking to see if this filehash is in the custom list called "filehash_blocklist"
|
||||
"""
|
||||
def filter_6(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_6() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["filtered-data:filter_3:condition_1:artifact:*.cef.fileHash", "in", "custom_list:filehash_blocklist"],
|
||||
],
|
||||
name="filter_6:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
block_hash_2(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
The file hash is added to the custom list 'filehash_blocklist' in order to prevent the Playbook from attempting to block a file hash that has already been blocked.
|
||||
"""
|
||||
def add_to_hash_blocklist(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('add_to_hash_blocklist() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'add_to_hash_blocklist' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['block_hash_2:action_result.parameter.hash', 'block_hash_2:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'add_to_hash_blocklist' call
|
||||
for results_item_1 in results_data_1:
|
||||
if results_item_1[0]:
|
||||
parameters.append({
|
||||
'list': "custom_list:filehash_blocklist",
|
||||
'create': True,
|
||||
'new_row': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="add listitem", parameters=parameters, assets=['phantom'], name="add_to_hash_blocklist", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
The domain is added to the custom list 'domain_blocklist' in order to prevent the Playbook from attempting to block a domain that has already been blocked.
|
||||
"""
|
||||
def add_to_domain_blocklist(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('add_to_domain_blocklist() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'add_to_domain_blocklist' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['block_domain_1:action_result.parameter.domain', 'block_domain_1:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'add_to_domain_blocklist' call
|
||||
for results_item_1 in results_data_1:
|
||||
if results_item_1[0]:
|
||||
parameters.append({
|
||||
'list': "custom_list:domain_blocklist",
|
||||
'create': True,
|
||||
'new_row': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="add listitem", parameters=parameters, assets=['phantom'], name="add_to_domain_blocklist", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
The IP address is added to the custom list 'ip_address_blocklist' in order to prevent the Playbook from attempting to block an IP address that has already been blocked.
|
||||
"""
|
||||
def add_to_IP_blocklist(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('add_to_IP_blocklist() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'add_to_IP_blocklist' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['block_ip_1:action_result.parameter.ip', 'block_ip_1:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'add_to_IP_blocklist' call
|
||||
for results_item_1 in results_data_1:
|
||||
if results_item_1[0]:
|
||||
parameters.append({
|
||||
'list': "custom_list:ip_address_blocklist",
|
||||
'create': True,
|
||||
'new_row': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="add listitem", parameters=parameters, assets=['phantom'], name="add_to_IP_blocklist", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def filter_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_1() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["artifact:*.cef.destinationAddress", "!=", ""],
|
||||
],
|
||||
name="filter_1:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
filter_4(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Checking to see if this IP address is in the custom list called "ip_address_blocklist"
|
||||
"""
|
||||
def filter_4(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_4() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["filtered-data:filter_1:condition_1:artifact:*.cef.destinationAddress", "not in", "custom_list:ip_address_blocklist"],
|
||||
],
|
||||
name="filter_4:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
block_ip_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
def on_finish(container, summary):
|
||||
phantom.debug('on_finish() called')
|
||||
# This function is called after all actions are completed.
|
||||
# summary of all the action and/or all details of actions
|
||||
# can be collected here.
|
||||
|
||||
# summary_json = phantom.get_summary()
|
||||
# if 'result' in summary_json:
|
||||
# for action_result in summary_json['result']:
|
||||
# if 'action_run_id' in action_result:
|
||||
# action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
|
||||
# phantom.debug(action_results)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Block Indicators
|
||||
id: fc0edc76-ff2b-48b0-5f6f-63da6783fd63
|
||||
version: 1
|
||||
date: '2021-01-21'
|
||||
author: Philip Royer, Splunk
|
||||
type: Response
|
||||
description: This playbook retrieves IP addresses, domains, and file hashes, blocks them on various services, and adds them to specific blocklists as custom lists.
|
||||
playbook: block_indicators
|
||||
how_to_implement: "This playbook uses the following custom lists: ip_address_blocklist, domain_blocklist, filehash_blocklist. This playbook provides an easy, automated, and straightforward solution to maintaining up-to-date IP address, file, and domain blocklists. The playbook looks for any of the required CEF fields within the container. The CEF value is then cross-referenced with their respective Custom Lists. IP addresses are blocked on a Firewall, while domains are blocked using a blocklist service. The blocking of these two will prevent access to the IOCs. Finally, file hashes are blocked using an endpoint protection service, which will prevent the process from running on affected endpoints within a network. After the IOCs are blocked using various apps, they are added to their respective custom lists as to maintain a running blocklist record."
|
||||
references: []
|
||||
app_list:
|
||||
- "Palo Alto Networks Firewall"
|
||||
- "CarbonBlack Response"
|
||||
- "OpenDNS Umbrella"
|
||||
tags:
|
||||
platform_tags:
|
||||
- Response
|
||||
playbook_fields:
|
||||
- destinationDnsDomain
|
||||
- destinationAddress
|
||||
- fileHash
|
||||
product:
|
||||
- Splunk SOAR
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 221 KiB |
@@ -0,0 +1,338 @@
|
||||
"""
|
||||
This playbook tries to determine if a file is malware and whether or not the file is present on any managed machines. VirusTotal "file reputation" and PAN WildFire "detonate file" are used to determine if a file is malware, and CarbonBlack Response "hunt file" is used to search managed machines for the file. The results of these investigations are summarized in an email to the incident response team.
|
||||
"""
|
||||
|
||||
import phantom.rules as phantom
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
def on_start(container):
|
||||
phantom.debug('on_start() called')
|
||||
|
||||
# call 'filter_1' block
|
||||
filter_1(container=container)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Run a reputation lookup on the fileHash to determine how many antivirus engines recognize it as malware.
|
||||
"""
|
||||
def file_reputation_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('file_reputation_1() called')
|
||||
|
||||
# collect data for 'file_reputation_1' call
|
||||
filtered_artifacts_data_1 = phantom.collect2(container=container, datapath=['filtered-data:filter_1:condition_1:artifact:*.cef.fileHash', 'filtered-data:filter_1:condition_1:artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'file_reputation_1' call
|
||||
for filtered_artifacts_item_1 in filtered_artifacts_data_1:
|
||||
if filtered_artifacts_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_artifacts_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_artifacts_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="file reputation", parameters=parameters, assets=['virustotal'], callback=filter_2, name="file_reputation_1")
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Hunt for binaries with the malicious fileHash across endpoints.
|
||||
"""
|
||||
def hunt_file_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('hunt_file_2() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'hunt_file_2' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_5:condition_1:detonate_file_1:action_result.data.*.file_info.md5", "filtered-data:filter_5:condition_1:detonate_file_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'hunt_file_2' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
if filtered_results_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'type': "",
|
||||
'range': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="hunt file", parameters=parameters, assets=['carbonblack'], callback=join_format_for_emailer, name="hunt_file_2")
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Detonate file requires a Vault file, so only proceed if vaultId is not null.
|
||||
"""
|
||||
def filter_4(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_4() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["filtered-data:filter_3:condition_1:artifact:*.cef.vaultId", "!=", ""],
|
||||
],
|
||||
name="filter_4:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
detonate_file_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Only hunt files that are considered malware per the sandbox (malware == yes).
|
||||
"""
|
||||
def filter_5(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_5() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["detonate_file_1:action_result.summary.malware", "==", "yes"],
|
||||
],
|
||||
name="filter_5:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
hunt_file_2(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Match hashes with less than 10 positives to artifacts to identify filtered_artifacts.
|
||||
"""
|
||||
def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_3() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["filtered-data:filter_2:condition_2:file_reputation_1:action_result.parameter.hash", "==", "artifact:*.cef.fileHash"],
|
||||
],
|
||||
name="filter_3:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
filter_4(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
If 10 or more antivirus engines flagged the hash, proceed directly to hunt for the file. Else, use a sandbox to detonate the executable first.
|
||||
"""
|
||||
def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_2() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", ">=", 10],
|
||||
],
|
||||
name="filter_2:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
hunt_file_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 2
|
||||
matched_artifacts_2, matched_results_2 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", "<", 10],
|
||||
],
|
||||
name="filter_2:condition_2")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_2 or matched_results_2:
|
||||
filter_3(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_2, filtered_results=matched_results_2)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Hunt for binaries with the malicious fileHash across endpoints.
|
||||
"""
|
||||
def hunt_file_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('hunt_file_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'hunt_file_1' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_2:condition_1:file_reputation_1:action_result.parameter.hash", "filtered-data:filter_2:condition_1:file_reputation_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'hunt_file_1' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
if filtered_results_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'type': "",
|
||||
'range': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="hunt file", parameters=parameters, assets=['carbonblack'], callback=join_format_for_emailer, name="hunt_file_1")
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Only process artifacts that have a CEF fileHash.
|
||||
"""
|
||||
def filter_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_1() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
conditions=[
|
||||
["artifact:*.cef.fileHash", "!=", ""],
|
||||
],
|
||||
name="filter_1:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
file_reputation_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Detonate the file(s) in the vault.
|
||||
"""
|
||||
def detonate_file_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('detonate_file_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'detonate_file_1' call
|
||||
filtered_artifacts_data_1 = phantom.collect2(container=container, datapath=['filtered-data:filter_4:condition_1:artifact:*.cef.vaultId', 'filtered-data:filter_4:condition_1:artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'detonate_file_1' call
|
||||
for filtered_artifacts_item_1 in filtered_artifacts_data_1:
|
||||
if filtered_artifacts_item_1[0]:
|
||||
parameters.append({
|
||||
'vault_id': filtered_artifacts_item_1[0],
|
||||
'file_name': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_artifacts_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="detonate file", parameters=parameters, assets=['wildfire'], callback=filter_5, name="detonate_file_1")
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Send the formatted string as an email.
|
||||
"""
|
||||
def send_email_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('send_email_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'send_email_1' call
|
||||
formatted_data_1 = phantom.get_format_data(name='format_for_emailer')
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'send_email_1' call
|
||||
parameters.append({
|
||||
'cc': "",
|
||||
'to': "recipient@phantom.localhost",
|
||||
'bcc': "",
|
||||
'body': formatted_data_1,
|
||||
'from': "automation@phantom.localhost",
|
||||
'headers': "",
|
||||
'subject': "Malware event confirmed",
|
||||
'attachments': "",
|
||||
})
|
||||
|
||||
phantom.act(action="send email", parameters=parameters, assets=['smtp'], name="send_email_1")
|
||||
|
||||
return
|
||||
|
||||
"""
|
||||
Format all results for an email.
|
||||
"""
|
||||
def format_for_emailer(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('format_for_emailer() called')
|
||||
|
||||
template = """Malware in a security event has been confirmed using file reputation and/or file detonation services.
|
||||
|
||||
Reputation Results:
|
||||
Using file reputation services, the following file hashes have been identified as malware:
|
||||
{0}
|
||||
|
||||
EDR tool detects that the above file hashes are present on the following endpoints:
|
||||
{1}
|
||||
|
||||
Detonation Results:
|
||||
Using sandboxing services, the following file hashes have been identified as malware:
|
||||
{2}
|
||||
|
||||
The Phantom Vault ID for the malicious files, as determined by the sandbox service, are as follows:
|
||||
{3}
|
||||
|
||||
EDR tool detects that the file hashes indicated as positives per the sandbox service are present on the following endpoints:
|
||||
{4}
|
||||
|
||||
Container id: {5}
|
||||
|
||||
[EOM]"""
|
||||
|
||||
# parameter list for template variable replacement
|
||||
parameters = [
|
||||
"hunt_file_1:action_result.parameter.hash",
|
||||
"hunt_file_1:action_result.data.*.process.results.*.hostname",
|
||||
"filtered-data:filter_5:condition_1:detonate_file_1:action_result.data.*.file_info.md5",
|
||||
"filtered-data:filter_5:condition_1:detonate_file_1:action_result.parameter.vault_id",
|
||||
"hunt_file_2:action_result.data.*.process.results.*.hostname",
|
||||
"container:id",
|
||||
]
|
||||
|
||||
phantom.format(container=container, template=template, parameters=parameters, name="format_for_emailer")
|
||||
|
||||
send_email_1(container=container)
|
||||
|
||||
return
|
||||
|
||||
def join_format_for_emailer(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None):
|
||||
phantom.debug('join_format_for_emailer() called')
|
||||
|
||||
# check if all connected incoming playbooks, actions, or custom functions are done i.e. have succeeded or failed
|
||||
if phantom.completed(action_names=['hunt_file_1', 'hunt_file_2']):
|
||||
|
||||
# call connected block "format_for_emailer"
|
||||
format_for_emailer(container=container, handle=handle)
|
||||
|
||||
return
|
||||
|
||||
def on_finish(container, summary):
|
||||
phantom.debug('on_finish() called')
|
||||
# This function is called after all actions are completed.
|
||||
# summary of all the action and/or all details of actions
|
||||
# can be collected here.
|
||||
|
||||
# summary_json = phantom.get_summary()
|
||||
# if 'result' in summary_json:
|
||||
# for action_result in summary_json['result']:
|
||||
# if 'action_run_id' in action_result:
|
||||
# action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
|
||||
# phantom.debug(action_results)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Email Notification for Malware
|
||||
id: fb3edc76-ff2b-48b0-5f6f-63da6483fd63
|
||||
version: 1
|
||||
date: '2021-01-19'
|
||||
author: Philip Royer, Splunk
|
||||
type: Response
|
||||
description: This playbook tries to determine if a file is malware and whether or not the file is present on any managed machines. VirusTotal "file reputation" and PAN WildFire "detonate file" are used to determine if a file is malware, and CarbonBlack Response "hunt file" is used to search managed machines for the file. The results of these investigations are summarized in an email to the incident response team.
|
||||
playbook: email_notification_for_malware
|
||||
how_to_implement: "Be sure to update asset naming to reflect the asset names configured in your environment."
|
||||
references: []
|
||||
app_list:
|
||||
- "VirusTotal"
|
||||
- "WildFire"
|
||||
- "CarbonBlack Response"
|
||||
- "SMTP"
|
||||
tags:
|
||||
platform_tags:
|
||||
- Response
|
||||
playbook_fields:
|
||||
- fileHash
|
||||
- vaultId
|
||||
product:
|
||||
- Splunk SOAR
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 375 KiB |
@@ -0,0 +1,456 @@
|
||||
"""
|
||||
This playbook investigates and remediates malware infections on the endpoint.
|
||||
"""
|
||||
|
||||
import phantom.rules as phantom
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
##############################
|
||||
# Start - Global Code Block
|
||||
|
||||
"""Malicous file detected on endpoint"""
|
||||
|
||||
# End - Global Code block
|
||||
##############################
|
||||
|
||||
def on_start(container):
|
||||
phantom.debug('on_start() called')
|
||||
|
||||
# call 'file_reputation_1' block
|
||||
file_reputation_1(container=container)
|
||||
|
||||
return
|
||||
|
||||
def filter_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_3() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", ">", 5],
|
||||
["file_reputation_1:action_result.summary.positives", "<=", 10],
|
||||
],
|
||||
logical_operator='and',
|
||||
name="filter_3:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
create_ticket_3(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
def shutdown_system_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('shutdown_system_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'shutdown_system_1' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['hunt_file_2:action_result.data.*.process.results.*.hostname', 'hunt_file_2:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'shutdown_system_1' call
|
||||
for results_item_1 in results_data_1:
|
||||
parameters.append({
|
||||
'ph': "",
|
||||
'message': "",
|
||||
'wait_time': "",
|
||||
'ip_hostname': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="shutdown system", parameters=parameters, assets=['domainctrl1'], callback=join_filter_2, name="shutdown_system_1", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def create_ticket_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'create_ticket_2' call
|
||||
|
||||
disabled_users = set(phantom.collect2(datapath='disable_user_1:action_result.parameter.username'))
|
||||
blocked_hashes = set(phantom.collect2(datapath='block_hash_3:action_result.parameter.hash'))
|
||||
loggedoff_users = set(phantom.collect2(datapath='logoff_user_1:action_result.parameter.username'))
|
||||
shutdown_systems = set(phantom.collect2(datapath='shutdown_system_1:action_result.parameter.ip_hostname'))
|
||||
file_reputation = phantom.collect2(datapath=['file_reputation_1:filtered-action_result.parameter.hash',
|
||||
'file_reputation_1:filtered-action_result.summary.positives'])
|
||||
detected_users = set(phantom.collect2(datapath='hunt_file_2:action_result.data.*.process.results.*.username'))
|
||||
detected_systems = set(phantom.collect2(datapath='hunt_file_2:action_result.data.*.process.results.*.hostname'))
|
||||
|
||||
title = "Virus Detected on {0} devices".format(len(detected_systems))
|
||||
|
||||
description = "Hashes sumbitted with detections:\n{0}\n\n".format(", ".join(["{0} ({1})".format(*fr) for fr in file_reputation]))
|
||||
description += "File was found on {0} devices:\n{1}\n\n".format(len(detected_systems), ', '.join(detected_systems))
|
||||
description += "This impacts at least {0} users:\n{1}\n\n".format(len(detected_users), ', '.join(detected_users))
|
||||
if len(blocked_hashes):
|
||||
description += "{0} hashes were submitted for blocking:\n{1}\n\n".format(len(blocked_hashes), ", ".join(blocked_hashes))
|
||||
if len(loggedoff_users):
|
||||
description += "{0} users were forced to logoff:\n{1}\n\n".format(len(loggedoff_users), ", ".join(loggedoff_users))
|
||||
if len(disabled_users):
|
||||
description += "{0} user accounts were disabled:\n{1}\n\n".format(len(disabled_users), ", ".join(disabled_users))
|
||||
if len(shutdown_systems):
|
||||
description += "{0} systems were shutdown:\n{1}\n\n".format(len(shutdown_systems), ", ".join(shutdown_systems))
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'create_ticket_2' call
|
||||
parameters.append({
|
||||
'short_description': title,
|
||||
'description': description,
|
||||
'fields': "",
|
||||
})
|
||||
|
||||
if parameters:
|
||||
phantom.act("create ticket", parameters=parameters, assets=['servicenow'], name="create_ticket_2", parent_action=action)
|
||||
else:
|
||||
phantom.error("'create_ticket_2' will not be executed due to lack of parameters")
|
||||
|
||||
return
|
||||
|
||||
def filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_2() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", ">", 10],
|
||||
],
|
||||
name="filter_2:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
create_ticket_2(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
return
|
||||
|
||||
def join_filter_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None):
|
||||
phantom.debug('join_filter_2() called')
|
||||
|
||||
# check if all connected incoming playbooks, actions, or custom functions are done i.e. have succeeded or failed
|
||||
if phantom.completed(action_names=['logoff_user_1', 'shutdown_system_1', 'disable_user_1', 'block_hash_3']):
|
||||
|
||||
# call connected block "filter_2"
|
||||
filter_2(container=container, handle=handle)
|
||||
|
||||
return
|
||||
|
||||
def logoff_user_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('logoff_user_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'logoff_user_1' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['hunt_file_2:action_result.data.*.process.results.*.hostname', 'hunt_file_2:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'logoff_user_1' call
|
||||
for results_item_1 in results_data_1:
|
||||
parameters.append({
|
||||
'username': "",
|
||||
'ip_hostname': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="logoff user", parameters=parameters, assets=['domainctrl1'], callback=join_filter_2, name="logoff_user_1", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def filter_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('filter_1() called')
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 1
|
||||
matched_artifacts_1, matched_results_1 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", ">", 5],
|
||||
["file_reputation_1:action_result.summary.positives", "<=", 10],
|
||||
],
|
||||
logical_operator='and',
|
||||
name="filter_1:condition_1")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_1 or matched_results_1:
|
||||
hunt_file_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
get_file_2(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_1, filtered_results=matched_results_1)
|
||||
|
||||
# collect filtered artifact ids for 'if' condition 2
|
||||
matched_artifacts_2, matched_results_2 = phantom.condition(
|
||||
container=container,
|
||||
action_results=results,
|
||||
conditions=[
|
||||
["file_reputation_1:action_result.summary.positives", ">", 10],
|
||||
],
|
||||
name="filter_1:condition_2")
|
||||
|
||||
# call connected blocks if filtered artifacts or results
|
||||
if matched_artifacts_2 or matched_results_2:
|
||||
hunt_file_2(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_2, filtered_results=matched_results_2)
|
||||
get_file_3(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function, filtered_artifacts=matched_artifacts_2, filtered_results=matched_results_2)
|
||||
|
||||
return
|
||||
|
||||
def hunt_file_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('hunt_file_2() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'hunt_file_2' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_1:condition_2:file_reputation_1:action_result.parameter.hash", "filtered-data:filter_1:condition_2:file_reputation_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'hunt_file_2' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
if filtered_results_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'type': "",
|
||||
'range': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="hunt file", parameters=parameters, assets=['carbonblack'], callback=hunt_file_2_callback, name="hunt_file_2")
|
||||
|
||||
return
|
||||
|
||||
def hunt_file_2_callback(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None):
|
||||
phantom.debug('hunt_file_2_callback() called')
|
||||
|
||||
disable_user_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function)
|
||||
logoff_user_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function)
|
||||
shutdown_system_1(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function)
|
||||
block_hash_3(action=action, success=success, container=container, results=results, handle=handle, custom_function=custom_function)
|
||||
|
||||
return
|
||||
|
||||
def get_file_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('get_file_3() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'get_file_3' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_1:condition_2:file_reputation_1:action_result.parameter.hash", "filtered-data:filter_1:condition_2:file_reputation_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'get_file_3' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'ph_0': "",
|
||||
'offset': "",
|
||||
'get_count': "",
|
||||
'sensor_id': "",
|
||||
'file_source': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="get file", parameters=parameters, assets=['carbonblack'], name="get_file_3")
|
||||
|
||||
return
|
||||
|
||||
def get_file_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('get_file_2() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'get_file_2' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_1:condition_1:file_reputation_1:action_result.parameter.hash", "filtered-data:filter_1:condition_1:file_reputation_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'get_file_2' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'ph_0': "",
|
||||
'offset': "",
|
||||
'get_count': "",
|
||||
'sensor_id': "",
|
||||
'file_source': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="get file", parameters=parameters, assets=['carbonblack'], name="get_file_2")
|
||||
|
||||
return
|
||||
|
||||
def create_ticket_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'create_ticket_2' call
|
||||
|
||||
file_reputation = phantom.collect2(datapath=['file_reputation_1:filtered-action_result.parameter.hash',
|
||||
'file_reputation_1:filtered-action_result.summary.positives'])
|
||||
blocked_hashes = set(phantom.collect2(datapath='block_hash_2:action_result.parameter.hash'))
|
||||
detected_users = set(phantom.collect2(datapath='hunt_file_1:action_result.data.*.process.results.*.username'))
|
||||
detected_systems = set(phantom.collect2(datapath='hunt_file_1:action_result.data.*.process.results.*.hostname'))
|
||||
|
||||
title = "Virus Detected on {0} devices".format(len(detected_systems))
|
||||
|
||||
description = "Hashes sumbitted with detections:\n{0}\n\n".format(", ".join(["{0} ({1})".format(*fr) for fr in file_reputation]))
|
||||
description += "File was found on {0} devices:\n{1}\n\n".format(len(detected_systems), ', '.join(detected_systems))
|
||||
description += "This impacts at least {0} users:\n{1}\n\n".format(len(detected_users), ', '.join(detected_users))
|
||||
if len(blocked_hashes):
|
||||
description += "{0} hashes were submitted for blocking:\n{1}\n\n".format(len(blocked_hashes), ", ".join(blocked_hashes))
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'create_ticket_2' call
|
||||
parameters.append({
|
||||
'short_description': title,
|
||||
'description': description,
|
||||
'fields': "",
|
||||
})
|
||||
|
||||
if parameters:
|
||||
phantom.act("create ticket", parameters=parameters, assets=['servicenow'], name="create_ticket_3", parent_action=action)
|
||||
else:
|
||||
phantom.error("'create_ticket_3' will not be executed due to lack of parameters")
|
||||
|
||||
return
|
||||
|
||||
def disable_user_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('disable_user_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'disable_user_1' call
|
||||
results_data_1 = phantom.collect2(container=container, datapath=['hunt_file_2:action_result.data.*.process.results.*.username', 'hunt_file_2:action_result.parameter.context.artifact_id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'disable_user_1' call
|
||||
for results_item_1 in results_data_1:
|
||||
if results_item_1[0]:
|
||||
parameters.append({
|
||||
'username': results_item_1[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="disable user", parameters=parameters, assets=['domainctrl1'], callback=join_filter_2, name="disable_user_1", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def block_hash_3(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('block_hash_3() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'block_hash_3' call
|
||||
inputs_data_1 = phantom.collect2(container=container, datapath=['hunt_file_2:artifact:*.cef.fileHash', 'hunt_file_2:artifact:*.id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'block_hash_3' call
|
||||
for inputs_item_1 in inputs_data_1:
|
||||
if inputs_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': inputs_item_1[0],
|
||||
'comment': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': inputs_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="block hash", parameters=parameters, assets=['carbonblack'], callback=join_filter_2, name="block_hash_3", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def hunt_file_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('hunt_file_1() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'hunt_file_1' call
|
||||
filtered_results_data_1 = phantom.collect2(container=container, datapath=["filtered-data:filter_1:condition_1:file_reputation_1:action_result.parameter.hash", "filtered-data:filter_1:condition_1:file_reputation_1:action_result.parameter.context.artifact_id"])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'hunt_file_1' call
|
||||
for filtered_results_item_1 in filtered_results_data_1:
|
||||
if filtered_results_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': filtered_results_item_1[0],
|
||||
'type': "binary",
|
||||
'range': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': filtered_results_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="hunt file", parameters=parameters, assets=['carbonblack'], callback=block_hash_2, name="hunt_file_1")
|
||||
|
||||
return
|
||||
|
||||
def block_hash_2(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('block_hash_2() called')
|
||||
|
||||
#phantom.debug('Action: {0} {1}'.format(action['name'], ('SUCCEEDED' if success else 'FAILED')))
|
||||
|
||||
# collect data for 'block_hash_2' call
|
||||
inputs_data_1 = phantom.collect2(container=container, datapath=['hunt_file_1:artifact:*.cef.fileHash', 'hunt_file_1:artifact:*.id'], action_results=results)
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'block_hash_2' call
|
||||
for inputs_item_1 in inputs_data_1:
|
||||
if inputs_item_1[0]:
|
||||
parameters.append({
|
||||
'hash': inputs_item_1[0],
|
||||
'comment': "",
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': inputs_item_1[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="block hash", parameters=parameters, assets=['carbonblack'], callback=filter_3, name="block_hash_2", parent_action=action)
|
||||
|
||||
return
|
||||
|
||||
def file_reputation_1(action=None, success=None, container=None, results=None, handle=None, filtered_artifacts=None, filtered_results=None, custom_function=None, **kwargs):
|
||||
phantom.debug('file_reputation_1() called')
|
||||
|
||||
# collect data for 'file_reputation_1' call
|
||||
container_data = phantom.collect2(container=container, datapath=['artifact:*.cef.fileHash', 'artifact:*.id'])
|
||||
|
||||
parameters = []
|
||||
|
||||
# build parameters list for 'file_reputation_1' call
|
||||
for container_item in container_data:
|
||||
if container_item[0]:
|
||||
parameters.append({
|
||||
'hash': container_item[0],
|
||||
# context (artifact id) is added to associate results with the artifact
|
||||
'context': {'artifact_id': container_item[1]},
|
||||
})
|
||||
|
||||
phantom.act(action="file reputation", parameters=parameters, assets=['virustotal'], callback=filter_1, name="file_reputation_1")
|
||||
|
||||
return
|
||||
|
||||
def on_finish(container, summary):
|
||||
phantom.debug('on_finish() called')
|
||||
# This function is called after all actions are completed.
|
||||
# summary of all the action and/or all details of actions
|
||||
# can be collected here.
|
||||
|
||||
# summary_json = phantom.get_summary()
|
||||
# if 'result' in summary_json:
|
||||
# for action_result in summary_json['result']:
|
||||
# if 'action_run_id' in action_result:
|
||||
# action_results = phantom.get_action_results(action_run_id=action_result['action_run_id'], result_data=False, flatten=False)
|
||||
# phantom.debug(action_results)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Malware Hunt and Contain
|
||||
id: fb3edc76-ff2b-43c0-5f6f-63da4483fd63
|
||||
version: 1
|
||||
date: '2021-01-21'
|
||||
author: Philip Royer, Splunk
|
||||
type: Response
|
||||
description: This playbook investigates and remediates malware infections on the endpoint.
|
||||
playbook: malware_hunt_and_contain
|
||||
how_to_implement: "Be sure to update asset naming to reflect the asset names configured in your environment."
|
||||
references: []
|
||||
app_list:
|
||||
- "LDAP"
|
||||
- "ServiceNow"
|
||||
- "CarbonBlack Response"
|
||||
- "VirusTotal"
|
||||
tags:
|
||||
platform_tags:
|
||||
- Response
|
||||
playbook_fields:
|
||||
- fileHash
|
||||
product:
|
||||
- Splunk SOAR
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux File Creation In Init Boot Directory Unit Test
|
||||
tests:
|
||||
- name: Linux File Creation In Init Boot Directory
|
||||
file: endpoint/linux_file_creation_in_init_boot_directory.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-30d'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1546.004/linux_init_profile/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux File Creation In Profile Directory Unit Test
|
||||
tests:
|
||||
- name: Linux File Creation In Profile Directory
|
||||
file: endpoint/linux_file_creation_in_profile_directory.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1546.004/linux_init_profile/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux Service File Created In Systemd Directory Unit Test
|
||||
tests:
|
||||
- name: Linux Service File Created In Systemd Directory
|
||||
file: endpoint/linux_service_file_created_in_systemd_directory.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux Service Restarted Unit Test
|
||||
tests:
|
||||
- name: Linux Service Restarted
|
||||
file: endpoint/linux_service_restarted.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux Service Started Or Enabled Unit Test
|
||||
tests:
|
||||
- name: Linux Service Started Or Enabled
|
||||
file: endpoint/linux_service_started_or_enabled.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1053.006/service_systemd/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux Setuid Using Chmod Utility Unit Test
|
||||
tests:
|
||||
- name: Linux Setuid Using Chmod Utility
|
||||
file: endpoint/linux_setuid_using_chmod_utility.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1548.001/chmod_uid/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Linux Setuid Using Setcap Utility Unit Test
|
||||
tests:
|
||||
- name: Linux Setuid Using Setcap Utility
|
||||
file: endpoint/linux_setuid_using_setcap_utility.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: sysmon_linux.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1548.001/linux_setcap/sysmon_linux.log
|
||||
source: Syslog:Linux-Sysmon/Operational
|
||||
sourcetype: sysmon_linux
|
||||
@@ -0,0 +1,12 @@
|
||||
name: MSI Module Loaded by Non-System Binary Unit Test
|
||||
tests:
|
||||
- name: MSI Module Loaded by Non-System Binary
|
||||
file: endpoint/msi_module_loaded_by_non_system_binary.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: windows-sysmon.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1574.002/msi_module_load/windows-sysmon.log
|
||||
source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational
|
||||
sourcetype: xmlwineventlog
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Windows DISM Remove Defender Unit Test
|
||||
tests:
|
||||
- name: Windows DISM Remove Defender
|
||||
file: endpoint/windows_dism_remove_defender.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: windows-sysmon_dism.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1562.001/atomic_red_team/windows-sysmon_dism.log
|
||||
source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational
|
||||
sourcetype: xmlwineventlog
|
||||
@@ -0,0 +1,12 @@
|
||||
name: Windows Raccine Scheduled Task Deletion Unit Test
|
||||
tests:
|
||||
- name: Windows Raccine Scheduled Task Deletion
|
||||
file: endpoint/windows_raccine_scheduled_task_deletion.yml
|
||||
pass_condition: '| stats count | where count > 0'
|
||||
earliest_time: '-24h'
|
||||
latest_time: 'now'
|
||||
attack_data:
|
||||
- file_name: windows-sysmon_raccine.log
|
||||
data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1562.001/atomic_red_team/windows-sysmon_raccine.log
|
||||
source: XmlWinEventLog:Microsoft-Windows-Sysmon/Operational
|
||||
sourcetype: xmlwineventlog
|
||||
Reference in New Issue
Block a user