Branch was auto-updated.

This commit is contained in:
pyth0n1c
2022-01-10 13:06:18 -08:00
committed by GitHub
46 changed files with 26462 additions and 13 deletions
@@ -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
@@ -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
+1 -1
View File
@@ -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 |
+3
View File
@@ -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 |
+46
View File
@@ -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
![](https://raw.githubusercontent.com/splunk/security_content/develop/playbooks/block_indicators.png)
#### 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
![](https://raw.githubusercontent.com/splunk/security_content/develop/playbooks/email_notification_for_malware.png)
#### 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
![](https://raw.githubusercontent.com/splunk/security_content/develop/playbooks/malware_hunt_and_contain.png)
#### 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
+1 -1
View File
@@ -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
View File
@@ -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

+297
View File
@@ -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
+23
View File
@@ -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

+338
View File
@@ -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

+456
View File
@@ -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
+22
View File
@@ -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