[Hunt Tuning] Add Descriptions, Collapse Queries and Re-Generate Docs (#3791)

* add description to hunting schema; change queries to be a list

* update createremotethreat by process hunt

* update dll hijack and masquerading as MSFT library

* remove sysmon specific dDLL hijack via masquerading MSFT library

* updated Masquerading Attempts as Native Windows Binaries

* updates Rare DLL Side-Loading by Occurrence

* updates Rare LSASS Process Access Attempts

* update DNS Queries via LOLBins with Low Occurence Frequency

* updated Low Occurrence of Drivers Loaded on Unique Hosts

* updates Excessive RDP Network Activity by Host and User

* updates Excessive SMB Network Activity by Process ID

* updated Executable File Creation by an Unusual Microsoft Binary

* Frequency of Process Execution and Network Logon by Source Address

* updates Frequency of Process Execution and Network Logon by Source Address

* updated Execution via Remote Services by Client Address

* updated Startup Execution with Low Occurrence Frequency by Unique Host

* updated Low Frequency of Process Execution via WMI by Unique Agent

* updated Low Frequency of Process Execution via Windows Scheduled Task by Unique Agent

* updated Low Occurence of Process Execution via Windows Services with Unique Agent

* Updated High Count of Network Connection Over Extended Period by Process

* update Libraries Loaded by svchost with Low Occurrence Frequency

* updated Microsoft Office Child Processes with Low Occurrence Frequency by Unique Agent

* updated Network Discovery via Sensitive Ports by Unusual Process

* updated PE File Transfer via SMB_Admin Shares by Agent or User

* updated Persistence via Run Key with Low Occurrence Frequency

* updates Persistence via Startup with Low Occurrence Frequency by Unique Host

* updates "Persistence via Run Key with Low Occurrence Frequency"; adjusted file names to remove data source

* updates "Low Occurrence of Suspicious Launch Agent or Launch Daemon"

* updates "Egress Network Connections with Total Bytes Greater than Threshold"

* updates "Rundll32 Execution Aggregated by Command Line"

* updates "Scheduled tasks Creation by Action via Registry"

* updates "Scheduled Tasks Creation for Unique Hosts by Task Command"

* updates "Suspicious Base64 Encoded Powershell Command"

* updates "Suspicious DNS TXT Record Lookups by Process"

* updates "Unique Windows Services Creation by Service File Name"

* Updates "Unique Windows Services Creation by Service File Name"

* updates "Windows Command and Scripting Interpreter from Unusual Parent Process"

* updates "Windows Logon Activity by Source IP"

* updates "Suspicious Network Connections by Unsigned Mach-O"

* updates LLM hunting queries

* re-generated markdown files; updated generate markdown py file

* updated test_hunt_data

* Update hunting/macos/queries/suspicious_network_connections_by_unsigned_macho.toml

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>

* Update hunting/windows/queries/drivers_load_with_low_occurrence_frequency.toml

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>

* Update hunting/windows/queries/domain_names_queried_via_lolbins_and_with_low_occurence_frequency.toml

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>

* Update hunting/windows/queries/excessive_rdp_network_activity_by_source_host_and_user.toml

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>

* Update hunting/windows/queries/excessive_rdp_network_activity_by_source_host_and_user.toml

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>

* updated missing integrations

* updated MD docs according to recent hunting changes

* Update hunting/windows/queries/executable_file_creation_by_an_unusual_microsoft_binary.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* Update hunting/windows/queries/detect_rare_dll_sideload_by_occurrence.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* Update hunting/windows/queries/detect_masquerading_attempts_as_native_windows_binaries.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* Update hunting/windows/queries/detect_dll_hijack_via_masquerading_as_microsoft_native_libraries.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* Update hunting/llm/queries/aws_bedrock_dos_resource_exhaustion_detection.toml

Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>

* added enrichment policy link to rule

* Update hunting/windows/docs/execution_via_windows_management_instrumentation_by_occurrence_frequency_by_unique_agent.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/windows_command_and_scripting_interpreter_from_unusual_parent.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/windows_command_and_scripting_interpreter_from_unusual_parent.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/rundll32_execution_aggregated_by_cmdline.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/microsoft_office_child_processes_with_low_occurrence_frequency.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/microsoft_office_child_processes_with_low_occurrence_frequency.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/queries/execution_via_windows_management_instrumentation_by_occurrence_frequency_by_unique_agent.toml

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/queries/execution_via_windows_management_instrumentation_by_occurrence_frequency_by_unique_agent.toml

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/index.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/docs/execution_via_network_logon_by_occurrence_frequency_by_top_source_ip.md

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

* Update hunting/windows/queries/execution_via_network_logon_by_occurrence_frequency_by_top_source_ip.toml

Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

---------

Co-authored-by: Mika Ayenson <Mikaayenson@users.noreply.github.com>
Co-authored-by: Jonhnathan <26856693+w0rk3r@users.noreply.github.com>
Co-authored-by: Samirbous <64742097+Samirbous@users.noreply.github.com>

(cherry picked from commit 632e169f7a)
This commit is contained in:
Terrance DeJesus
2024-06-25 09:35:36 -04:00
committed by github-actions[bot]
parent 30f5784613
commit 45e6b901a2
139 changed files with 3360 additions and 2319 deletions
+5 -2
View File
@@ -28,12 +28,13 @@ class Hunt:
"""Dataclass to represent a hunt."""
author: str
description: str
integration: list[str]
uuid: str
name: str
language: str
license: str
query: str
query: list[str]
notes: Optional[List[str]] = field(default_factory=list)
mitre: Optional[List[str]] = field(default_factory=list)
references: Optional[List[str]] = field(default_factory=list)
@@ -81,11 +82,13 @@ def convert_toml_to_markdown(hunt_config: Hunt, file_path: Path) -> str:
markdown = f"# {hunt_config.name}\n\n---\n\n"
markdown += "## Metadata\n\n"
markdown += f"- **Author:** {hunt_config.author}\n"
markdown += f"- **Description:** {hunt_config.description}\n"
markdown += f"- **UUID:** `{hunt_config.uuid}`\n"
markdown += f"- **Integration:** {", ".join(generate_integration_links(hunt_config.integration))}\n"
markdown += f"- **Language:** `{hunt_config.language}`\n\n"
markdown += "## Query\n\n"
markdown += f"```sql\n{hunt_config.query}```\n\n"
for query in hunt_config.query:
markdown += f"```sql\n{query}```\n\n"
if hunt_config.notes:
markdown += "## Notes\n\n" + "\n".join(f"- {note}" for note in hunt_config.notes)
+35 -54
View File
@@ -3,9 +3,9 @@
Here are the queries currently available:
## llm
- [Denial of Service or Resource Exhaustion Attacks Detection](./llm/docs/llm_dos_resource_exhaustion_detection.md) (ES|QL)
- [Monitoring for Latency Anomalies](./llm/docs/llm_latency_anomalies_detection.md) (ES|QL)
- [Sensitive Content Refusal Detection](./llm/docs/llm_sensitive_content_refusal_detection.md) (ES|QL)
- [AWS Bedrock LLM Denial-of-Service or Resource Exhaustion](./llm/docs/aws_bedrock_dos_resource_exhaustion_detection.md) (ES|QL)
- [AWS Bedrock LLM Latency Anomalies](./llm/docs/aws_bedrock_latency_anomalies_detection.md) (ES|QL)
- [AWS Bedrock LLM Sensitive Content Refusals](./llm/docs/aws_bedrock_sensitive_content_refusal_detection.md) (ES|QL)
## macos
@@ -13,55 +13,36 @@ Here are the queries currently available:
## windows
- [CreateRemoteThread by source process with low occurrence](./windows/docs/createremotethread_by_source_process_with_low_occurrence.md) (ES|QL)
- [Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Elastic Defend](./windows/docs/detect_dll_hijack_via_masquerading_as_microsoft_native_libraries_elastic_defend.md) (ES|QL)
- [Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Sysmon](./windows/docs/detect_dll_hijack_via_masquerading_as_microsoft_native_libraries_sysmon.md) (ES|QL)
- [Detect masquerading attempts as native Windows binaries](./windows/docs/detect_masquerading_attempts_as_native_windows_binaries.md) (ES|QL)
- [Detect Rare DLL SideLoad by Occurrence - Elastic Defend](./windows/docs/detect_rare_dll_sideload_by_occurrence_elastic_defend.md) (ES|QL)
- [Detect Rare DLL SideLoad by Occurrence - Sysmon](./windows/docs/detect_rare_dll_sideload_by_occurrence_sysmon.md) (ES|QL)
- [Detect Rare LSASS Process Access Attempts - Elastic Defend](./windows/docs/detect_rare_lsass_process_access_attempts_elastic_defend.md) (ES|QL)
- [Detect Rare LSASS Process Access Attempts - Sysmon](./windows/docs/detect_rare_lsass_process_access_attempts_sysmon.md) (ES|QL)
- [Doamin Names queries via Lolbins and with low occurence frequency](./windows/docs/doamin_names_queries_via_lolbins_and_with_low_occurence_frequency.md) (ES|QL)
- [Drivers Load with low occurrence frequency - Elastic Defend](./windows/docs/drivers_load_with_low_occurrence_frequency_elastic_defend.md) (ES|QL)
- [Drivers Load with low occurrence frequency - Sysmon](./windows/docs/drivers_load_with_low_occurrence_frequency_sysmon.md) (ES|QL)
- [Drivers Load with low occurrence frequency - Windows 7045](./windows/docs/drivers_load_with_low_occurrence_frequency_windows_7045.md) (ES|QL)
- [Excessive RDP Network Activity by Source Host and User- Elastic Defend - Sysmon](./windows/docs/excessive_rdp_network_activity_by_source_host_and_user-_elastic_defend_sysmon.md) (ES|QL)
- [Excessive RDP Network Activity by Source Host - Elastic Defend - Sysmon](./windows/docs/excessive_rdp_network_activity_by_source_host_elastic_defend_sysmon.md) (ES|QL)
- [Excessive SMB Network Activity by process Id](./windows/docs/excessive_smb_network_activity_by_process_id.md) (ES|QL)
- [Executable File creation by an Unusual Microsoft Binary - Elastic Defend](./windows/docs/executable_file_creation_by_an_unusual_microsoft_binary_elastic_defend.md) (ES|QL)
- [Executable File creation by an Unusual Microsoft Binary - Sysmon](./windows/docs/executable_file_creation_by_an_unusual_microsoft_binary_sysmon.md) (ES|QL)
- [Execution via Network Logon by occurrence frequency](./windows/docs/execution_via_network_logon_by_occurrence_frequency.md) (ES|QL)
- [Execution via Network Logon by occurrence frequency by top Source IP](./windows/docs/execution_via_network_logon_by_occurrence_frequency_by_top_source_ip.md) (ES|QL)
- [Low Occurrence Rate of CreateRemoteThread by Source Process](./windows/docs/createremotethread_by_source_process_with_low_occurrence.md) (ES|QL)
- [DLL Hijack via Masquerading as Microsoft Native Libraries](./windows/docs/detect_dll_hijack_via_masquerading_as_microsoft_native_libraries.md) (ES|QL)
- [Masquerading Attempts as Native Windows Binaries](./windows/docs/detect_masquerading_attempts_as_native_windows_binaries.md) (ES|QL)
- [Rare DLL Side-Loading by Occurrence](./windows/docs/detect_rare_dll_sideload_by_occurrence.md) (ES|QL)
- [Rare LSASS Process Access Attempts](./windows/docs/detect_rare_lsass_process_access_attempts.md) (ES|QL)
- [DNS Queries via LOLBins with Low Occurence Frequency](./windows/docs/domain_names_queried_via_lolbins_and_with_low_occurence_frequency.md) (ES|QL)
- [Low Occurrence of Drivers Loaded on Unique Hosts](./windows/docs/drivers_load_with_low_occurrence_frequency.md) (ES|QL)
- [Excessive RDP Network Activity by Host and User](./windows/docs/excessive_rdp_network_activity_by_source_host_and_user.md) (ES|QL)
- [Excessive SMB Network Activity by Process ID](./windows/docs/excessive_smb_network_activity_by_process_id.md) (ES|QL)
- [Executable File Creation by an Unusual Microsoft Binary](./windows/docs/executable_file_creation_by_an_unusual_microsoft_binary.md) (ES|QL)
- [Frequency of Process Execution via Network Logon by Source Address](./windows/docs/execution_via_network_logon_by_occurrence_frequency_by_top_source_ip.md) (ES|QL)
- [Execution via Remote Services by Client Address](./windows/docs/execution_via_remote_services_by_client_address.md) (ES|QL)
- [Execution via Startup with low occurrence frequency](./windows/docs/execution_via_startup_with_low_occurrence_frequency.md) (ES|QL)
- [Execution via Windows Management Instrumentation by occurrence frequency by Unique Agent - Elastic Defend - Sysmon](./windows/docs/execution_via_windows_management_instrumentation_by_occurrence_frequency_by_unique_agent_elastic_defend_sysmon.md) (ES|QL)
- [Execution via Windows Management Instrumentation by occurrence frequency - Elastic Defend - Sysmon](./windows/docs/execution_via_windows_management_instrumentation_by_occurrence_frequency_elastic_defend_sysmon.md) (ES|QL)
- [Execution via Windows Management Instrumentation by occurrence frequency - Elastic Defend - Sysmon - Windows Security](./windows/docs/execution_via_windows_management_instrumentation_by_occurrence_frequency_elastic_defend_sysmon_windows_security.md) (ES|QL)
- [Execution via Windows Scheduled Task with low occurrence frequency](./windows/docs/execution_via_windows_scheduled_task_with_low_occurrence_frequency.md) (ES|QL)
- [Execution via Windows Services with low occurrence frequency - Elastic Defend - Sysmon](./windows/docs/execution_via_windows_services_with_low_occurrence_frequency_elastic_defend_sysmon.md) (ES|QL)
- [Execution via Windows Services with low occurrence frequency - Windows Security](./windows/docs/execution_via_windows_services_with_low_occurrence_frequency_windows_security.md) (ES|QL)
- [High count of network connection over extended period by process - Elastic Defend Network](./windows/docs/high_count_of_network_connection_over_extended_period_by_process_elastic_defend_network.md) (ES|QL)
- [High count of network connection over extended period by process - Elastic Defend Network - Sysmon](./windows/docs/high_count_of_network_connection_over_extended_period_by_process_elastic_defend_network_sysmon.md) (ES|QL)
- [High count of network connection over extended period by process - Elastic Defend - Sysmon](./windows/docs/high_count_of_network_connection_over_extended_period_by_process_elastic_defend_sysmon.md) (ES|QL)
- [Libraries loaded by svchost with low occurrence frequency - Elastic Defend](./windows/docs/libraries_loaded_by_svchost_with_low_occurrence_frequency_elastic_defend.md) (ES|QL)
- [Libraries loaded by svchost with low occurrence frequency - Sysmon](./windows/docs/libraries_loaded_by_svchost_with_low_occurrence_frequency_sysmon.md) (ES|QL)
- [Microsoft Office Child Processes with low occurrence frequency](./windows/docs/microsoft_office_child_processes_with_low_occurrence_frequency.md) (ES|QL)
- [Network Discovery via sensitive ports by unusual process](./windows/docs/network_discovery_via_sensitive_ports_by_unusual_process.md) (ES|QL)
- [PE File Transfer via SMB_Admin Shares by Agent](./windows/docs/pe_file_transfer_via_smb_admin_shares_by_agent.md) (ES|QL)
- [PE File Transfer via SMB_Admin Shares by User](./windows/docs/pe_file_transfer_via_smb_admin_shares_by_user.md) (ES|QL)
- [Persistence via Run Key with low occurrence frequency - Elastic Defend](./windows/docs/persistence_via_run_key_with_low_occurrence_frequency_elastic_defend.md) (ES|QL)
- [Persistence via Run Key with low occurrence frequency - Sysmon](./windows/docs/persistence_via_run_key_with_low_occurrence_frequency_sysmon.md) (ES|QL)
- [Persistence via Startup with low occurrence frequency](./windows/docs/persistence_via_startup_with_low_occurrence_frequency.md) (ES|QL)
- [Persistence via Suspicious Launch Agent or Launch Daemon with low occurrence](./windows/docs/persistence_via_suspicious_launch_agent_or_launch_daemon_with_low_occurrence.md) (ES|QL)
- [Potential Exfiltration by process total egress bytes](./windows/docs/potential_exfiltration_by_process_total_egress_bytes.md) (ES|QL)
- [Rundll32 execution aggregated by cmdline](./windows/docs/rundll32_execution_aggregated_by_cmdline.md) (ES|QL)
- [Scheduled tasks creation by action via registry](./windows/docs/scheduled_task_creation_by_action_via_registry.md) (ES|QL)
- [Scheduled tasks creation with low occurrence frequency](./windows/docs/scheduled_tasks_creation_with_low_occurrence_frequency.md) (ES|QL)
- [Suspicious Base64 Encoded PowerShell Command](./windows/docs/suspicious_base64_encoded_powershell_commands.md) (ES|QL)
- [Suspicious DNS TXT Record lookups by process](./windows/docs/suspicious_dns_txt_record_lookups_by_process.md) (ES|QL)
- [Unique Windows Services Creation by ServiceFileName - Elastic Defend Registry - Sysmon](./windows/docs/unique_windows_services_creation_by_servicefilename_elastic_defend_registry_sysmon.md) (ES|QL)
- [Unique Windows Services Creation by ServiceFileName - Elastic Defend - Sysmon Registry](./windows/docs/unique_windows_services_creation_by_servicefilename_elastic_defend_sysmon_registry.md) (ES|QL)
- [Unique Windows Services Creation by ServiceFileName - Windows Security 4697](./windows/docs/unique_windows_services_creation_by_servicefilename_windows_security_4697.md) (ES|QL)
- [Unique Windows Services Creation by ServiceFileName - Windows Security 7045](./windows/docs/unique_windows_services_creation_by_servicefilename_windows_security_7045.md) (ES|QL)
- [Windows Command and Scripting Interpreter from unusual parent](./windows/docs/windows_command_and_scripting_interpreter_from_unusual_parent.md) (ES|QL)
- [Windows logon activity by source IP](./windows/docs/windows_logon_activity_by_source_ip.md) (ES|QL)
- [Startup Execution with Low Occurrence Frequency by Unique Host](./windows/docs/execution_via_startup_with_low_occurrence_frequency.md) (ES|QL)
- [Low Frequency of Process Execution via WMI by Unique Agent](./windows/docs/execution_via_windows_management_instrumentation_by_occurrence_frequency_by_unique_agent.md) (ES|QL)
- [Low Frequency of Process Execution via Windows Scheduled Task by Unique Agent](./windows/docs/execution_via_windows_scheduled_task_with_low_occurrence_frequency.md) (ES|QL)
- [Low Occurence of Process Execution via Windows Services with Unique Agent](./windows/docs/execution_via_windows_services_with_low_occurrence_frequency.md) (ES|QL)
- [High Count of Network Connection Over Extended Period by Process](./windows/docs/high_count_of_network_connection_over_extended_period_by_process.md) (ES|QL)
- [Libraries Loaded by svchost with Low Occurrence Frequency](./windows/docs/libraries_loaded_by_svchost_with_low_occurrence_frequency.md) (ES|QL)
- [Microsoft Office Child Processes with Low Occurrence Frequency by Unique Agent](./windows/docs/microsoft_office_child_processes_with_low_occurrence_frequency.md) (ES|QL)
- [Network Discovery via Sensitive Ports by Unusual Process](./windows/docs/network_discovery_via_sensitive_ports_by_unusual_process.md) (ES|QL)
- [PE File Transfer via SMB_Admin Shares by Agent or User](./windows/docs/pe_file_transfer_via_smb_admin_shares_by_agent.md) (ES|QL)
- [Persistence via Run Key with Low Occurrence Frequency](./windows/docs/persistence_via_run_key_with_low_occurrence_frequency.md) (ES|QL)
- [Persistence via Startup with Low Occurrence Frequency by Unique Host](./windows/docs/persistence_via_startup_with_low_occurrence_frequency.md) (ES|QL)
- [Low Occurrence of Suspicious Launch Agent or Launch Daemon](./windows/docs/persistence_via_suspicious_launch_agent_or_launch_daemon_with_low_occurrence.md) (ES|QL)
- [Egress Network Connections with Total Bytes Greater than Threshold](./windows/docs/potential_exfiltration_by_process_total_egress_bytes.md) (ES|QL)
- [Rundll32 Execution Aggregated by Command Line](./windows/docs/rundll32_execution_aggregated_by_cmdline.md) (ES|QL)
- [Scheduled tasks Creation by Action via Registry](./windows/docs/scheduled_task_creation_by_action_via_registry.md) (ES|QL)
- [Scheduled Tasks Creation for Unique Hosts by Task Command](./windows/docs/scheduled_tasks_creation_for_unique_hosts_by_task_command.md) (ES|QL)
- [Suspicious Base64 Encoded Powershell Command](./windows/docs/suspicious_base64_encoded_powershell_commands.md) (ES|QL)
- [Suspicious DNS TXT Record Lookups by Process](./windows/docs/suspicious_dns_txt_record_lookups_by_process.md) (ES|QL)
- [Unique Windows Services Creation by Service File Name](./windows/docs/unique_windows_services_creation_by_servicefilename.md) (ES|QL)
- [Windows Command and Scripting Interpreter from Unusual Parent Process](./windows/docs/windows_command_and_scripting_interpreter_from_unusual_parent.md) (ES|QL)
- [Windows Logon Activity by Source IP](./windows/docs/windows_logon_activity_by_source_ip.md) (ES|QL)
@@ -1,10 +1,12 @@
# Denial of Service or Resource Exhaustion Attacks Detection
# AWS Bedrock LLM Denial-of-Service or Resource Exhaustion
---
## Metadata
- **Author:** Elastic
- **Description:** This hunting query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.
- **UUID:** `dc181967-c32c-46c9-b84b-ec4c8811c6a0`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
@@ -29,7 +31,6 @@ from logs-aws_bedrock.invocation-*
## Notes
- This query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.
- Consider reviewing the context of high token requests to differentiate between legitimate heavy usage and potential abuse. Monitor the source of requests and patterns over time for better assessment.
- Ensure logging and monitoring are correctly configured to capture detailed metrics on token usage. This will facilitate accurate detection and allow for a quick response to potential threats.
- Collect evidence from logs that detail the timestamp, user ID, session information, and token counts for incidents flagged by this analytic. This information will be crucial for forensic analysis in the event of a security incident.
@@ -40,7 +41,7 @@ from logs-aws_bedrock.invocation-*
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Denial of Service or Resource Exhaustion Attacks Detection](../queries/llm_dos_resource_exhaustion_detection.toml)
- [AWS Bedrock LLM Denial-of-Service or Resource Exhaustion](../queries/aws_bedrock_dos_resource_exhaustion_detection.toml)
## License
@@ -1,10 +1,12 @@
# Monitoring for Latency Anomalies
# AWS Bedrock LLM Latency Anomalies
---
## Metadata
- **Author:** Elastic
- **Description:** This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.
- **UUID:** `3708787b-811b-43b1-b2e7-c7276b8db48c`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
@@ -24,7 +26,6 @@ from logs-aws_bedrock.invocation-*
## Notes
- This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.
- Review the incidents flagged by this analytic to understand the context and potential sources of latency. This can include network configurations, resource allocation, or external network pressures.
- Effective logging and monitoring setup are essential to capture relevant latency metrics accurately. Ensure system clocks and time syncing are properly configured to avoid false positives.
- Gather comprehensive logs that detail the request and response timestamps, user IDs, and session details for thorough investigation and evidence collection in case of security incidents.
@@ -35,7 +36,7 @@ from logs-aws_bedrock.invocation-*
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Monitoring for Latency Anomalies](../queries/llm_latency_anomalies_detection.toml)
- [AWS Bedrock LLM Latency Anomalies](../queries/aws_bedrock_latency_anomalies_detection.toml)
## License
@@ -1,10 +1,11 @@
# Sensitive Content Refusal Detection
# AWS Bedrock LLM Sensitive Content Refusals
---
## Metadata
- **Author:** Elastic
- **Description:** This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards.
- **UUID:** `8fabae86-7ed2-4006-9623-5db28164f374`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
@@ -24,7 +25,6 @@ from logs-aws_bedrock.invocation-*
## Notes
- This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards.
- Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent or probing of model boundaries.
- Regularly review and update the phrases that trigger refusals to adapt to new ethical guidelines and compliance requirements.
- Ensure that data logs contain enough detail to provide context around the refusal, which will aid in subsequent investigations by security teams.
@@ -35,7 +35,7 @@ from logs-aws_bedrock.invocation-*
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Sensitive Content Refusal Detection](../queries/llm_sensitive_content_refusal_detection.toml)
- [AWS Bedrock LLM Sensitive Content Refusals](../queries/aws_bedrock_sensitive_content_refusal_detection.toml)
## License
@@ -1,11 +1,15 @@
[hunt]
author = "Elastic"
description = """
This hunting query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.
"""
integration = ["aws_bedrock.invocation"]
uuid = "dc181967-c32c-46c9-b84b-ec4c8811c6a0"
name = "Denial of Service or Resource Exhaustion Attacks Detection"
name = "AWS Bedrock LLM Denial-of-Service or Resource Exhaustion"
language = "ES|QL"
license = "Elastic License v2"
query = '''
query = [
'''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
@@ -20,8 +24,8 @@ from logs-aws_bedrock.invocation-*
| WHERE request_count > 1
| SORT max_prompt_tokens, max_request_tokens, max_completion_tokens DESC
'''
]
notes = [
"This query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.",
"Consider reviewing the context of high token requests to differentiate between legitimate heavy usage and potential abuse. Monitor the source of requests and patterns over time for better assessment.",
"Ensure logging and monitoring are correctly configured to capture detailed metrics on token usage. This will facilitate accurate detection and allow for a quick response to potential threats.",
"Collect evidence from logs that detail the timestamp, user ID, session information, and token counts for incidents flagged by this analytic. This information will be crucial for forensic analysis in the event of a security incident."
@@ -1,11 +1,15 @@
[hunt]
author = "Elastic"
description = """
This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.
"""
integration = ["aws_bedrock.invocation"]
uuid = "3708787b-811b-43b1-b2e7-c7276b8db48c"
name = "Monitoring for Latency Anomalies"
name = "AWS Bedrock LLM Latency Anomalies"
language = "ES|QL"
license = "Elastic License v2"
query = '''
query = [
'''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
| EVAL response_delay_seconds = gen_ai.performance.start_response_time / 1000
@@ -15,8 +19,8 @@ from logs-aws_bedrock.invocation-*
| WHERE request_count > 3
| SORT max_response_delay DESC
'''
]
notes = [
"This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.",
"Review the incidents flagged by this analytic to understand the context and potential sources of latency. This can include network configurations, resource allocation, or external network pressures.",
"Effective logging and monitoring setup are essential to capture relevant latency metrics accurately. Ensure system clocks and time syncing are properly configured to avoid false positives.",
"Gather comprehensive logs that detail the request and response timestamps, user IDs, and session details for thorough investigation and evidence collection in case of security incidents."
@@ -1,11 +1,13 @@
[hunt]
author = "Elastic"
description = "This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards."
integration = ["aws_bedrock.invocation"]
uuid = "8fabae86-7ed2-4006-9623-5db28164f374"
name = "Sensitive Content Refusal Detection"
name = "AWS Bedrock LLM Sensitive Content Refusals"
language = "ES|QL"
license = "Elastic License v2"
query = '''
query = [
'''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
@@ -15,8 +17,8 @@ from logs-aws_bedrock.invocation-*
| STATS user_request_count = count() BY gen_ai.user.id
| WHERE user_request_count >= 3
'''
]
notes = [
"This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards.",
"Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent or probing of model boundaries.",
"Regularly review and update the phrases that trigger refusals to adapt to new ethical guidelines and compliance requirements.",
"Ensure that data logs contain enough detail to provide context around the refusal, which will aid in subsequent investigations by security teams."
@@ -5,6 +5,8 @@
## Metadata
- **Author:** Elastic
- **Description:** This hunt aggregates by process ID and destination IP by the number of connections per hour over a period of time greater than a defined threshold. This may indicate suspicious network connections by unsigned Mach-O binaries.
- **UUID:** `44aff0e3-e0d7-4dca-a94f-2dd0b96f18bd`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -14,8 +16,8 @@
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.family == "macos" and event.category == "network" and
(process.code_signature.exists == false or process.code_signature.trusted != true) and
| where host.os.family == "macos" and event.category == "network" and
(process.code_signature.exists == false or process.code_signature.trusted != true) and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
@@ -29,8 +31,8 @@ from logs-endpoint.events.network-*
## Notes
- This hunt aggregates by process ID and destination IP the number of connections per hour over a period of time greater than a defined threshold. The process paths are scoped to Microsoft signed binaries often injected or used as a lolbin to masquerade malicious execution. This could be a sign of long term network activity to perform command and control from an injected process.
- Hunt can be extended by adding suspicious process paths or lolbins.
- This hunt returns a list of processes by entity_id and name that have a high number of connections per hour over a period of time greater than a defined threshold.
- Pivoting by `process.entity_id` will allow further investigation (parent process, hash, child processes, other network events etc.).
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
@@ -1,20 +1,24 @@
[hunt]
author = "Elastic"
description = """
This hunt aggregates by process ID and destination IP by the number of connections per hour over a period of time greater than a defined threshold. This may indicate suspicious network connections by unsigned Mach-O binaries.
"""
integration = ["endpoint"]
uuid = "44aff0e3-e0d7-4dca-a94f-2dd0b96f18bd"
name = "Suspicious Network Connections by Unsigned Mach-O"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt aggregates by process ID and destination IP the number of connections per hour over a period of time greater than a defined threshold. The process paths are scoped to Microsoft signed binaries often injected or used as a lolbin to masquerade malicious execution. This could be a sign of long term network activity to perform command and control from an injected process.", "Hunt can be extended by adding suspicious process paths or lolbins.",
"This hunt returns a list of processes by entity_id and name that have a high number of connections per hour over a period of time greater than a defined threshold.",
"Pivoting by `process.entity_id` will allow further investigation (parent process, hash, child processes, other network events etc.).",
]
mitre = ["T1071"]
query = '''
query = [
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.family == "macos" and event.category == "network" and
(process.code_signature.exists == false or process.code_signature.trusted != true) and
| where host.os.family == "macos" and event.category == "network" and
(process.code_signature.exists == false or process.code_signature.trusted != true) and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
@@ -24,4 +28,5 @@ from logs-endpoint.events.network-*
| keep process.entity_id, process.name, duration_hours, destination.address, MB_out, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute, you can adjust it to your env/FP rate */
| where duration_hours >= 8 and number_of_con_per_hour >= 120
'''
'''
]
@@ -1,10 +1,11 @@
# CreateRemoteThread by source process with low occurrence
# Low Occurrence Rate of CreateRemoteThread by Source Process
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt attempts to identify remote process injection by aggregating Sysmon `CreateRemoteThread` events by source process and returns the ones that we observed in only one unique host.
- **UUID:** `0545f23f-84a7-4b88-9b5b-b8cfcfdc9276`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -12,7 +13,7 @@
## Query
```sql
from logs-windows.sysmon_operational-*
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "CreateRemoteThread"
| eval source_process = replace(process.executable, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
@@ -23,8 +24,7 @@ from logs-windows.sysmon_operational-*
## Notes
- This hunt aggregates Sysmon CreateRemoteThread events by source process and returns the ones that we observed in only one unique host. This may indicate remote process injection.
- Adding winlog.event_data.TargetImage to the group by clause can be beneficial but may introduce more legit hits.
- Adding `winlog.event_data.TargetImage` to the aggregation clause can be beneficial but may introduce more false-positives.
## MITRE ATT&CK Techniques
- [T1055](https://attack.mitre.org/techniques/T1055)
@@ -0,0 +1,62 @@
# DLL Hijack via Masquerading as Microsoft Native Libraries
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies when a process loads a DLL normally located in `System32` or `SysWOW64` folders from an unusual path. Adversaries may execute their own malicious payloads by side-loading malicious DLLs. The host count also should help exclude false-positives by looking at low occurrences when this abnormal behavior is limited to unique agents.
- **UUID:** `87c97865-fdaa-48b2-bfa6-67bed7cf56ef`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and
not dll.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep dll.name, dll.path, dll.hash.sha256, process.executable, host.id
/* steps how to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c */
| ENRICH libs-policy-defend
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(dll.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(dll.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by dll.name, dll_path, process_path, dll.hash.sha256
| sort host_count asc
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep file.name, file.path, file.hash.sha256, process.executable, host.id
/* steps to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c - just replace dll by file */
| ENRICH libs-policy-sysmon
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(file.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(file.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by file.name, dll_path, process_path, file.hash.sha256
| sort host_count asc
```
## Notes
- This hunt has two optional queries, one for Elastic Defend data and another for Sysmon data.
- This hunt requires the creation of an [enrichment policy](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-enrich-data.html) to use with the ES|QL (ENRICH command).
- The `dll.hash.sha256` field can be used to pivot and further investigate the DLL origin and purpose.
- Paths like `C:\Users\Public and C:\ProgramData\` are often observed in malware employing DLL side-loading.
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.001](https://attack.mitre.org/techniques/T1574/001)
## License
- `Elastic License v2`
@@ -1,43 +0,0 @@
# Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `87c97865-fdaa-48b2-bfa6-67bed7cf56ef`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and
not dll.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep dll.name, dll.path, dll.hash.sha256, process.executable, host.id
/* steps how to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c */
| ENRICH libs-policy-defend
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(dll.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(dll.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by dll.name, dll_path, process_path, dll.hash.sha256
| sort host_count asc
```
## Notes
- This hunt require the creation of an enrichment policy to use with the ES|QL (ENRICH command).
- The `dll.hash.sha256` field can be used to pivot and further investigate the DLL origin and purpose.
- Paths like C:\Users\Public and C:\ProgramData\ are often observed in malware employing DLL side-loading.
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.001](https://attack.mitre.org/techniques/T1574/001)
## License
- `Elastic License v2`
@@ -1,44 +0,0 @@
# Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `68314691-1460-4ac5-ae0d-6b3514e43254`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep file.name, file.path, file.hash.sha256, process.executable, host.id
/* steps to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c - just replace dll by file */
| ENRICH libs-policy-sysmon
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(file.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(file.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by file.name, dll_path, process_path, file.hash.sha256
| sort host_count asc
```
## Notes
- This hunt require the creation of an enrichment policy to use with the ES|QL (ENRICH command).
- Using dll.hash.sha256 for Elastic Defend or file.hash.sha256 for Sysmon you can pivot to further investigate the DLL origin and purpose.
- Paths like C:\Users\Public and C:\ProgramData\ are often observed in malware employing DLL side-loading.
- Process code signature information is not captured in Sysmon Image Load Events (not present in the ES|QL hunt).
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.001](https://attack.mitre.org/techniques/T1574/001)
## License
- `Elastic License v2`
@@ -1,10 +1,11 @@
# Detect masquerading attempts as native Windows binaries
# Masquerading Attempts as Native Windows Binaries
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt detects processes named as legit Microsoft native binaries located in the system32 folder. Adversaries may attempt to manipulate features of their artifacts to make them appear legitimate or benign to users and/or security tools. Masquerading occurs when the name or location of an object, legitimate or malicious, is manipulated or abused for the sake of evading defenses and observation.
- **UUID:** `93a72542-a1f7-4407-9175-8f066343db60`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -27,8 +28,8 @@ from logs-endpoint.events.process-*
## Notes
- Output of the query is the process.name and host.id, you can pivot by host.id and process.name(non Microsoft signed) to find the specific suspicious instances.
- Potential false positives include processes with missing code signature details due to enrichment bugs.
- Output of the query is the `process.name` and `host.id` where you can pivot by `host.id` and `process.name` (non Microsoft signed) to find the specific suspicious instances.
- Potential false-positives include processes with missing code signature details due to enrichment bugs.
- The queried index must capture process start events with code signature information (e.g. Windows event 4688 is not supported).
## MITRE ATT&CK Techniques
@@ -0,0 +1,58 @@
# Rare DLL Side-Loading by Occurrence
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies instances where a signed Windows process attempts to load an unsigned DLL from the same process folder. Matches are limited to a unique host with low library load occurrence. Adversaries may execute their own malicious payloads by side-loading malicious DLLs.
- **UUID:** `bcdb7c29-1312-4974-8f2e-10ddeb09cf5c`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and dll.Ext.relative_file_creation_time <= 86400
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and process.name != dll.name
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, dll.name, process.name, dll.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10 | keep total_count, host_count, dll_folder, dll.name, process.name, dll.hash.sha256
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and file.name != process.name
/* paths normalization by removing random patterns */
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, file.name, process.name, file.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10
| keep total_count, host_count, dll_folder, file.name, process.name, file.hash.sha256
```
## Notes
- This hunt has two optional queries, one for Elastic Defend data and another for Sysmon data.
- Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.
- Paths like `C:\\Users\\Public` and `C:\\ProgramData\\` are often observed in malware employing DLL side-loading.
- Elastic Defned DLL Events include `dll.Ext.relative_file_creation_time` which help us limit the hunt to recently dropped DLLs.
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.002](https://attack.mitre.org/techniques/T1574/002)
## License
- `Elastic License v2`
@@ -1,40 +0,0 @@
# Detect Rare DLL SideLoad by Occurrence - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `bcdb7c29-1312-4974-8f2e-10ddeb09cf5c`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and dll.Ext.relative_file_creation_time <= 86400
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and process.name != dll.name
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, dll.name, process.name, dll.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10 | keep total_count, host_count, dll_folder, dll.name, process.name, dll.hash.sha256
```
## Notes
- Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.
- Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.
- Elastic Defned DLL Events include dll.Ext.relative_file_creation_time which help us limit the hunt to recently dropped DLLs.
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.002](https://attack.mitre.org/techniques/T1574/002)
## License
- `Elastic License v2`
@@ -1,42 +0,0 @@
# Detect Rare DLL SideLoad by Occurrence - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `0df1e142-7d70-4112-be8d-6c60ac812883`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and file.name != process.name
/* paths normalization by removing random patterns */
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, file.name, process.name, file.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10
| keep total_count, host_count, dll_folder, file.name, process.name, file.hash.sha256
```
## Notes
- Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.
- Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.
- Elastic Defned DLL Events include dll.Ext.relative_file_creation_time which help us limit the hunt to recently dropped DLLs.
## MITRE ATT&CK Techniques
- [T1574](https://attack.mitre.org/techniques/T1574)
- [T1574.002](https://attack.mitre.org/techniques/T1574/002)
## License
- `Elastic License v2`
@@ -0,0 +1,52 @@
# Rare LSASS Process Access Attempts
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies instances where a process attempts to open the Local Security Authority Subsystem Service (LSASS) memory and where the number of occurences is limited to one unique agent and a low number of attempts. This may indicate either a rare legitimate condition or a malicious process attempting to obtain credentials or inject code into the LSASS.
- **UUID:** `3978e183-0b70-4e1c-8c40-24e367f6db5a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.api*
| where @timestamp > NOW() - 7 day
| where event.category == "api" and host.os.family == "windows" and process.Ext.api.name in ("OpenProcess", "OpenThread", "ReadProcessMemory") and
Target.process.name == "lsass.exe"
| keep process.executable.caseless, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process = replace(process.executable.caseless, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats occurences = count(process), agents = count_distinct(host.id) by process
| where agents == 1 and occurences <= 10
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where event.category == "process" and host.os.family == "windows" and event.action == "ProcessAccess" and
winlog.event_data.TargetImage in ("C:\\Windows\\system32\\lsass.exe", "c:\\Windows\\system32\\lsass.exe", "c:\\Windows\\System32\\lsass.exe")
| keep process.executable, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats occurences = count(process_path), agents = count_distinct(host.id) by process_path
| where agents == 1 and occurences <= 10
```
## Notes
- Based on the process.executable and process.name you can pivot and investigate further for the matching instances.
- Potential false-positives include rare legitimate conditions that may trigger this behavior due to third-party software or LSASS crashing.
## MITRE ATT&CK Techniques
- [T1003](https://attack.mitre.org/techniques/T1003)
- [T1003.001](https://attack.mitre.org/techniques/T1003/001)
## License
- `Elastic License v2`
@@ -1,37 +0,0 @@
# Detect Rare LSASS Process Access Attempts - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `3978e183-0b70-4e1c-8c40-24e367f6db5a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.api*
| where @timestamp > NOW() - 7 day
| where event.category == "api" and host.os.family == "windows" and process.Ext.api.name in ("OpenProcess", "OpenThread", "ReadProcessMemory") and
Target.process.name == "lsass.exe"
| keep process.executable.caseless, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process = replace(process.executable.caseless, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats occurences = count(process), agents = count_distinct(host.id) by process
| where agents == 1 and occurences <= 10
```
## Notes
- Based on the process.executable and process.name you can pivot and investigate further the matching instances.
- Potential false positives include rare legit condition that may trigger this behavior due to third party software or Lsass crash.
## MITRE ATT&CK Techniques
- [T1003](https://attack.mitre.org/techniques/T1003)
- [T1003.001](https://attack.mitre.org/techniques/T1003/001)
## License
- `Elastic License v2`
@@ -1,38 +0,0 @@
# Detect Rare LSASS Process Access Attempts - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `3978e183-0b70-4e1c-8c40-24e367f6db5a`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where event.category == "process" and host.os.family == "windows" and event.action == "ProcessAccess" and
winlog.event_data.TargetImage in ("C:\\Windows\\system32\\lsass.exe", "c:\\Windows\\system32\\lsass.exe", "c:\\Windows\\System32\\lsass.exe")
| keep process.executable, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats occurences = count(process_path), agents = count_distinct(host.id) by process_path
| where agents == 1 and occurences <= 10
```
## Notes
- Based on the process.executable and process.name you can pivot and investigate further the matching instances.
- Potential false positives include rare legit condition that may trigger this behavior due to third party software or Lsass crash.
## MITRE ATT&CK Techniques
- [T1003](https://attack.mitre.org/techniques/T1003)
- [T1003.001](https://attack.mitre.org/techniques/T1003/001)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Doamin Names queries via Lolbins and with low occurence frequency
# DNS Queries via LOLBins with Low Occurence Frequency
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for DNS queries performed by commonly abused Microsoft binaries that perform remote file transfer or binary proxy execution. Aggregations for the number of occurrences is limited to one host to reduce the number of potentially legitimate hits.
- **UUID:** `ebf8eb13-c98a-4d2c-8bdb-3f72a3a3961b`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -13,9 +15,9 @@
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and event.category == "network" and
event.action in ("lookup_requested", "DNSEvent (DNS query)") and
process.name in ("powershell.exe", "rundll32.exe", "certutil.exe", "curl.exe", "wget.exe", "CertReq.exe", "bitsadmin.exe", "mshta.exe", "pwsh.exe", "wmic.exe", "wscript.exe", "cscript.exe", "msbuild.exe", "regsvr32.exe", "MSBuild.exe", "InstallUtil.exe", "RegAsm.exe", "RegSvcs.exe", "msxsl.exe", "CONTROL.EXE", "Microsoft.Workflow.Compiler.exe", "msiexec.exe") and dns.question.name rlike """.+\.[a-z-A-Z]{2,3}"""
| where @timestamp > now() - 7 day and host.os.family == "windows" and event.category == "network" and
event.action in ("lookup_requested", "DNSEvent (DNS query)") and
process.name in ("powershell.exe", "rundll32.exe", "certutil.exe", "curl.exe", "wget.exe", "CertReq.exe", "bitsadmin.exe", "mshta.exe", "pwsh.exe", "wmic.exe", "wscript.exe", "cscript.exe", "msbuild.exe", "regsvr32.exe", "MSBuild.exe", "InstallUtil.exe", "RegAsm.exe", "RegSvcs.exe", "msxsl.exe", "CONTROL.EXE", "Microsoft.Workflow.Compiler.exe", "msiexec.exe") and dns.question.name rlike """.+\.[a-z-A-Z]{2,3}"""
| keep process.name, dns.question.name, host.id
| stats occurrences = count(*), hosts = count_distinct(host.id) by process.name, dns.question.name
| where hosts == 1
@@ -23,8 +25,8 @@ from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
## Notes
- Utilities like curl and SSL verification web-servvices are noisy, while others are rare like scripting utilities and are worth further investigation.
- Connection to legit domains like github, discord, telegram and many other legit web-services by lolbins is still suspicious and require further investigation.
- Utilities like curl and SSL verification for web services are noisy, while others are rare such as scripting utilities and are worth further investigation.
- Connection to legit domains like Github, Discord, Telegram and many other legit web services by LOLBins is still suspicious and require further investigation.
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
@@ -0,0 +1,57 @@
# Low Occurrence of Drivers Loaded on Unique Hosts
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt helps identify drivers loaded once on a unique host and with a unique hash over a 15 day period of time. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.
- **UUID:** `99818ad6-c242-4da7-a41a-df64fe7314d6`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver" and event.action == "load" and dll.Ext.relative_file_creation_time <= 900
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(dll.hash.sha256) by dll.name, dll.pe.imphash
| where host_count == 1 and total_count == 1 and hash_count == 1
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver"
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(file.hash.sha256) by file.name
| where host_count == 1 and total_count == 1 and hash_count == 1
```
```sql
from logs-system.system-*
| where @timestamp > now() - 15day
| where host.os.family == "windows" and event.code == "7045" and
winlog.event_data.ServiceType == "kernel mode driver"
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
## Notes
- This hunt has three optional queries, one for Elastic Defend data, another for Sysmon data and the last one for Windows 7045 events.
- Further investigation can be done pivoting by `dll.pe.imphash` or `dll.name.`
- `dll.Ext.relative_file_creation_time` is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).
- Aggregation can also be done by `dll.hash.sha256` / `file.hash.sha256` but will return more results.
- Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).
## MITRE ATT&CK Techniques
- [T1068](https://attack.mitre.org/techniques/T1068)
## License
- `Elastic License v2`
@@ -1,34 +0,0 @@
# Drivers Load with low occurrence frequency - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `99818ad6-c242-4da7-a41a-df64fe7314d6`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver" and event.action == "load" and dll.Ext.relative_file_creation_time <= 900
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(dll.hash.sha256) by dll.name, dll.pe.imphash
| where host_count == 1 and total_count == 1 and hash_count == 1
```
## Notes
- This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.
- dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).
- aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.
- Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).
## MITRE ATT&CK Techniques
- [T1068](https://attack.mitre.org/techniques/T1068)
## License
- `Elastic License v2`
@@ -1,34 +0,0 @@
# Drivers Load with low occurrence frequency - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `6bb90aba-af6b-4128-a9b2-160e164a15ff`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver"
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(file.hash.sha256) by file.name
| where host_count == 1 and total_count == 1 and hash_count == 1
```
## Notes
- This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.
- dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).
- aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.
- Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).
## MITRE ATT&CK Techniques
- [T1068](https://attack.mitre.org/techniques/T1068)
## License
- `Elastic License v2`
@@ -1,38 +0,0 @@
# Drivers Load with low occurrence frequency - Windows 7045
---
## Metadata
- **Author:** Elastic
- **UUID:** `bc4848ce-5323-42b4-a559-3333c11ca938`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-system.system-*
| where @timestamp > now() - 15day
| where host.os.family == "windows" and event.code == "7045" and
winlog.event_data.ServiceType == "kernel mode driver"
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
## Notes
- This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.
- dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).
- aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.
- Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).
## MITRE ATT&CK Techniques
- [T1068](https://attack.mitre.org/techniques/T1068)
## License
- `Elastic License v2`
@@ -1,37 +0,0 @@
# Excessive RDP Network Activity by Source Host and User- Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `fe01a8a5-6367-4c4c-a57b-be513ab80e42`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where count_unique_dst >= 10
```
## Notes
- This hunt looks for high number of Remote Desktop connections from same host and user.name to more than a defined threshold of unique destination Ip addresses. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol.
- Further investigation can done pivoting by host.id and user name.
- Depending on normal SysAdmin RDP activity the 10 threshold can be adjusted to reduce normal noisy activity.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
- [T1021.001](https://attack.mitre.org/techniques/T1021/001)
## License
- `Elastic License v2`
@@ -0,0 +1,48 @@
# Excessive RDP Network Activity by Host and User
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for a high occurrence of remote desktop connections from the same host and user. The number of unique destination IP addresses is compared to a defined threshold. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol (RDP).
- **UUID:** `fe01a8a5-6367-4c4c-a57b-be513ab80e42`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where count_unique_dst >= 10
```
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and process.name == "svchost.exe" and network.direction == "ingress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| stats agents = count_distinct(host.id) by source.ip
| where agents >= 10
```
## Notes
- Further investigation can done pivoting by `host.id` and `user.name`.
- Depending on normal SysAdmin RDP activity, the threshold of 10 can be adjusted to reduce normal noisy activity.
- The second query uses Windows Security log event ID 4624 to summarize numbers of RDP connections by `source.ip` and `user.name` and duration.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
- [T1021.001](https://attack.mitre.org/techniques/T1021/001)
## License
- `Elastic License v2`
@@ -1,35 +0,0 @@
# Excessive RDP Network Activity by Source Host - Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `6ff3a518-3bf4-4e7d-9a66-2ef7aaa68cfc`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and process.name == "svchost.exe" and network.direction == "ingress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| stats agents = count_distinct(host.id) by source.ip
| where agents >= 10
```
## Notes
- This hunt looks for high number of Remote Desktop connections from same host and user.name to more than a defined threshold of unique destination Ip addresses. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol.
- Further investigation can done pivoting by host.id and user name.
- Depending on normal SysAdmin RDP activity the 10 threshold can be adjusted to reduce normal noisy activity.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
- [T1021.001](https://attack.mitre.org/techniques/T1021/001)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Excessive SMB Network Activity by process Id
# Excessive SMB Network Activity by Process ID
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for a high occurrence of SMB connections from the same process by unique destination IP addresses. The number of unique destination IP addresses is compared to a defined threshold. This could be a sign of SMB scanning or lateral movement via remote services that depend on the SMB protocol.
- **UUID:** `6949135b-76d7-47a3-ae95-ef482508fb7c`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -12,9 +14,9 @@
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 445 and source.port >= 49152 and process.pid == 4
| keep destination.ip, process.entity_id, host.id
| stats count_unique_dst = count_distinct(destination.ip) by process.entity_id, host.id
@@ -24,9 +26,8 @@ from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
## Notes
- This hunt looks for high number of SMB connections from same process to more than a defined threshold of unique destination Ip addresses. This could be a sign of SMB scanning or some lateral movement via remote services that depend on SMB protocol.
- Further investigation can done pivoting by process.entity_id and host.id.
- Maximum number of unique destination.ip by process can be adjusted to your environment to reduce normal noisy hosts by Id.
- Further investigation can done pivoting by `process.entity_id` and `host.id.`
- Maximum number of unique `destination.ip` by process can be adjusted to your environment to reduce normal noisy hosts by process ID.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
@@ -0,0 +1,51 @@
# Executable File Creation by an Unusual Microsoft Binary
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies executable file creation by an unusual Microsoft native binary. This could be the result of
code injection or some other form of exploitation for defense evasion.
- **UUID:** `3b2900fe-74d9-4c49-b3df-cbeceb02e841`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "creation" and
starts_with(file.Ext.header_bytes, "4d5a") and process.code_signature.status == "trusted" and
starts_with(process.code_signature.subject_name, "Microsoft") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "FileCreate" and
file.extension in ("exe", "dll") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
```
## Notes
- This hunt includes two optional queries, one for Elastic Defend data and another for Sysmon data.
- Sysmon file events don't populate file header and process code signature information thus we use `file.extension`.
- Some exploits may result in the creation of an executable file by the exploited process.
- Further investigation can be done by pivoting on `process.executable` and filtering for executable file creation.
## MITRE ATT&CK Techniques
- [T1211](https://attack.mitre.org/techniques/T1211)
- [T1055](https://attack.mitre.org/techniques/T1055)
## License
- `Elastic License v2`
@@ -1,37 +0,0 @@
# Executable File creation by an Unusual Microsoft Binary - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `3b2900fe-74d9-4c49-b3df-cbeceb02e841`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "creation" and
starts_with(file.Ext.header_bytes, "4d5a") and process.code_signature.status == "trusted" and
starts_with(process.code_signature.subject_name, "Microsoft") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
```
## Notes
- Sysmon file event don't populate file header and process code signature information thus the use of file.extension.
- Some exploits may result in the creation of an executable file by the exploited process.
- Further investigation can be done pivoting by process.executable and filter for executable file creation.
## MITRE ATT&CK Techniques
- [T1211](https://attack.mitre.org/techniques/T1211)
- [T1055](https://attack.mitre.org/techniques/T1055)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Executable File creation by an Unusual Microsoft Binary - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `36c94354-9d6e-4dc5-b2aa-a7cf578a4169`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "FileCreate" and
file.extension in ("exe", "dll") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
```
## Notes
- Sysmon file event don't populate file header and process code signature information thus the use of file.extension.
- Some exploits may result in the creation of an executable file by the exploited process.
- Further investigation can be done pivoting by process.executable and filter for executable file creation.
## MITRE ATT&CK Techniques
- [T1211](https://attack.mitre.org/techniques/T1211)
- [T1055](https://attack.mitre.org/techniques/T1055)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Execution via Network Logon by occurrence frequency
---
## Metadata
- **Author:** Elastic
- **UUID:** `fd3f9982-fd8c-4f0f-bbe6-e589752c34db`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*), hosts = count_distinct(host.id) by process.hash.sha256, process.Ext.session_info.client_address, user.name, process.parent.name
/* unique hash limited to one host and number of execution is 1 */
| where hosts == 1 and total == 1
```
## Notes
- process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.
- Execution via legit Microsoft processes like powershell and cmd need to further investigated via aggregation by process.command_line.
- Aggregation can be also done by process.executable, normalizing process path by removing random patterns using the REPLACE function via regex.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Execution via Network Logon by occurrence frequency by top Source IP
# Frequency of Process Execution via Network Logon by Source Address
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt aggregates process execution and remote network logons by source address, account name and process hash. It then limits the results by unique host within a 7 day period. This may indicate lateral movement via remote services.
- **UUID:** `ae07c580-290e-4421-add8-d6ca30509b6a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -13,8 +15,8 @@
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*) by process.Ext.session_info.client_address, user.name
@@ -22,11 +24,23 @@ from logs-endpoint.events.process-*
| sort total desc
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*), hosts = count_distinct(host.id) by process.hash.sha256, process.Ext.session_info.client_address, user.name, process.parent.name
/* unique hash limited to one host and number of execution is 1 */
| where hosts == 1 and total == 1
```
## Notes
- process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.
- Execution via legit Microsoft processes like powershell and cmd need to further investigated via aggregation by process.command_line.
- Aggregation can be also done by process.executable, normalizing process path by removing random patterns using the REPLACE function via regex.
- The second query highest occurrence of source addresses/accounts performing remote process execution
- `process.Ext.session_info.*` is populated for Elastic Defend versions 8.6.0+ and above.
- Execution via legitimate Microsoft processes for PowerShell and cmd need to be further investigated via aggregation by `process.command_line`.
- Aggregation can be also done by `process.executable`, normalizing process path by removing random patterns using the ES|QL REPLACE function.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
@@ -5,6 +5,8 @@
## Metadata
- **Author:** Elastic
- **Description:** This hunt aggregates process execution via remote network logon by source address, account name and where the parent process is related to remote services such as WMI, WinRM, DCOM and remote PowerShell. This may indicate lateral movement via remote services.
- **UUID:** `e6e54717-2676-4785-a4a6-503577bfb0ea`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -13,10 +15,10 @@
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type */
process.Ext.session_info.logon_type == "Network" and
process.Ext.session_info.logon_type == "Network" and
(process.parent.name .caseless in ("wmiprvse.exe", "wsmprovhost.exe", "winrshost.exe") or (process.parent.name == "svchost.exe" and process.parent.args == "DcomLaunch"))
| stats total = count(*), hosts = count_distinct(host.id) by process.Ext.session_info.client_address, user.name, process.parent.name
/* sort by top source.ip and account */
@@ -25,7 +27,7 @@ from logs-endpoint.events.process-*
## Notes
- process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.
- `process.Ext.session_info.*` is populated for Elastic Defend versions 8.6.0+.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
@@ -1,10 +1,12 @@
# Execution via Startup with low occurrence frequency
# Startup Execution with Low Occurrence Frequency by Unique Host
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies programs started shortly after user logon and presence limited to a unique host. Run registry key and Startup folder cause programs to run each time that a user logs on and are often abused by malwares to maintain persistence on an endpoint.
- **UUID:** `a447df80-d3d5-48b3-a175-a864264ec487`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -13,10 +15,10 @@
```sql
from logs-endpoint.events.process-*
| where host.os.family == "windows" and event.category == "process" and event.action == "start" and
| where host.os.family == "windows" and event.category == "process" and event.action == "start" and
/* programs started shortly after user logon like startup items */
process.parent.executable.caseless == "c:\\windows\\explorer.exe" and process.Ext.session_info.relative_logon_time <= 100 and
not starts_with(process.executable, "C:\\Program Files") and not starts_with(process.executable, "C:\\Windows\\System32\\DriverStore\\FileRepository\\") and
process.parent.executable.caseless == "c:\\windows\\explorer.exe" and process.Ext.session_info.relative_logon_time <= 100 and
not starts_with(process.executable, "C:\\Program Files") and not starts_with(process.executable, "C:\\Windows\\System32\\DriverStore\\FileRepository\\") and
/* this hunt is scoped to unsigned or untrusted code-sig or Microsoft signed binaries to not miss lolbins */
(process.code_signature.exists == false or process.code_signature.trusted == false or starts_with(process.code_signature.subject_name, "Microsoft"))
| keep process.executable, host.id, process.hash.sha256
@@ -28,8 +30,8 @@ from logs-endpoint.events.process-*
## Notes
- Items set to persist via Startup like Run key and Startup folder will be executed by Explorer.exe shortly after user logon (process.Ext.session_info.relative_logon_time help us to capture that time difference).
- Pay close attention to unknown hashes, suspicious paths and lolbins.
- Items set to persist via Startup such as Run keys and Startup folder will be executed by `Explorer.exe` shortly after user logon (`process.Ext.session_info.relative_logon_time` helps us to capture that time difference).
- Special attention to unknown hashes, suspicious paths and LOLBins should be given.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
@@ -0,0 +1,58 @@
# Low Frequency of Process Execution via WMI by Unique Agent
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for unique process execution via Windows Management Instrumentation (WMI) by removing random patterns from `process.command_line` and aggregating execution by count of agents with the same command line to limit results to unique ones.
- **UUID:** `b5efeb92-9b51-45b9-839f-be4cdc054ef4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
to_lower(process.parent.name) == "wmiprvse.exe" and starts_with(process.code_signature.subject_name, "Microsoft")
| keep process.hash.sha256, host.id, process.name
| stats agents = count_distinct(host.id) by process.name
| where agents == 1
```
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and
event.action in ("start", "Process creation", "created-process") and
process.parent.name.caseless == "wmiprvse.exe"
| keep process.command_line, host.id
| eval cmdline = replace(process.command_line, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| eval cmdline = replace(cmdline, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats agents = count_distinct(host.id) by cmdline
| where agents == 1
```
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
process.parent.name.caseless == "wmiprvse.exe" and (process.code_signature.exists == false or process.code_signature.trusted == false)
| keep process.hash.sha256, host.id, process.name
| stats agents = count_distinct(host.id) by process.hash.sha256
| where agents == 1
```
## Notes
- This hunt contains three queries for Elastic Defend, Sysmon, and Windows Security event 4688.
## MITRE ATT&CK Techniques
- [T1047](https://attack.mitre.org/techniques/T1047)
## License
- `Elastic License v2`
@@ -1,34 +0,0 @@
# Execution via Windows Management Instrumentation by occurrence frequency by Unique Agent - Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `b5efeb92-9b51-45b9-839f-be4cdc054ef4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
process.parent.name.caseless == "wmiprvse.exe" and starts_with(process.code_signature.subject_name, "Microsoft")
| keep process.hash.sha256, host.id, process.name
| stats agents = count_distinct(host.id) by process.name
| where agents == 1
```
## Notes
- This hunt looks for unique process execution via Windows Management Instrumentation by removing random patterns from process.command_line and aggregating execution by count of agents with same cmdline to limit result to unique ones.
- This hunt is compatible with Sysmon, Elastic Defend and Windows Security event 4688.
## MITRE ATT&CK Techniques
- [T1047](https://attack.mitre.org/techniques/T1047)
## License
- `Elastic License v2`
@@ -1,34 +0,0 @@
# Execution via Windows Management Instrumentation by occurrence frequency - Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `958a9027-2c6f-4eb0-a9ca-d1116a3bec76`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
process.parent.name.caseless == "wmiprvse.exe" and (process.code_signature.exists == false or process.code_signature.trusted == false)
| keep process.hash.sha256, host.id, process.name
| stats agents = count_distinct(host.id) by process.hash.sha256
| where agents == 1
```
## Notes
- This hunt looks for unique process execution via Windows Management Instrumentation by removing random patterns from process.command_line and aggregating execution by count of agents with same cmdline to limit result to unique ones.
- This hunt is compatible with Sysmon, Elastic Defend and Windows Security event 4688.
## MITRE ATT&CK Techniques
- [T1047](https://attack.mitre.org/techniques/T1047)
## License
- `Elastic License v2`
@@ -1,37 +0,0 @@
# Execution via Windows Management Instrumentation by occurrence frequency - Elastic Defend - Sysmon - Windows Security
---
## Metadata
- **Author:** Elastic
- **UUID:** `793d5655-d7d9-422a-ba9d-1fa75029265e`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "process" and
event.action in ("start", "Process creation", "created-process") and
process.parent.name.caseless == "wmiprvse.exe"
| keep process.command_line, host.id
| eval cmdline = replace(process.command_line, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| eval cmdline = replace(cmdline, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats agents = count_distinct(host.id) by cmdline
| where agents == 1
```
## Notes
- This hunt looks for unique process execution via Windows Management Instrumentation by removing random patterns from process.command_line and aggregating execution by count of agents with same cmdline to limit result to unique ones.
- This hunt is compatible with Sysmon, Elastic Defend and Windows Security event 4688.
## MITRE ATT&CK Techniques
- [T1047](https://attack.mitre.org/techniques/T1047)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Execution via Windows Scheduled Task with low occurrence frequency
# Low Frequency of Process Execution via Windows Scheduled Task by Unique Agent
---
## Metadata
- **Author:** Elastic
- **Description:** Aggregating by paths/hash, this hunt identifies rare instances where a program executes as a child process of the Tasks Scheduler service. This could be the result of persistence as a Windows Scheduled Task.
- **UUID:** `96d5afc8-1f25-4265-8a0e-9998091a2e1f`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -13,9 +15,9 @@
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and
event.action in ("start", "Process creation") and process.code_signature.trusted != true and
| where @timestamp > now(-) - 7 day
| where host.os.family == "windows" and event.category == "process" and
event.action in ("start", "Process creation") and process.code_signature.trusted != true and
/* child process of the Tasks Schedule service */
process.parent.name == "svchost.exe" and ends_with(process.parent.command_line, "Schedule")
| stats hosts = count_distinct(host.id) by process.hash.sha256, process.name
@@ -25,8 +27,8 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
## Notes
- Windows security event 4688 lacks process.parent.command_line needed for this hunt to identify the Schedule svchost instance.
- Unique process.hash.sha256 and agent is not necessarily malicious, this help surface ones worth further investigation.
- Windows security event 4688 lacks `process.parent.command_line` needed for this hunt to identify the Schedule `svchost` instance.
- Unique `process.hash.sha256` and agent is not necessarily malicious, however this helps surface signals worth further investigation.
## MITRE ATT&CK Techniques
- [T1053](https://attack.mitre.org/techniques/T1053)
@@ -0,0 +1,51 @@
# Low Occurence of Process Execution via Windows Services with Unique Agent
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for a low occurrence of process execution via the Windows Services Control Manager by unique agent. The Services Control Manager is responsible for starting, stopping, and interacting with system services. This could be a sign of persistence as a Windows service.
- **UUID:** `858b7022-b587-4b95-afd6-8ce597bedce3`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
process.parent.name == "services.exe" and process.code_signature.trusted != true
| stats hosts = count_distinct(host.id) by process.hash.sha256, process.name
/* unique hash observed in one unique agent */
| where hosts == 1
```
```sql
from logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.code == "4688" and
event.action == "created-process" and process.parent.name == "services.exe"
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats hosts = count_distinct(host.id) by process_path
/* unique path observed in one unique agent */
| where hosts == 1
```
## Notes
- This hunt contains two queries for Elastic Defend and Windows Security event 4688.
- Windows security event 4688 lacks code signature and hash information, hence the use of `process.executable` for aggregation.
- Unique `process.hash.sha256` and agent is not necessarily malicious, this help surface ones worth further investigation.
- Suspicious `process.executable` paths and LOLBins should be reviewed further.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Execution via Windows Services with low occurrence frequency - Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `858b7022-b587-4b95-afd6-8ce597bedce3`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation") and
process.parent.name == "services.exe" and process.code_signature.trusted != true
| stats hosts = count_distinct(host.id) by process.hash.sha256, process.name
/* unique hash observed in one unique agent */
| where hosts == 1
```
## Notes
- Windows security event 4688 lacks code signature and hash information, hence the use of process.executable for aggregation.
- Unique process.hash.sha256 and agent is not necessarily malicious, this help surface ones worth further investigation.
- Suspicious process.executable paths and lolbins should be reviewed further.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,38 +0,0 @@
# Execution via Windows Services with low occurrence frequency - Windows Security
---
## Metadata
- **Author:** Elastic
- **UUID:** `5fdc9f73-c6a4-4ea4-8e16-347ed675e236`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.code == "4688" and
event.action == "created-process" and process.parent.name == "services.exe"
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats hosts = count_distinct(host.id) by process_path
/* unique path observed in one unique agent */
| where hosts == 1
```
## Notes
- Windows security event 4688 lacks code signature and hash information, hence the use of process.executable for aggregation.
- Unique process.hash.sha256 and agent is not necessarily malicious, this help surface ones worth further investigation.
- Suspicious process.executable paths and lolbins should be reviewed further.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -0,0 +1,77 @@
# High Count of Network Connection Over Extended Period by Process
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies browser or svchost instances performing a considerable number of connections per hour over an extended period of hours to a specific destination address, limited to a unique host of the monitored agents. Browsers and svchost are both good targets for masquerading network traffic on the endpoint.
- **UUID:** `ed254a22-e7bb-4a36-9291-196b77762dd8`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and process.name in ("chrome.exe", "msedge.exe", "iexplore.exe", "firefox.exe", "svchost.exe") and
/* excluding DNS */
destination.port != 53 and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp, host.id
/* calc total duration and the number of connections per hour */
| stats count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp), hosts= count_distinct(host.id), count_unique_pids = count_distinct(process.entity_id) by destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.name, duration_hours, destination.address, hosts, count_unique_pids, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute during 4 hours and limited to 1 agent and 1 pid, you can adjust this values to your hunting needs */
| where number_of_con_per_hour >= 120 and duration_hours >= 4 and hosts == 1 and count_unique_pids == 1
```
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and
(process.code_signature.exists == false or process.code_signature.trusted != true or starts_with(process.executable, "C:\\Users\\Public\\")) and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
/* calc total duration , total MB out and the number of connections per hour */
| stats total_bytes_out = sum(source.bytes), count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp) by process.entity_id, destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), MB_out=TO_DOUBLE(total_bytes_out) / (1024*1024), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.entity_id, process.name, duration_hours, destination.address, MB_out, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute , you can adjust it to your env/FP rate */
| where duration_hours >= 1 and number_of_con_per_hour >= 120
```
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and (process.executable like "C:\\\\Windows\\\\System32*" or process.executable like "C:\\\\Windows\\\\SysWOW64\\\\*") and not user.id in ("S-1-5-19", "S-1-5-20") and
/* multiple Windows svchost services perform long term connection to MS ASN, can be covered in a dedicated hunt */
not (process.name == "svchost.exe" and user.id == "S-1-5-18") and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
/* calc total duration , total MB out and the number of connections per hour */
| stats total_bytes_out = sum(source.bytes), count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp) by process.entity_id, destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), MB_out=TO_DOUBLE(total_bytes_out) / (1024*1024), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.entity_id, process.name, duration_hours, destination.address, MB_out, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute , you can adjust it to your env/FP rate */
| where duration_hours >= 1 and number_of_con_per_hour >= 120
```
## Notes
- This hunt includes three queries for Elastic Defend and Sysmon data sources.
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
## License
- `Elastic License v2`
@@ -1,40 +0,0 @@
# High count of network connection over extended period by process - Elastic Defend Network
---
## Metadata
- **Author:** Elastic
- **UUID:** `76843f1f-404d-42b8-9c25-fcc14e270240`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and
(process.code_signature.exists == false or process.code_signature.trusted != true or starts_with(process.executable, "C:\\Users\\Public\\")) and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
/* calc total duration , total MB out and the number of connections per hour */
| stats total_bytes_out = sum(source.bytes), count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp) by process.entity_id, destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), MB_out=TO_DOUBLE(total_bytes_out) / (1024*1024), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.entity_id, process.name, duration_hours, destination.address, MB_out, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute , you can adjust it to your env/FP rate */
| where duration_hours >= 1 and number_of_con_per_hour >= 120
```
## Notes
- This hunt aggregate by process Id and destination ip the number of connections per hour over a period of time greater than a defined threshold. The process paths are scoped to Microsoft signed binaries often injected or used as a lolbin to masquerade malicious execution. This could be a sign of long term network activity to perform command and control from an injected process. Scoped for unsigned processes or ones running from suspicious paths, the Sysmon network events don't include process code signature information
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
## License
- `Elastic License v2`
@@ -1,40 +0,0 @@
# High count of network connection over extended period by process - Elastic Defend Network - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `ed254a22-e7bb-4a36-9291-196b77762dd8`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and process.name in ("chrome.exe", "msedge.exe", "iexplore.exe", "firefox.exe", "svchost.exe") and
/* excluding DNS */
destination.port != 53 and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp, host.id
/* calc total duration and the number of connections per hour */
| stats count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp), hosts= count_distinct(host.id), count_unique_pids = count_distinct(process.entity_id) by destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.name, duration_hours, destination.address, hosts, count_unique_pids, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute during 4 hours and limited to 1 agent and 1 pid, you can adjust this values to your hunting needs */
| where number_of_con_per_hour >= 120 and duration_hours >= 4 and hosts == 1 and count_unique_pids == 1
```
## Notes
- This hunt identify browser or svchost instances performing a considerable number of connections per hour over an extended period of hours to a specific destination address and this is limited to a unique host of the monitored agents. Browsers and svchost are both good targets for masquerading network traffic on the endpoint.
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
## License
- `Elastic License v2`
@@ -1,41 +0,0 @@
# High count of network connection over extended period by process - Elastic Defend - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `7ee9a5a7-3ce1-47eb-b15a-1b148299fcf0`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and
network.direction == "egress" and (process.executable like "C:\\\\Windows\\\\System32*" or process.executable like "C:\\\\Windows\\\\SysWOW64\\\\*") and not user.id in ("S-1-5-19", "S-1-5-20") and
/* multiple Windows svchost services perform long term connection to MS ASN, can be covered in a dedicated hunt */
not (process.name == "svchost.exe" and user.id == "S-1-5-18") and
/* excluding private IP ranges */
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.name, process.entity_id, @timestamp
/* calc total duration , total MB out and the number of connections per hour */
| stats total_bytes_out = sum(source.bytes), count_connections = count(*), start_time = min(@timestamp), end_time = max(@timestamp) by process.entity_id, destination.address, process.name
| eval dur = TO_DOUBLE(end_time)-TO_DOUBLE(start_time), duration_hours=TO_INT(dur/3600000), MB_out=TO_DOUBLE(total_bytes_out) / (1024*1024), number_of_con_per_hour = (count_connections / duration_hours)
| keep process.entity_id, process.name, duration_hours, destination.address, MB_out, count_connections, number_of_con_per_hour
/* threshold is set to 120 connections per minute , you can adjust it to your env/FP rate */
| where duration_hours >= 1 and number_of_con_per_hour >= 120
```
## Notes
- This hunt aggregate by process Id and destination ip the number of connections per hour over a period of time greater than a defined threshold. The process paths are scoped to Microsoft signed binaries often injected or used as a lolbin to masquerade malicious execution. This could be a sign of long term network activity to perform command and control from an injected process.
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
## License
- `Elastic License v2`
@@ -0,0 +1,60 @@
# Libraries Loaded by svchost with Low Occurrence Frequency
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt returns the SHA256 hash and the `dll.path` of unsigned libraries loaded by svchost where the presence of unique path/hash is limited to a unique host. Adversaries may use Windows service DLLs to maintain persistence or run with System privileges.
- **UUID:** `e37fe0b9-1b70-4800-8989-58bac5a0a9bb`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "library" and event.action == "load" and
process.name == "svchost.exe" and (dll.code_signature.trusted == false or dll.code_signature.exists == false) and dll.hash.sha256 like "?*" and
(dll.Ext.relative_file_creation_time <= 900 or dll.Ext.relative_file_name_modify_time <= 900)
| keep dll.name, dll.path, dll.hash.sha256, host.id
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
/* paths normalization by removing random patterns */
| eval dll_path = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "replaced")
| eval dll_path = replace(dll_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| eval dll_path = replace(dll_path, """SoftwareDistribution\\Download\\[a-z0-9]+""", """SoftwareDistribution\\Download\\""")
| stats hosts = count_distinct(host.id), count_dlls_per_folder = count(dll_path) by dll_path, dll.name, dll.hash.sha256
| where hosts == 1 and count_dlls_per_folder == 1
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and
process.name == "svchost.exe" and file.code_signature.status != "Valid" and file.hash.sha256 like "?*"
| keep file.name, file.path, file.hash.sha256, host.id
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
/* paths normalization by removing random patterns */
| eval dll_path = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "replaced")
| eval dll_path = replace(dll_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| eval dll_path = replace(dll_path, """SoftwareDistribution\\Download\\[a-z0-9]+""", """SoftwareDistribution\\Download\\""")
| stats hosts = count_distinct(host.id), count_dlls_per_folder = count(dll_path) by dll_path, file.name, file.hash.sha256
| where hosts == 1 and count_dlls_per_folder == 1
```
## Notes
- This hunt includes two queries to cover both Sysmon and Elastic Defend data sources.
- The hunt uses Elastic Defend library events for an extra optional condition `dll.Ext.relative_file_creation_time` to scope if for recently dropped DLLs.
- The `count_dlls_per_folder` variable filter is used to avoid cases where multiple DLLs with different names are loaded from same directory (often observed in FPs loaded multiple dependencies from same dir).
- Pay close attention unknown hashes and suspicious paths, usually ServiceDLLs are located in trusted directories like `%programfiles%` and `system32/syswow64`.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,42 +0,0 @@
# Libraries loaded by svchost with low occurrence frequency - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `e37fe0b9-1b70-4800-8989-58bac5a0a9bb`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "library" and event.action == "load" and
process.name == "svchost.exe" and (dll.code_signature.trusted == false or dll.code_signature.exists == false) and dll.hash.sha256 like "?*" and
(dll.Ext.relative_file_creation_time <= 900 or dll.Ext.relative_file_name_modify_time <= 900)
| keep dll.name, dll.path, dll.hash.sha256, host.id
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
/* paths normalization by removing random patterns */
| eval dll_path = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "replaced")
| eval dll_path = replace(dll_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| eval dll_path = replace(dll_path, """SoftwareDistribution\\Download\\[a-z0-9]+""", """SoftwareDistribution\\Download\\""")
| stats hosts = count_distinct(host.id), count_dlls_per_folder = count(dll_path) by dll_path, dll.name, dll.hash.sha256
| where hosts == 1 and count_dlls_per_folder == 1
```
## Notes
- The hunt using Elastic Defend library events uses an extra optional condition dll.Ext.relative_file_creation_time to scope if for recently dropped DLLs.
- The count_dlls_per_folder variable filter is used to avoid cases where multiple DLLs with different names are loaded from same directory (often observed in FPs loaded multiple dependencies from same dir).
- Pay close attention unknown hashes and suspicious paths, usually ServiceDLLs are located in trusted directories like %programfiles% and system32/syswow64.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,41 +0,0 @@
# Libraries loaded by svchost with low occurrence frequency - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `1ae6bfd7-34ce-4d7b-b956-f12d3797ac68`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and
process.name == "svchost.exe" and file.code_signature.status != "Valid" and file.hash.sha256 like "?*"
| keep file.name, file.path, file.hash.sha256, host.id
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
/* paths normalization by removing random patterns */
| eval dll_path = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "replaced")
| eval dll_path = replace(dll_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| eval dll_path = replace(dll_path, """SoftwareDistribution\\Download\\[a-z0-9]+""", """SoftwareDistribution\\Download\\""")
| stats hosts = count_distinct(host.id), count_dlls_per_folder = count(dll_path) by dll_path, file.name, file.hash.sha256
| where hosts == 1 and count_dlls_per_folder == 1
```
## Notes
- The hunt using Elastic Defend library events uses an extra optional condition dll.Ext.relative_file_creation_time to scope if for recently dropped DLLs.
- The count_dlls_per_folder variable filter is used to avoid cases where multiple DLLs with different names are loaded from same directory (often observed in FPs loaded multiple dependencies from same dir).
- Pay close attention unknown hashes and suspicious paths, usually ServiceDLLs are located in trusted directories like %programfiles% and system32/syswow64.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Microsoft Office Child Processes with low occurrence frequency
# Microsoft Office Child Processes with Low Occurrence Frequency by Unique Agent
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for Microsoft Office child processes with low occurrence frequency. This could be a normal rare behavior as well as potential execution via a malicious document. Adversaries may use Microsoft Office applications to execute malicious code, such as macros, scripts, or other payloads.
- **UUID:** `74b2e54b-7002-4201-83d6-7fd9bd5dcf0f`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -13,18 +15,18 @@
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*
| where host.os.family == "windows" and @timestamp > NOW() - 15 day and
event.category == "process" and event.action in ("start", "Process creation", "created-process") and
process.parent.name.caseless in ("winword.exe", "excel.exe", "powerpnt.exe") and not starts_with(process.executable, "C:\\Program Files")
| where host.os.family == "windows" and @timestamp > NOW() - 15 day and
event.category == "process" and event.action in ("start", "Process creation", "created-process") and
to_lower(process.parent.name) in ("winword.exe", "excel.exe", "powerpnt.exe") and not starts_with(process.executable, "C:\\Program Files")
// normalize user home profile paths
| eval process_path = replace(process.executable.caseless, """[c]:\\[u][s][e][r][s]\\[a-zA-Z0-9\.\-\_\$]+\\""", "c:\\\\users\\\\user\\\\")
| stats occurrences = count(*), agents = count_distinct(agent.id) by process_path, process.parent.name
| eval process_path = replace(to_lower(process.executable), """[c]:\\[u][s][e][r][s]\\[a-zA-Z0-9\.\-\_\$]+\\""", "c:\\\\users\\\\user\\\\")
| stats occurrences = count(*), agents = count_distinct(agent.id) by process_path, process.parent.name
| where occurrences == 1 and agents == 1
```
## Notes
- Certain processes like WerFault.exe, dw20.exe and dwwin.exe are often related to application crash.
- Certain processes like `WerFault.exe`, `dw20.exe` and `dwwin.exe` are often related to application crash.
- Closer attention should be attributed to lolbins and unsigned executables (Windows 4688 is not capturing process code signature information).
## MITRE ATT&CK Techniques
@@ -1,10 +1,12 @@
# Network Discovery via sensitive ports by unusual process
# Network Discovery via Sensitive Ports by Unusual Process
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for either processes connecting to multiple sensitive TCP ports (SMB, RDP, LDAP, Kerberos and ADWS), a high number of SMB/RDP connections to unique destinations or the same process connecting to both RDP and SMB (should be rare).
- **UUID:** `e0acab7d-30bd-4be0-9682-5c3457bbeb4f`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -12,10 +14,10 @@
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port in (3389, 445, 389, 9389, 88, 5985, 5986, 22) and source.port >= 49152 and
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port in (3389, 445, 389, 9389, 88, 5985, 5986, 22) and source.port >= 49152 and
process.pid != 4
| keep process.executable, destination.port, destination.ip, process.entity_id
/* network events with SMB or RDP as a target */
@@ -1,10 +1,12 @@
# PE File Transfer via SMB_Admin Shares by Agent
# PE File Transfer via SMB_Admin Shares by Agent or User
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for a high number of executable file transfers via the SMB protocol by the same user or agent to more than a defined maxium threshold of targets. This could be a sign of lateral movement via the Windows Admin Shares.
- **UUID:** `3e66fc1a-2ea0-43a6-ba51-0280c693d152`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -13,17 +15,26 @@
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action != "deletion" and process.pid == 4 and
starts_with(file.Ext.header_bytes, "4d5a*") and (starts_with(user.id, "S-1-5-21-") or starts_with(user.id, "S-1-12-1-"))
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action != "deletion" and process.pid == 4 and
starts_with(file.Ext.header_bytes, "4d5a*") and (starts_with(user.id, "S-1-5-21-") or starts_with(user.id, "S-1-12-1-"))
| stats agents = count_distinct(host.id), total = count(*) by user.name
| where agents == 1 and total <= 3
```
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action != "deletion" and process.pid == 4 and
starts_with(file.Ext.header_bytes, "4d5a*") and (starts_with(user.id, "S-1-5-21-") or starts_with(user.id, "S-1-12-1-"))
| stats agents = count_distinct(host.id), total = count(*) by user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where agents >= 10
```
## Notes
- This hunt looks for high number of executable file transfer via the SMB protocol by the same user.name to more than a defined maxium threshold of targets. This could be a sign of lateral movement via the Windows Admin Shares.
- Further investigation can done pivoting by host.id and user name.
- Further investigation can done pivoting by `host.id` and `user.name`.
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
@@ -1,35 +0,0 @@
# PE File Transfer via SMB_Admin Shares by User
---
## Metadata
- **Author:** Elastic
- **UUID:** `ef9def35-0671-4599-8a18-5a1b833ef4c4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action != "deletion" and process.pid == 4 and
starts_with(file.Ext.header_bytes, "4d5a*") and (starts_with(user.id, "S-1-5-21-") or starts_with(user.id, "S-1-12-1-"))
| stats agents = count_distinct(host.id), total = count(*) by user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where agents >= 10
```
## Notes
- This hunt looks for high number of executable file transfer via the SMB protocol by the same user.name to more than a defined maxium threshold of targets. This could be a sign of lateral movement via the Windows Admin Shares.
- PE File Transfer via SMB/Admin Shares by User
## MITRE ATT&CK Techniques
- [T1021](https://attack.mitre.org/techniques/T1021)
- [T1021.002](https://attack.mitre.org/techniques/T1021/002)
## License
- `Elastic License v2`
@@ -0,0 +1,57 @@
# Persistence via Run Key with Low Occurrence Frequency
---
## Metadata
- **Author:** Elastic
- **Description:** Leveraging frequency based analysis and random values normalization, this hunt identifies instances where a program adds a persistence entry with rare values or are imited to unique hosts. Run registry key cause programs to run each time that a user logs on and are often abused by adversaries to maintain persistence on an endpoint.
- **UUID:** `1078e906-0485-482e-bcf3-7ee939e07020`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.registry-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action == "modification" and
(process.code_signature.exists == false or starts_with(process.code_signature.subject_name, "Microsoft")) and
ends_with(registry.key,"\\Microsoft\\Windows\\CurrentVersion\\Run") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.{1,2}[c-fC-F]:\\WINDOWS\\System32\\DriverStore\\FileRepository\\.+)"""
| keep registry.key, registry.data.strings, process.name, host.id
/* Paths normalization in registry.data.strings to ease aggregation */
| eval registry_data = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval registry_data = replace(registry_data, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by process.name, registry_data
| where hosts == 1 and cc == 1
```
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action == "RegistryEvent (Value Set)" and
ends_with(registry.key,"\\Microsoft\\Windows\\CurrentVersion\\Run") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.{1,2}[c-fC-F]:\\WINDOWS\\System32\\DriverStore\\FileRepository\\.+)"""
| keep registry.key, registry.data.strings, process.name, host.id
/* Paths normalization in registry.data.strings to ease aggregation */
| eval registry_data = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval registry_data = replace(registry_data, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by process.name, registry_data
| where hosts == 1 and cc == 1
```
## Notes
- This hunt includes two queries to cover both Sysmon and Elastic Defend data sources.
- Sysmon registry events do not populate process code signature information (hence the separation of the queries).
- Suspicious paths and LOLBins in the `registry.data.strings` value should be reviewed further.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
- [T1547.001](https://attack.mitre.org/techniques/T1547/001)
## License
- `Elastic License v2`
@@ -1,40 +0,0 @@
# Persistence via Run Key with low occurrence frequency - Elastic Defend
---
## Metadata
- **Author:** Elastic
- **UUID:** `1078e906-0485-482e-bcf3-7ee939e07020`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.registry-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action == "modification" and
(process.code_signature.exists == false or starts_with(process.code_signature.subject_name, "Microsoft")) and
ends_with(registry.key,"\\Microsoft\\Windows\\CurrentVersion\\Run") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.{1,2}[c-fC-F]:\\WINDOWS\\System32\\DriverStore\\FileRepository\\.+)"""
| keep registry.key, registry.data.strings, process.name, host.id
/* Paths normalization in registry.data.strings to ease aggregation */
| eval registry_data = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval registry_data = replace(registry_data, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by process.name, registry_data
| where hosts == 1 and cc == 1
```
## Notes
- Sysmon registry event don't populate process code signature information (hence the separation of the queries).
- Suspicious paths and lolbins in the registry.data.strings value should be reviewed further.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
- [T1547.001](https://attack.mitre.org/techniques/T1547/001)
## License
- `Elastic License v2`
@@ -1,39 +0,0 @@
# Persistence via Run Key with low occurrence frequency - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `cb2d8acc-123a-4578-bd33-7004c2be9843`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action == "RegistryEvent (Value Set)" and
ends_with(registry.key,"\\Microsoft\\Windows\\CurrentVersion\\Run") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.{1,2}[c-fC-F]:\\WINDOWS\\System32\\DriverStore\\FileRepository\\.+)"""
| keep registry.key, registry.data.strings, process.name, host.id
/* Paths normalization in registry.data.strings to ease aggregation */
| eval registry_data = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval registry_data = replace(registry_data, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by process.name, registry_data
| where hosts == 1 and cc == 1
```
## Notes
- Sysmon registry event don't populate process code signature information (hence the separation of the queries).
- Suspicious paths and lolbins in the registry.data.strings value should be reviewed further.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
- [T1547.001](https://attack.mitre.org/techniques/T1547/001)
## License
- `Elastic License v2`
@@ -1,10 +1,11 @@
# Persistence via Startup with low occurrence frequency
# Persistence via Startup with Low Occurrence Frequency by Unique Host
---
## Metadata
- **Author:** Elastic
- **Description:** Leveraging frequency based analysis and path normalization, this hunt identifies rare instances where a program adds a Startup persistence via file creation. Startup entries cause programs to run each time that a user logs on and are often abused by adversaries to maintain persistence on an endpoint.
- **UUID:** `9d8c79fd-0006-4988-8aaa-d5f9b9a7df8e`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -14,7 +15,7 @@
```sql
from logs-endpoint.events.file-*, logs-windows.sysmon_operational-default-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action in ("creation", "FileCreate") and
| where host.os.family == "windows" and event.category == "file" and event.action in ("creation", "FileCreate") and
file.path rlike """(C:\\Users\\.+\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\.+*|C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\StartUp\\.+)"""
| keep process.executable, host.id, file.name
/* Paths normalization in registry.data.strings to ease aggregation */
@@ -26,9 +27,9 @@ from logs-endpoint.events.file-*, logs-windows.sysmon_operational-default-*
## Notes
- Elastic Defend file event captures the process.code_signature information, this can be added to the hunt to limit to unsigned and Microsoft signed programs.
- Unique file.name and limited to 1 agent is not necessarily malicious, this help surface ones worth further investigation.
- Suspicious process.executable paths and lolbins should be reviewed further.
- Elastic Defend file event captures the `process.code_signature` information, this can be added to the hunt to limit to unsigned and Microsoft signed programs.
- Unique `file.name` and limited to one agent is not necessarily malicious, however helps surface ones worth further investigation.
- Suspicious `process.executable` paths and LOLBins should be reviewed further.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
@@ -1,10 +1,12 @@
# Persistence via Suspicious Launch Agent or Launch Daemon with low occurrence
# Low Occurrence of Suspicious Launch Agent or Launch Daemon
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for persistence via Launch agent or daemon where the distribution is limited to one unique host.
- **UUID:** `a7dcd1a1-2860-491e-8802-31169a607167`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -14,7 +16,7 @@
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 7 day
| where host.os.family == "macos" and event.category == "file" and event.action == "launch_daemon" and
| where host.os.family == "macos" and event.category == "file" and event.action == "launch_daemon" and
(Persistence.runatload == true or Persistence.keepalive == true) and process.executable is not null
| eval args = MV_CONCAT(Persistence.args, ",")
/* normalizing users home profile */
@@ -25,8 +27,7 @@ from logs-endpoint.events.file-*
## Notes
- This hunt looks for persistence via Launch agent or daemon where the distribution is limited to one unique host.
- Further investigation can done pivoting by Persistence.name and args.
- Further investigation can done pivoting by `Persistence.name` and `args`.
## MITRE ATT&CK Techniques
- [T1547](https://attack.mitre.org/techniques/T1547)
@@ -1,10 +1,12 @@
# Potential Exfiltration by process total egress bytes
# Egress Network Connections with Total Bytes Greater than Threshold
---
## Metadata
- **Author:** Elastic
- **Description:** Using aggregation and the ES|QL `SUM` function, this hunt identifies processes that performed egress connections with total bytes greater or equal to a defined maximum threshold. This may indicate exfiltration or long term command and control activity.
- **UUID:** `977d77f9-86e0-4df6-bdc7-aed87c048290`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -13,9 +15,9 @@
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 8 hour
| where host.os.family == "windows" and event.category == "network" and
event.action == "disconnect_received" and
| where @timestamp > now() - 8 hour
| where host.os.family == "windows" and event.category == "network" and
event.action == "disconnect_received" and
not CIDR_MATCH(destination.ip, "10.0.0.0/8", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.0.0/29", "192.0.0.8/32", "192.0.0.9/32", "192.0.0.10/32", "192.0.0.170/32", "192.0.0.171/32", "192.0.2.0/24", "192.31.196.0/24", "192.52.193.0/24", "192.168.0.0/16", "192.88.99.0/24", "224.0.0.0/4", "100.64.0.0/10", "192.175.48.0/24","198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep source.bytes, destination.address, process.executable, process.entity_id
| stats total_bytes_out = sum(source.bytes) by process.entity_id, destination.address, process.executable
@@ -25,10 +27,10 @@ from logs-endpoint.events.network-*
## Notes
- This hunt is not compatible with Sysmon event 3 (Network connection) and Windows security event 5156 as both don't log source.bytes.
- The use of host.os.family is to optimise the query and avoid timeout. You can duplicate the same query for other platforms (linux, macos etc.)
- This hunt is not compatible with Sysmon event 3 (Network connection) and Windows security event 5156 as both don't log `source.bytes`.
- The use of `host.os.family` is to optimise the query and avoid timeout. You can duplicate the same query for other platforms (linux, macos etc.)
- Based on limited testing it's recommended to set the query time window to 8 hours.
- Pivoting by process.entity_id will allow further investigation (parent process, hash, child processes, other network events etc.).
- Pivoting by `process.entity_id` will allow further investigation (parent process, hash, child processes, other network events etc.).
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
@@ -1,10 +1,12 @@
# Rundll32 execution aggregated by cmdline
# Rundll32 Execution Aggregated by Command Line
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt aggregate Rundll32 execution by normalized `process.command_line` and returns instances that are unique by frequency. Rundll32 is one of the most abused binaries to proxy execution of malicious commands and modules.
- **UUID:** `30f37cd2-c1d8-4554-bb4a-ed76de9e6857`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -14,8 +16,8 @@
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation", "created-process") and
process.name.caseless == "rundll32.exe" and
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation", "created-process") and
to_lower(process.name) == "rundll32.exe" and
not process.command_line rlike """.*(zzzzInvokeManagedCustomActionOutOfProc|GeneralTel.dll,RunInUserCxt|ShOpenVerbApplication|davclnt.dll,DavSetCookie|FileProtocolHandler|EDGEHTML.dll|FirewallControlPanel.dll,ShowNotificationDialog|printui.dll,PrintUIEntryDPIAware|Program Files|SHCreateLocalServerRunDll|ImageView_Fullscreen|StatusMonitorEntryPoint|Control_RunDLL|HotPlugSafeRemovalDriveNotification|AppxDeploymentClient.dll|acproxy.dll,PerformAutochkOperations|CapabilityAccessManagerDoStoreMaintenance|dfshim.dll|display.dll,ShowAdapterSettings|ForceProxyDetectionOnNextRun|PfSvWsSwapAssessmentTask|acmigration.dll,ApplyMigrationShims|LenovoBatteryGaugePackage.dll|-localserver|DriverStore|CnmDxPEntryPoint|DeferredDelete|DeviceProperties_RunDLL|AppxDeploymentClient.dll|spool\\DRIVERS|printui.dll,PrintUIEntry|DfdGetDefaultPolicyAndSMART|cryptext.dll,CryptExt|WininetPlugin.dll|ClearMyTracksByProcess|SusRunTask|OpenURL|CleanupTemporaryState).*"""
| keep process.parent.name, process.command_line, host.id
| eval cmdline = replace(process.command_line, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
@@ -27,7 +29,7 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-sys
## Notes
- Execution of DLLs from suspicious paths or with suspicious export function names or from suspicious parent should be further reviewed.
- Parents such as svchost, explorer.exe, wmiprvse.exe, winword.exe and others should be carefully reviewed.
- Parents such as svchost, `explorer.exe`, `wmiprvse.exe`, `winword.exe` and others should be carefully reviewed.
## MITRE ATT&CK Techniques
- [T1127](https://attack.mitre.org/techniques/T1127)
@@ -1,10 +1,12 @@
# Scheduled tasks creation by action via registry
# Scheduled tasks Creation by Action via Registry
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for scheduled tasks creation by action using registry events. Scheduled tasks actions are saved under the TaskCache registry key in base64 encoded blob. Malware often abuse LOLBins to proxy execution or run executables from unusual paths, you can add more patterns to the query.
- **UUID:** `344c0690-ebc3-4794-b123-272a5c09c57b`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
@@ -28,8 +30,7 @@ from logs-endpoint.events.registry-*
## Notes
- This hunt aggregate created scheduled tasks by action using registry events.
- Malware often abuse lolbins to proxy execution or run executables from unusual paths, you can add more patterns to the query.
- Malware often abuse LOLBins to proxy execution or run executables from unusual paths, you can add more patterns to the query.
## MITRE ATT&CK Techniques
- [T1053](https://attack.mitre.org/techniques/T1053)
@@ -1,10 +1,12 @@
# Scheduled tasks creation with low occurrence frequency
# Scheduled Tasks Creation for Unique Hosts by Task Command
---
## Metadata
- **Author:** Elastic
- **Description:** Using aggregation and strings extraction, this hunt identifies instances where a scheduled task is created and set to run a command unique to a specific host. This could be the result of persistence as a Windows Scheduled Task.
- **UUID:** `75804319-122c-4bdc-976e-d6355bca0d78`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -16,23 +18,23 @@ from logs-system.security-default-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.code == "4698" and event.action == "scheduled-task-created"
/* parsing unstructured data from winlog message to extract a scheduled task Exec command */
| grok message "(?<Command><Command>.+</Command>)" | eval Command = replace(Command, "(<Command>|</Command>)", "")
| grok message "(?<Command><Command>.+</Command>)" | eval Command = replace(Command, "(<Command>|</Command>)", "")
| where Command is not null
/* normalise task name by removing usersid and uuid string patterns */
| eval TaskName = replace(winlog.event_data.TaskName, """((-S-1-5-.*)|\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\})""", "")
| eval TaskName = replace(winlog.event_data.TaskName, """((-S-1-5-.*)|\{[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\})""", "")
/* normalise task name by removing random patterns in a file path */
| eval Task_Command = replace(Command, """(ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
/* normalize user home profile path */
| eval Task_Command = replace(Task_Command, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| where Task_Command like "?*" and not starts_with(Task_Command, "C:\\Program Files") and not starts_with(Task_Command, "\"C:\\Program Files")
| stats tasks_count = count(*), hosts_count = count_distinct(host.id) by Task_Command, TaskName
| stats tasks_count = count(*), hosts_count = count_distinct(host.id) by Task_Command, TaskName
| where hosts_count == 1
```
## Notes
- This hunt returns the aggregation of created tasks by task name, command to execute and number of hosts where this task is present.
- Close attention should be paid to suspicious paths like C:\Users\Public and C:\ProgramData\ as well as lolbins.
- Close attention should be paid to suspicious paths like `C:\Users\Public and C:\ProgramData\` as well as LOLBins.
## MITRE ATT&CK Techniques
- [T1053](https://attack.mitre.org/techniques/T1053)
@@ -1,10 +1,12 @@
# Suspicious Base64 Encoded PowerShell Command
# Suspicious Base64 Encoded Powershell Command
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies base64 encoded powershell commands in process start events and filters ones with suspicious keywords like downloaders and evasion related commands.
- **UUID:** `8bf800de-b3a2-4b36-9484-7d9dae2a1992`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -27,7 +29,8 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-sys
## Notes
- This hunt decode base64 obfuscated powershell commands in process start events and filter ones with suspicious keywords like downloaders and evasion related commands.
- This hunt can be expanded to include more evasion techniques and downloaders.
- Pivoting by `agent.id` can provide more context on the affected hosts.
## MITRE ATT&CK Techniques
- [T1059](https://attack.mitre.org/techniques/T1059)
@@ -1,10 +1,13 @@
# Suspicious DNS TXT Record lookups by process
# Suspicious DNS TXT Record Lookups by Process
---
## Metadata
- **Author:** Elastic
- **Description:** Leveraging aggregation by process executable entities, this hunt identifies identifies a high number of DNS TXT record queries from same process.
Adversaries may leverage DNS TXT queries to stage malicious content or exfiltrate data.
- **UUID:** `0b7343f7-2d16-43c7-af28-9d1f012b1093`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
@@ -12,20 +15,1583 @@
## Query
```sql
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where host.os.family == "windows" and event.category == "network" and
event.action in ("lookup_requested", "DNSEvent (DNS query)") and
(dns.question.type == "TXT" or dns.answers.type == "TXT") and process.executable != "C:\\Windows\\system32\\svchost.exe"
| keep process.executable, process.entity_id
| stats occurrences = count(*) by process.entity_id, process.executable
/* threshold can be adjusted to your env */
| where occurrences >= 50
f```
```sql
r```
```sql
o```
```sql
m```
```sql
```
```sql
l```
```sql
o```
```sql
g```
```sql
s```
```sql
-```
```sql
e```
```sql
n```
```sql
d```
```sql
p```
```sql
o```
```sql
i```
```sql
n```
```sql
t```
```sql
.```
```sql
e```
```sql
v```
```sql
e```
```sql
n```
```sql
t```
```sql
s```
```sql
.```
```sql
n```
```sql
e```
```sql
t```
```sql
w```
```sql
o```
```sql
r```
```sql
k```
```sql
-```
```sql
*```
```sql
,```
```sql
```
```sql
l```
```sql
o```
```sql
g```
```sql
s```
```sql
-```
```sql
w```
```sql
i```
```sql
n```
```sql
d```
```sql
o```
```sql
w```
```sql
s```
```sql
.```
```sql
s```
```sql
y```
```sql
s```
```sql
m```
```sql
o```
```sql
n```
```sql
_```
```sql
o```
```sql
p```
```sql
e```
```sql
r```
```sql
a```
```sql
t```
```sql
i```
```sql
o```
```sql
n```
```sql
a```
```sql
l```
```sql
-```
```sql
*```
```sql
```
```sql
|```
```sql
```
```sql
w```
```sql
h```
```sql
e```
```sql
r```
```sql
e```
```sql
```
```sql
h```
```sql
o```
```sql
s```
```sql
t```
```sql
.```
```sql
o```
```sql
s```
```sql
.```
```sql
f```
```sql
a```
```sql
m```
```sql
i```
```sql
l```
```sql
y```
```sql
```
```sql
=```
```sql
=```
```sql
```
```sql
"```
```sql
w```
```sql
i```
```sql
n```
```sql
d```
```sql
o```
```sql
w```
```sql
s```
```sql
"```
```sql
```
```sql
a```
```sql
n```
```sql
d```
```sql
```
```sql
e```
```sql
v```
```sql
e```
```sql
n```
```sql
t```
```sql
.```
```sql
c```
```sql
a```
```sql
t```
```sql
e```
```sql
g```
```sql
o```
```sql
r```
```sql
y```
```sql
```
```sql
=```
```sql
=```
```sql
```
```sql
"```
```sql
n```
```sql
e```
```sql
t```
```sql
w```
```sql
o```
```sql
r```
```sql
k```
```sql
"```
```sql
```
```sql
a```
```sql
n```
```sql
d```
```sql
```
```sql
```
```sql
```
```sql
e```
```sql
v```
```sql
e```
```sql
n```
```sql
t```
```sql
.```
```sql
a```
```sql
c```
```sql
t```
```sql
i```
```sql
o```
```sql
n```
```sql
```
```sql
i```
```sql
n```
```sql
```
```sql
(```
```sql
"```
```sql
l```
```sql
o```
```sql
o```
```sql
k```
```sql
u```
```sql
p```
```sql
_```
```sql
r```
```sql
e```
```sql
q```
```sql
u```
```sql
e```
```sql
s```
```sql
t```
```sql
e```
```sql
d```
```sql
"```
```sql
,```
```sql
```
```sql
"```
```sql
D```
```sql
N```
```sql
S```
```sql
E```
```sql
v```
```sql
e```
```sql
n```
```sql
t```
```sql
```
```sql
(```
```sql
D```
```sql
N```
```sql
S```
```sql
```
```sql
q```
```sql
u```
```sql
e```
```sql
r```
```sql
y```
```sql
)```
```sql
"```
```sql
)```
```sql
```
```sql
a```
```sql
n```
```sql
d```
```sql
```
```sql
```
```sql
```
```sql
(```
```sql
d```
```sql
n```
```sql
s```
```sql
.```
```sql
q```
```sql
u```
```sql
e```
```sql
s```
```sql
t```
```sql
i```
```sql
o```
```sql
n```
```sql
.```
```sql
t```
```sql
y```
```sql
p```
```sql
e```
```sql
```
```sql
=```
```sql
=```
```sql
```
```sql
"```
```sql
T```
```sql
X```
```sql
T```
```sql
"```
```sql
```
```sql
o```
```sql
r```
```sql
```
```sql
d```
```sql
n```
```sql
s```
```sql
.```
```sql
a```
```sql
n```
```sql
s```
```sql
w```
```sql
e```
```sql
r```
```sql
s```
```sql
.```
```sql
t```
```sql
y```
```sql
p```
```sql
e```
```sql
```
```sql
=```
```sql
=```
```sql
```
```sql
"```
```sql
T```
```sql
X```
```sql
T```
```sql
"```
```sql
)```
```sql
```
```sql
a```
```sql
n```
```sql
d```
```sql
```
```sql
p```
```sql
r```
```sql
o```
```sql
c```
```sql
e```
```sql
s```
```sql
s```
```sql
.```
```sql
e```
```sql
x```
```sql
e```
```sql
c```
```sql
u```
```sql
t```
```sql
a```
```sql
b```
```sql
l```
```sql
e```
```sql
```
```sql
!```
```sql
=```
```sql
```
```sql
"```
```sql
C```
```sql
:```
```sql
\```
```sql
\```
```sql
W```
```sql
i```
```sql
n```
```sql
d```
```sql
o```
```sql
w```
```sql
s```
```sql
\```
```sql
\```
```sql
s```
```sql
y```
```sql
s```
```sql
t```
```sql
e```
```sql
m```
```sql
3```
```sql
2```
```sql
\```
```sql
\```
```sql
s```
```sql
v```
```sql
c```
```sql
h```
```sql
o```
```sql
s```
```sql
t```
```sql
.```
```sql
e```
```sql
x```
```sql
e```
```sql
"```
```sql
```
```sql
|```
```sql
```
```sql
k```
```sql
e```
```sql
e```
```sql
p```
```sql
```
```sql
p```
```sql
r```
```sql
o```
```sql
c```
```sql
e```
```sql
s```
```sql
s```
```sql
.```
```sql
e```
```sql
x```
```sql
e```
```sql
c```
```sql
u```
```sql
t```
```sql
a```
```sql
b```
```sql
l```
```sql
e```
```sql
,```
```sql
```
```sql
```
```sql
p```
```sql
r```
```sql
o```
```sql
c```
```sql
e```
```sql
s```
```sql
s```
```sql
.```
```sql
e```
```sql
n```
```sql
t```
```sql
i```
```sql
t```
```sql
y```
```sql
_```
```sql
i```
```sql
d```
```sql
```
```sql
|```
```sql
```
```sql
s```
```sql
t```
```sql
a```
```sql
t```
```sql
s```
```sql
```
```sql
o```
```sql
c```
```sql
c```
```sql
u```
```sql
r```
```sql
r```
```sql
e```
```sql
n```
```sql
c```
```sql
e```
```sql
s```
```sql
```
```sql
=```
```sql
```
```sql
c```
```sql
o```
```sql
u```
```sql
n```
```sql
t```
```sql
(```
```sql
*```
```sql
)```
```sql
```
```sql
b```
```sql
y```
```sql
```
```sql
p```
```sql
r```
```sql
o```
```sql
c```
```sql
e```
```sql
s```
```sql
s```
```sql
.```
```sql
e```
```sql
n```
```sql
t```
```sql
i```
```sql
t```
```sql
y```
```sql
_```
```sql
i```
```sql
d```
```sql
,```
```sql
```
```sql
p```
```sql
r```
```sql
o```
```sql
c```
```sql
e```
```sql
s```
```sql
s```
```sql
.```
```sql
e```
```sql
x```
```sql
e```
```sql
c```
```sql
u```
```sql
t```
```sql
a```
```sql
b```
```sql
l```
```sql
e```
```sql
```
```sql
```
```sql
/```
```sql
*```
```sql
```
```sql
t```
```sql
h```
```sql
r```
```sql
e```
```sql
s```
```sql
h```
```sql
o```
```sql
l```
```sql
d```
```sql
```
```sql
c```
```sql
a```
```sql
n```
```sql
```
```sql
b```
```sql
e```
```sql
```
```sql
a```
```sql
d```
```sql
j```
```sql
u```
```sql
s```
```sql
t```
```sql
e```
```sql
d```
```sql
```
```sql
t```
```sql
o```
```sql
```
```sql
y```
```sql
o```
```sql
u```
```sql
r```
```sql
```
```sql
e```
```sql
n```
```sql
v```
```sql
```
```sql
*```
```sql
/```
```sql
```
```sql
|```
```sql
```
```sql
w```
```sql
h```
```sql
e```
```sql
r```
```sql
e```
```sql
```
```sql
o```
```sql
c```
```sql
c```
```sql
u```
```sql
r```
```sql
r```
```sql
e```
```sql
n```
```sql
c```
```sql
e```
```sql
s```
```sql
```
```sql
>```
```sql
=```
```sql
```
```sql
5```
```sql
0```
```sql
```
## Notes
- This hunt returns a list of processes unique pids and executable path that performs a high number of DNS TXT lookups.
- Pivoting by process.entity_id will allow further investigation (parent process, hash, child processes, other network events etc.).
- This hunt returns a list of processes unique pids and executable paths that performs a high number of DNS TXT lookups.
- Pivoting by `process.entity_id` will allow further investigation (parent process, hash, child processes, other network events etc.).
## MITRE ATT&CK Techniques
- [T1071](https://attack.mitre.org/techniques/T1071)
@@ -0,0 +1,77 @@
# Unique Windows Services Creation by Service File Name
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt aggregates created Windows services by service file name and distribution limited to unique hosts. Using the ES|QL `Replace` command we can also further remove random patterns to reduce results to interesting events. More investigation can be conducted on instance that looks suspicious based on service file path, names and LOLBins.
- **UUID:** `ebf79207-16dc-44f8-b10c-317d4a034bad`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.registry-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action in ("modification", "RegistryEvent (Value Set)") and
registry.value in ("ServiceDLL", "ImagePath") and starts_with(registry.path, "HKLM\\SYSTEM\\") and
process.executable != "C:\\Windows\\System32\\services.exe"
| eval process_path = replace(process.executable, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats hosts = count_distinct(host.id), occurrences = count(*) by process_path
/* unique process.executable found in one agent */
| where hosts == 1 and occurrences == 1
```
```sql
from logs-endpoint.events.registry-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action in ("modification", "RegistryEvent (Value Set)") and
registry.value in ("ServiceDLL", "ImagePath") and starts_with(registry.path, "HKLM\\SYSTEM\\") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
/* unique ServiceFileName observed in 1 host*/
| where hosts == 1 and cc == 1
```
```sql
from logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "configuration" and event.code == "4697" and
not winlog.event_data.ServiceFileName rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(winlog.event_data.ServiceFileName, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
```sql
from logs-system.system-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.code == "7045" and
not winlog.event_data.ImagePath rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
## Notes
- This hunt also identifies services registry modification by unusual process based on number of hosts and occurrences history.
- Windows event IDs 4697 and 7045 are used to identify service creation and modification.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Unique Windows Services Creation by ServiceFileName - Elastic Defend Registry - Sysmon
---
## Metadata
- **Author:** Elastic
- **UUID:** `ebf79207-16dc-44f8-b10c-317d4a034bad`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.registry-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action in ("modification", "RegistryEvent (Value Set)") and
registry.value in ("ServiceDLL", "ImagePath") and starts_with(registry.path, "HKLM\\SYSTEM\\") and
process.executable != "C:\\Windows\\System32\\services.exe"
| eval process_path = replace(process.executable, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats hosts = count_distinct(host.id), occurrences = count(*) by process_path
/* unique process.executable found in one agent */
| where hosts == 1 and occurrences == 1
```
## Notes
- This hunt identify services registry modification by unusual process based on number of hosts and occurrences history.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,38 +0,0 @@
# Unique Windows Services Creation by ServiceFileName - Elastic Defend - Sysmon Registry
---
## Metadata
- **Author:** Elastic
- **UUID:** `688dc79d-f52a-49ad-829d-89343e68b0f7`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
## Query
```sql
from logs-endpoint.events.registry-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "registry" and event.action in ("modification", "RegistryEvent (Value Set)") and
registry.value in ("ServiceDLL", "ImagePath") and starts_with(registry.path, "HKLM\\SYSTEM\\") and
not registry.data.strings rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(registry.data.strings, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
/* unique ServiceFileName observed in 1 host*/
| where hosts == 1 and cc == 1
```
## Notes
- This hunt aggregates created Windows services by service file name and distribution limited to unique hosts. Using the Replace command we can also further remove random pattern to reduce results to interesting events. More investigation can be conducted on instance that looks suspicious based on service file path, names and lolbins.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Unique Windows Services Creation by ServiceFileName - Windows Security 4697
---
## Metadata
- **Author:** Elastic
- **UUID:** `b6b14385-4ed2-44af-98fe-dad5b1581174`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "configuration" and event.code == "4697" and
not winlog.event_data.ServiceFileName rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(winlog.event_data.ServiceFileName, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
## Notes
- This hunt aggregates created Windows services by service file name and distribution limited to unique hosts. Using the Replace command we can also further remove random pattern to reduce results to interesting events. More investigation can be conducted on instance that looks suspicious based on service file path, names and lolbins.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,36 +0,0 @@
# Unique Windows Services Creation by ServiceFileName - Windows Security 7045
---
## Metadata
- **Author:** Elastic
- **UUID:** `1749a45b-98f0-4b27-8c2f-2287230e52b7`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
## Query
```sql
from logs-system.system-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.code == "7045" and
not winlog.event_data.ImagePath rlike """(.{1,2}[c-fC-F]:\\Program Files.+)|([c-fC-F]:\\Program Files.+)|(.*\\System32\\DriverStore\\FileRepository\\.+)"""
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
```
## Notes
- This hunt aggregates created Windows services by service file name and distribution limited to unique hosts. Using the Replace command we can also further remove random pattern to reduce results to interesting events. More investigation can be conducted on instance that looks suspicious based on service file path, names and lolbins.
## MITRE ATT&CK Techniques
- [T1543](https://attack.mitre.org/techniques/T1543)
- [T1543.003](https://attack.mitre.org/techniques/T1543/003)
## License
- `Elastic License v2`
@@ -1,10 +1,12 @@
# Windows Command and Scripting Interpreter from unusual parent
# Windows Command and Scripting Interpreter from Unusual Parent Process
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt looks for unusual Microsoft native processes spawning `cmd.exe`, `powershell.exe` or `conhost.exe` and limited to a unique host. This could be normal rare behavior as well as an interactive shell activity from an injected parent process to execute system commands.
- **UUID:** `de929347-c04a-4a94-8be2-cbe87b25bb25`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows), [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -14,9 +16,9 @@
```sql
from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation", "created-process") and
process.name.caseless in ("cmd.exe", "powershell.exe", "conhost.exe") and
(starts_with(process.parent.executable.caseless, "c:\\windows\\system32") or starts_with(process.parent.executable.caseless, "c:\\windows\\syswow64"))
| where host.os.family == "windows" and event.category == "process" and event.action in ("start", "Process creation", "created-process") and
to_lower(process.name) in ("cmd.exe", "powershell.exe", "conhost.exe") and
(starts_with(to_lower(process.parent.executable), "c:\\windows\\system32") or starts_with(to_lower(process.parent.executable), "c:\\windows\\syswow64"))
| keep process.name, process.parent.name, host.id
| stats hosts = count_distinct(host.id), cc = count(*) by process.parent.name
| where cc <= 10 and hosts == 1
@@ -24,8 +26,8 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-sys
## Notes
- Pivoting can be done via process.parent.name.
- Certain Microsoft binaries like LSASS, winlogon, spoolsv and others should never spawn cmd.exe powershell.exe or conhost.exe, if so it's highly likely malicious.
- Further pivoting can be done via `process.parent.name`.
- Certain Microsoft binaries like LSASS, winlogon, spoolsv and others should never spawn `cmd.exe`, `powershell.exe` or `conhost.exe`, if so it's highly likely malicious.
## MITRE ATT&CK Techniques
- [T1059](https://attack.mitre.org/techniques/T1059)
@@ -1,10 +1,12 @@
# Windows logon activity by source IP
# Windows Logon Activity by Source IP
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt returns a summary of network logon activity by `source.ip` using Windows event IDs 4624 and 4625. The higher the number of failures, low success and multiple accounts the more suspicious the behavior is.
- **UUID:** `7bdea198-eb09-4eca-ae3d-bfc3b52c89a9`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
@@ -14,10 +16,10 @@
```sql
from logs-system.security-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and
event.category == "authentication" and event.action in ("logon-failed", "logged-in") and winlog.logon.type == "Network" and
source.ip is not null and
/* noisy failure status codes often associated to authentication misconfiguration */
| where host.os.family == "windows" and
event.category == "authentication" and event.action in ("logon-failed", "logged-in") and winlog.logon.type == "Network" and
source.ip is not null and
/* noisy failure status codes often associated to authentication misconfiguration */
not (event.action == "logon-failed" and winlog.event_data.Status in ("0xC000015B", "0XC000005E", "0XC0000133", "0XC0000192"))
| eval failed = case(event.action == "logon-failed", source.ip, null), success = case(event.action == "logged-in", source.ip, null)
| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(winlog.event_data.TargetUserName) by source.ip
@@ -27,8 +29,7 @@ from logs-system.security-*
## Notes
- This hunt returns the total number of failed logons, successful ones and the number of unique account names grouped by source.ip.
- Pay close attention to IP addresses source of a high number of failures associated with low success attempts and high number of used accounts.
- Pay close attention to IP address sources with a high number of failed connections associated with low success attempts and high number of user accounts.
## MITRE ATT&CK Techniques
- [T1110](https://attack.mitre.org/techniques/T1110)
@@ -1,22 +1,23 @@
[hunt]
author = "Elastic"
description = "This hunt attempts to identify remote process injection by aggregating Sysmon `CreateRemoteThread` events by source process and returns the ones that we observed in only one unique host."
integration = ["windows"]
uuid = "0545f23f-84a7-4b88-9b5b-b8cfcfdc9276"
name = "CreateRemoteThread by source process with low occurrence"
name = "Low Occurrence Rate of CreateRemoteThread by Source Process"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt aggregates Sysmon CreateRemoteThread events by source process and returns the ones that we observed in only one unique host. This may indicate remote process injection.",
"Adding winlog.event_data.TargetImage to the group by clause can be beneficial but may introduce more legit hits.",
"Adding `winlog.event_data.TargetImage` to the aggregation clause can be beneficial but may introduce more false-positives.",
]
mitre = ["T1055"]
query = '''
from logs-windows.sysmon_operational-*
query = [
'''
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "CreateRemoteThread"
| eval source_process = replace(process.executable, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by source_process
/* unique source and target processes combined and observed in 1 host */
| where hosts == 1 and cc == 1
'''
'''
]
@@ -0,0 +1,50 @@
[hunt]
author = "Elastic"
description = "This hunt identifies when a process loads a DLL normally located in `System32` or `SysWOW64` folders from an unusual path. Adversaries may execute their own malicious payloads by side-loading malicious DLLs. The host count also should help exclude false-positives by looking at low occurrences when this abnormal behavior is limited to unique agents."
integration = ["endpoint", "windows"]
uuid = "87c97865-fdaa-48b2-bfa6-67bed7cf56ef"
name = "DLL Hijack via Masquerading as Microsoft Native Libraries"
language = "ES|QL"
license = "Elastic License v2"
mitre = ["T1574", "T1574.001"]
notes = [
"This hunt has two optional queries, one for Elastic Defend data and another for Sysmon data.",
"This hunt requires the creation of an [enrichment policy](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-enrich-data.html) to use with the ES|QL (ENRICH command).",
"The `dll.hash.sha256` field can be used to pivot and further investigate the DLL origin and purpose.",
"Paths like `C:\\Users\\Public and C:\\ProgramData\\` are often observed in malware employing DLL side-loading.",
]
query = [
'''
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and
not dll.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep dll.name, dll.path, dll.hash.sha256, process.executable, host.id
/* steps how to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c */
| ENRICH libs-policy-defend
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(dll.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(dll.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by dll.name, dll_path, process_path, dll.hash.sha256
| sort host_count asc
''',
'''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep file.name, file.path, file.hash.sha256, process.executable, host.id
/* steps to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c - just replace dll by file */
| ENRICH libs-policy-sysmon
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(file.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(file.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by file.name, dll_path, process_path, file.hash.sha256
| sort host_count asc
'''
]
@@ -1,30 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "87c97865-fdaa-48b2-bfa6-67bed7cf56ef"
name = "Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Elastic Defend"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt require the creation of an enrichment policy to use with the ES|QL (ENRICH command).",
"The `dll.hash.sha256` field can be used to pivot and further investigate the DLL origin and purpose.",
"Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.",
]
mitre = ["T1574", "T1574.001"]
query = '''
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and
not dll.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep dll.name, dll.path, dll.hash.sha256, process.executable, host.id
/* steps how to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c */
| ENRICH libs-policy-defend
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(dll.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(dll.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by dll.name, dll_path, process_path, dll.hash.sha256
| sort host_count asc
'''
@@ -1,31 +0,0 @@
[hunt]
author = "Elastic"
integration = ["windows"]
uuid = "68314691-1460-4ac5-ae0d-6b3514e43254"
name = "Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt require the creation of an enrichment policy to use with the ES|QL (ENRICH command).",
"Using dll.hash.sha256 for Elastic Defend or file.hash.sha256 for Sysmon you can pivot to further investigate the DLL origin and purpose.",
"Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.",
"Process code signature information is not captured in Sysmon Image Load Events (not present in the ES|QL hunt).",
]
mitre = [ "T1574", "T1574.001",]
query = '''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| keep file.name, file.path, file.hash.sha256, process.executable, host.id
/* steps to create DL enrichment policy https://gist.github.com/Samirbous/9f9c3237a0ada745e71cc2ba3425311c - just replace dll by file */
| ENRICH libs-policy-sysmon
/* if the DLL is normally located is system32 or syswow64 folders, native tag will be equal to yes */
| where native == "yes" and not starts_with(file.path, "C:\\Windows\\assembly\\NativeImages")
/* normalize paths by removing random patterns */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""),
dll_path = replace(file.path, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats host_count = count_distinct(host.id) by file.name, dll_path, process_path, file.hash.sha256
| sort host_count asc
'''
@@ -1,11 +1,13 @@
[hunt]
author = "Elastic"
description = "This hunt detects processes named as legit Microsoft native binaries located in the system32 folder. Adversaries may attempt to manipulate features of their artifacts to make them appear legitimate or benign to users and/or security tools. Masquerading occurs when the name or location of an object, legitimate or malicious, is manipulated or abused for the sake of evading defenses and observation. "
integration = ["endpoint"]
uuid = "93a72542-a1f7-4407-9175-8f066343db60"
name = "Detect masquerading attempts as native Windows binaries"
mitre = ["T1036"]
name = "Masquerading Attempts as Native Windows Binaries"
language = "ES|QL"
license = "Elastic License v2"
query = '''
query = ['''
from logs-endpoint.events.process-*
| where @timestamp > NOW() - 7 day
| where event.type == "start" and event.action == "start" and host.os.name == "Windows" and not starts_with(process.executable, "C:\\Program Files\\WindowsApps\\") and not starts_with(process.executable, "C:\\Windows\\System32\\DriverStore\\") and process.name != "setup.exe"
@@ -17,10 +19,10 @@ from logs-endpoint.events.process-*
| stats count_system_bin = count(system_bin), count_non_system_bin = count(non_system_bin) by process.name.caseless, host.id
/* filter where the same process.name is present in both system_bin and non_system_bin */
| where count_system_bin >= 1 and count_non_system_bin >= 1
'''
''']
notes = [
"Output of the query is the process.name and host.id, you can pivot by host.id and process.name(non Microsoft signed) to find the specific suspicious instances.",
"Potential false positives include processes with missing code signature details due to enrichment bugs.",
"Output of the query is the `process.name` and `host.id` where you can pivot by `host.id` and `process.name` (non Microsoft signed) to find the specific suspicious instances.",
"Potential false-positives include processes with missing code signature details due to enrichment bugs.",
"The queried index must capture process start events with code signature information (e.g. Windows event 4688 is not supported).",
]
mitre = ["T1036"]
@@ -0,0 +1,45 @@
[hunt]
author = "Elastic"
description = """This hunt identifies instances where a signed Windows process attempts to load an unsigned DLL from the same process folder. Matches are limited to a unique host with low library load occurrence. Adversaries may execute their own malicious payloads by side-loading malicious DLLs."""
integration = ["endpoint", "windows"]
uuid = "bcdb7c29-1312-4974-8f2e-10ddeb09cf5c"
name = "Rare DLL Side-Loading by Occurrence"
language = "ES|QL"
license = "Elastic License v2"
query = [
'''
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and dll.Ext.relative_file_creation_time <= 86400
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and process.name != dll.name
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, dll.name, process.name, dll.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10 | keep total_count, host_count, dll_folder, dll.name, process.name, dll.hash.sha256
''',
'''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and file.name != process.name
/* paths normalization by removing random patterns */
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, file.name, process.name, file.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10
| keep total_count, host_count, dll_folder, file.name, process.name, file.hash.sha256
'''
]
notes = [
'This hunt has two optional queries, one for Elastic Defend data and another for Sysmon data.',
'Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.',
'Paths like `C:\\Users\\Public` and `C:\\ProgramData\\` are often observed in malware employing DLL side-loading.',
'Elastic Defned DLL Events include `dll.Ext.relative_file_creation_time` which help us limit the hunt to recently dropped DLLs.'
]
mitre = ["T1574", "T1574.002"]
@@ -1,26 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "bcdb7c29-1312-4974-8f2e-10ddeb09cf5c"
name = "Detect Rare DLL SideLoad by Occurrence - Elastic Defend"
language = "ES|QL"
license = "Elastic License v2"
query = '''
from logs-endpoint.events.library-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.action == "load" and process.code_signature.status == "trusted" and dll.code_signature.status != "trusted" and dll.Ext.relative_file_creation_time <= 86400
| eval dll_folder = substring(dll.path, 1, length(dll.path) - (length(dll.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and process.name != dll.name
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, dll.name, process.name, dll.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10 | keep total_count, host_count, dll_folder, dll.name, process.name, dll.hash.sha256
'''
notes = [
'Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.',
'Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.',
'Elastic Defned DLL Events include dll.Ext.relative_file_creation_time which help us limit the hunt to recently dropped DLLs.'
]
mitre = ["T1574", "T1574.002"]
@@ -1,28 +0,0 @@
[hunt]
author = "Elastic"
integration = ["windows"]
uuid = "0df1e142-7d70-4112-be8d-6c60ac812883"
name = "Detect Rare DLL SideLoad by Occurrence - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
query = '''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "process" and event.action == "Image loaded" and file.code_signature.status != "Valid" and
not file.path rlike """[c-fC-F]:\\(Windows|windows|WINDOWS)\\(System32|SysWOW64|system32|syswow64)\\[a-zA-Z0-9_]+.dll"""
| eval dll_folder = substring(file.path, 1, length(file.path) - (length(file.name) + 1))
| eval process_folder = substring(process.executable, 1, length(process.executable) - (length(process.name) + 1))
| where process_folder is not null and dll_folder is not null and process_folder == dll_folder and file.name != process.name
/* paths normalization by removing random patterns */
| eval dll_folder = replace(dll_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), process_folder = replace(process_folder, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", ""), dll_folder = replace(dll_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\"), process_folder = replace(process_folder, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$]+\\""", "C:\\\\users\\\\user\\\\")
| stats host_count = count_distinct(host.id), total_count = count(*) by dll_folder, file.name, process.name, file.hash.sha256
/* total_count can be adjusted to higher or lower values depending on env */
| where host_count == 1 and total_count <= 10
| keep total_count, host_count, dll_folder, file.name, process.name, file.hash.sha256
'''
notes = [
'Based on the returned results you can further investigate suspicious DLLs by sha256 and library path.',
'Paths like C:\\Users\\Public and C:\\ProgramData\\ are often observed in malware employing DLL side-loading.',
'Elastic Defned DLL Events include dll.Ext.relative_file_creation_time which help us limit the hunt to recently dropped DLLs.'
]
mitre = ["T1574", "T1574.002"]
@@ -0,0 +1,40 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies instances where a process attempts to open the Local Security Authority Subsystem Service (LSASS) memory and where the number of occurences is limited to one unique agent and a low number of attempts. This may indicate either a rare legitimate condition or a malicious process attempting to obtain credentials or inject code into the LSASS.
"""
integration = ["endpoint", "windows"]
uuid = "3978e183-0b70-4e1c-8c40-24e367f6db5a"
name = "Rare LSASS Process Access Attempts"
language = "ES|QL"
license = "Elastic License v2"
query = [
'''
from logs-endpoint.events.api*
| where @timestamp > NOW() - 7 day
| where event.category == "api" and host.os.family == "windows" and process.Ext.api.name in ("OpenProcess", "OpenThread", "ReadProcessMemory") and
Target.process.name == "lsass.exe"
| keep process.executable.caseless, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process = replace(process.executable.caseless, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats occurences = count(process), agents = count_distinct(host.id) by process
| where agents == 1 and occurences <= 10
''',
'''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where event.category == "process" and host.os.family == "windows" and event.action == "ProcessAccess" and
winlog.event_data.TargetImage in ("C:\\Windows\\system32\\lsass.exe", "c:\\Windows\\system32\\lsass.exe", "c:\\Windows\\System32\\lsass.exe")
| keep process.executable, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats occurences = count(process_path), agents = count_distinct(host.id) by process_path
| where agents == 1 and occurences <= 10
'''
]
notes = [
"Based on the process.executable and process.name you can pivot and investigate further for the matching instances.",
"Potential false-positives include rare legitimate conditions that may trigger this behavior due to third-party software or LSASS crashing.",
]
mitre = ["T1003", "T1003.001"]
@@ -1,23 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "3978e183-0b70-4e1c-8c40-24e367f6db5a"
name = "Detect Rare LSASS Process Access Attempts - Elastic Defend"
language = "ES|QL"
license = "Elastic License v2"
query = '''
from logs-endpoint.events.api*
| where @timestamp > NOW() - 7 day
| where event.category == "api" and host.os.family == "windows" and process.Ext.api.name in ("OpenProcess", "OpenThread", "ReadProcessMemory") and
Target.process.name == "lsass.exe"
| keep process.executable.caseless, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process = replace(process.executable.caseless, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| stats occurences = count(process), agents = count_distinct(host.id) by process
| where agents == 1 and occurences <= 10
'''
notes = [
"Based on the process.executable and process.name you can pivot and investigate further the matching instances.",
"Potential false positives include rare legit condition that may trigger this behavior due to third party software or Lsass crash.",
]
mitre = ["T1003", "T1003.001"]
@@ -1,24 +0,0 @@
[hunt]
author = "Elastic"
integration = ["windows"]
uuid = "3978e183-0b70-4e1c-8c40-24e367f6db5a"
name = "Detect Rare LSASS Process Access Attempts - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
query = '''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where event.category == "process" and host.os.family == "windows" and event.action == "ProcessAccess" and
winlog.event_data.TargetImage in ("C:\\Windows\\system32\\lsass.exe", "c:\\Windows\\system32\\lsass.exe", "c:\\Windows\\System32\\lsass.exe")
| keep process.executable, host.id
/* normalize process paths to reduce known random patterns in process.executable */
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
| stats occurences = count(process_path), agents = count_distinct(host.id) by process_path
| where agents == 1 and occurences <= 10
'''
notes = [
"Based on the process.executable and process.name you can pivot and investigate further the matching instances.",
"Potential false positives include rare legit condition that may trigger this behavior due to third party software or Lsass crash.",
]
mitre = ["T1003", "T1003.001"]
@@ -1,22 +1,26 @@
[hunt]
author = "Elastic"
description = """
This hunt looks for DNS queries performed by commonly abused Microsoft binaries that perform remote file transfer or binary proxy execution. Aggregations for the number of occurrences is limited to one host to reduce the number of potentially legitimate hits.
"""
integration = ["endpoint", "windows"]
uuid = "ebf8eb13-c98a-4d2c-8bdb-3f72a3a3961b"
name = "Doamin Names queries via Lolbins and with low occurence frequency"
name = "DNS Queries via LOLBins with Low Occurence Frequency"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"Utilities like curl and SSL verification web-servvices are noisy, while others are rare like scripting utilities and are worth further investigation.",
"Connection to legit domains like github, discord, telegram and many other legit web-services by lolbins is still suspicious and require further investigation.",
"Utilities like curl and SSL verification for web services are noisy, while others are rare such as scripting utilities and are worth further investigation.",
"Connection to legit domains like Github, Discord, Telegram and many other legit web services by LOLBins is still suspicious and require further investigation.",
]
mitre = [ "T1071",]
query = '''
mitre = [ "T1071"]
query = [
'''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and event.category == "network" and
event.action in ("lookup_requested", "DNSEvent (DNS query)") and
process.name in ("powershell.exe", "rundll32.exe", "certutil.exe", "curl.exe", "wget.exe", "CertReq.exe", "bitsadmin.exe", "mshta.exe", "pwsh.exe", "wmic.exe", "wscript.exe", "cscript.exe", "msbuild.exe", "regsvr32.exe", "MSBuild.exe", "InstallUtil.exe", "RegAsm.exe", "RegSvcs.exe", "msxsl.exe", "CONTROL.EXE", "Microsoft.Workflow.Compiler.exe", "msiexec.exe") and dns.question.name rlike """.+\.[a-z-A-Z]{2,3}"""
| where @timestamp > now() - 7 day and host.os.family == "windows" and event.category == "network" and
event.action in ("lookup_requested", "DNSEvent (DNS query)") and
process.name in ("powershell.exe", "rundll32.exe", "certutil.exe", "curl.exe", "wget.exe", "CertReq.exe", "bitsadmin.exe", "mshta.exe", "pwsh.exe", "wmic.exe", "wscript.exe", "cscript.exe", "msbuild.exe", "regsvr32.exe", "MSBuild.exe", "InstallUtil.exe", "RegAsm.exe", "RegSvcs.exe", "msxsl.exe", "CONTROL.EXE", "Microsoft.Workflow.Compiler.exe", "msiexec.exe") and dns.question.name rlike """.+\.[a-z-A-Z]{2,3}"""
| keep process.name, dns.question.name, host.id
| stats occurrences = count(*), hosts = count_distinct(host.id) by process.name, dns.question.name
| where hosts == 1
'''
''',
]
@@ -0,0 +1,45 @@
[hunt]
author = "Elastic"
description = """
This hunt helps identify drivers loaded once on a unique host and with a unique hash over a 15 day period of time. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.
"""
integration = ["endpoint", "windows", "system"]
uuid = "99818ad6-c242-4da7-a41a-df64fe7314d6"
name = "Low Occurrence of Drivers Loaded on Unique Hosts"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt has three optional queries, one for Elastic Defend data, another for Sysmon data and the last one for Windows 7045 events.",
"Further investigation can be done pivoting by `dll.pe.imphash` or `dll.name.`",
"`dll.Ext.relative_file_creation_time` is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).",
"Aggregation can also be done by `dll.hash.sha256` / `file.hash.sha256` but will return more results.",
"Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).",
]
mitre = [ "T1068"]
query = [
'''
from logs-endpoint.events.library-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver" and event.action == "load" and dll.Ext.relative_file_creation_time <= 900
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(dll.hash.sha256) by dll.name, dll.pe.imphash
| where host_count == 1 and total_count == 1 and hash_count == 1
''',
'''
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver"
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(file.hash.sha256) by file.name
| where host_count == 1 and total_count == 1 and hash_count == 1
''',
'''
from logs-system.system-*
| where @timestamp > now() - 15day
| where host.os.family == "windows" and event.code == "7045" and
winlog.event_data.ServiceType == "kernel mode driver"
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
'''
]
@@ -1,22 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "99818ad6-c242-4da7-a41a-df64fe7314d6"
name = "Drivers Load with low occurrence frequency - Elastic Defend"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.",
"dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).",
"aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.",
"Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).",
]
mitre = [ "T1068",]
query = '''
from logs-endpoint.events.library-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver" and event.action == "load" and dll.Ext.relative_file_creation_time <= 900
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(dll.hash.sha256) by dll.name, dll.pe.imphash
| where host_count == 1 and total_count == 1 and hash_count == 1
'''
@@ -1,22 +0,0 @@
[hunt]
author = "Elastic"
integration = ["windows"]
uuid = "6bb90aba-af6b-4128-a9b2-160e164a15ff"
name = "Drivers Load with low occurrence frequency - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.",
"dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).",
"aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.",
"Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).",
]
mitre = [ "T1068",]
query = '''
from logs-windows.sysmon_operational-*
| where @timestamp > now() - 15 day
| where host.os.family == "windows" and event.category == "driver"
| stats host_count = count_distinct(host.id), total_count = count(*), hash_count = count_distinct(file.hash.sha256) by file.name
| where host_count == 1 and total_count == 1 and hash_count == 1
'''
@@ -1,26 +0,0 @@
[hunt]
author = "Elastic"
integration = ["system"]
uuid = "bc4848ce-5323-42b4-a559-3333c11ca938"
name = "Drivers Load with low occurrence frequency - Windows 7045"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt helps identify drivers loaded once, on a unique host and with a unique hash over a 15 days period of time. Further investigation can be done pivoting by dll.pe.imphash or dll.name. Advanced adversaries may leverage legit vulnerable driver to tamper with existing defences or execute code in Kernel mode.",
"dll.Ext.relative_file_creation_time is used in the first query to limit the result to recently dropped drivers (populated in Elastic Defend).",
"aggregation can be done also by dll.hash.sha256 / file.hash.sha256 but will return more results.",
"Bring Your Own Vulnerable Driver (BYOVD) are all signed and not malicious, further investigation should be done to check the surrounding events (service creation, process that dropped the driver etc.).",
]
mitre = [ "T1068",]
query = '''
from logs-system.system-*
| where @timestamp > now() - 15day
| where host.os.family == "windows" and event.code == "7045" and
winlog.event_data.ServiceType == "kernel mode driver"
| eval ServiceFileName = replace(winlog.event_data.ImagePath, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
| eval ServiceFileName = replace(ServiceFileName, """.inf_amd[a-z0-9]{5,}\\""", "_replaced_")
| eval ServiceFileName = replace(ServiceFileName, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9ñ\.\-\_\$~ ]+\\""", "C:\\\\users\\\\user\\\\")
| stats cc = count(*), hosts = count_distinct(host.id) by ServiceFileName
| where hosts == 1 and cc == 1
'''
@@ -1,24 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint", "windows"]
uuid = "fe01a8a5-6367-4c4c-a57b-be513ab80e42"
name = "Excessive RDP Network Activity by Source Host and User- Elastic Defend - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt looks for high number of Remote Desktop connections from same host and user.name to more than a defined threshold of unique destination Ip addresses. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol.",
"Further investigation can done pivoting by host.id and user name.",
"Depending on normal SysAdmin RDP activity the 10 threshold can be adjusted to reduce normal noisy activity.",
]
mitre = [ "T1021", "T1021.001",]
query = '''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where count_unique_dst >= 10
'''
@@ -0,0 +1,37 @@
[hunt]
author = "Elastic"
description = """
This hunt looks for a high occurrence of remote desktop connections from the same host and user. The number of unique destination IP addresses is compared to a defined threshold. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol (RDP).
"""
integration = ["endpoint", "windows"]
uuid = "fe01a8a5-6367-4c4c-a57b-be513ab80e42"
name = "Excessive RDP Network Activity by Host and User"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"Further investigation can done pivoting by `host.id` and `user.name`.",
"Depending on normal SysAdmin RDP activity, the threshold of 10 can be adjusted to reduce normal noisy activity.",
"The second query uses Windows Security log event ID 4624 to summarize numbers of RDP connections by `source.ip` and `user.name` and duration."
]
mitre = [ "T1021", "T1021.001"]
query = [
'''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
/* threshold set to 10 but can be adjusted to reduce normal baseline in your env */
| where count_unique_dst >= 10
''',
'''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and process.name == "svchost.exe" and network.direction == "ingress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| stats agents = count_distinct(host.id) by source.ip
| where agents >= 10
'''
]
@@ -1,21 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint", "windows"]
uuid = "6ff3a518-3bf4-4e7d-9a66-2ef7aaa68cfc"
name = "Excessive RDP Network Activity by Source Host - Elastic Defend - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt looks for high number of Remote Desktop connections from same host and user.name to more than a defined threshold of unique destination Ip addresses. This could be a sign of discovery or lateral movement via the Remote Desktop Protocol.",
"Further investigation can done pivoting by host.id and user name.",
"Depending on normal SysAdmin RDP activity the 10 threshold can be adjusted to reduce normal noisy activity.",]
mitre = [ "T1021", "T1021.001",]
query = '''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day
| where host.os.family == "windows" and event.category == "network" and process.name == "svchost.exe" and network.direction == "ingress" and
network.transport == "tcp"and destination.port == 3389 and source.port >= 49152
| stats agents = count_distinct(host.id) by source.ip
| where agents >= 10
'''
@@ -1,23 +1,26 @@
[hunt]
author = "Elastic"
description = """
This hunt looks for a high occurrence of SMB connections from the same process by unique destination IP addresses. The number of unique destination IP addresses is compared to a defined threshold. This could be a sign of SMB scanning or lateral movement via remote services that depend on the SMB protocol.
"""
integration = ["endpoint", "windows"]
uuid = "6949135b-76d7-47a3-ae95-ef482508fb7c"
name = "Excessive SMB Network Activity by process Id"
name = "Excessive SMB Network Activity by Process ID"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt looks for high number of SMB connections from same process to more than a defined threshold of unique destination Ip addresses. This could be a sign of SMB scanning or some lateral movement via remote services that depend on SMB protocol.",
"Further investigation can done pivoting by process.entity_id and host.id.",
"Maximum number of unique destination.ip by process can be adjusted to your environment to reduce normal noisy hosts by Id.",]
"Further investigation can done pivoting by `process.entity_id` and `host.id.`",
"Maximum number of unique `destination.ip` by process can be adjusted to your environment to reduce normal noisy hosts by process ID.",]
mitre = [ "T1021", "T1021.002",]
query = '''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
query = [
'''
from logs-endpoint.events.network-*, logs-windows.sysmon_operational-*
| where @timestamp > now() - 7 day and
host.os.family == "windows" and event.category == "network" and network.direction == "egress" and
network.transport == "tcp"and destination.port == 445 and source.port >= 49152 and process.pid == 4
| keep destination.ip, process.entity_id, host.id
| stats count_unique_dst = count_distinct(destination.ip) by process.entity_id, host.id
/* threshold set to 20 but can be adjusted to reduce normal baseline in your env */
| where count_unique_dst >= 20
'''
'''
]
@@ -0,0 +1,39 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies executable file creation by an unusual Microsoft native binary. This could be the result of
code injection or some other form of exploitation for defense evasion.
"""
integration = ["endpoint", "windows"]
uuid = "3b2900fe-74d9-4c49-b3df-cbeceb02e841"
name = "Executable File Creation by an Unusual Microsoft Binary"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"This hunt includes two optional queries, one for Elastic Defend data and another for Sysmon data.",
"Sysmon file events don't populate file header and process code signature information thus we use `file.extension`.",
"Some exploits may result in the creation of an executable file by the exploited process.",
"Further investigation can be done by pivoting on `process.executable` and filtering for executable file creation.",
]
mitre = [ "T1211", "T1055",]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "creation" and
starts_with(file.Ext.header_bytes, "4d5a") and process.code_signature.status == "trusted" and
starts_with(process.code_signature.subject_name, "Microsoft") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
''',
'''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "FileCreate" and
file.extension in ("exe", "dll") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
'''
]
@@ -1,24 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "3b2900fe-74d9-4c49-b3df-cbeceb02e841"
name = "Executable File creation by an Unusual Microsoft Binary - Elastic Defend"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"Sysmon file event don't populate file header and process code signature information thus the use of file.extension.",
"Some exploits may result in the creation of an executable file by the exploited process.",
"Further investigation can be done pivoting by process.executable and filter for executable file creation.",
]
mitre = [ "T1211", "T1055",]
query = '''
from logs-endpoint.events.file-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "creation" and
starts_with(file.Ext.header_bytes, "4d5a") and process.code_signature.status == "trusted" and
starts_with(process.code_signature.subject_name, "Microsoft") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
'''
@@ -1,23 +0,0 @@
[hunt]
author = "Elastic"
integration = ["windows"]
uuid = "36c94354-9d6e-4dc5-b2aa-a7cf578a4169"
name = "Executable File creation by an Unusual Microsoft Binary - Sysmon"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"Sysmon file event don't populate file header and process code signature information thus the use of file.extension.",
"Some exploits may result in the creation of an executable file by the exploited process.",
"Further investigation can be done pivoting by process.executable and filter for executable file creation.",
]
mitre = [ "T1211", "T1055",]
query = '''
from logs-windows.sysmon_operational-*
| where @timestamp > NOW() - 7 day
| where host.os.family == "windows" and event.category == "file" and event.action == "FileCreate" and
file.extension in ("exe", "dll") and process.executable rlike """[c-fC-F]:\\Windows\\(System32|SysWOW64)\\[a-zA-Z0-9_]+.exe"""
| keep process.executable, host.id
| stats occurences = count(*), agents = count_distinct(host.id) by process.executable
| where agents == 1 and occurences <= 10
'''
@@ -1,24 +0,0 @@
[hunt]
author = "Elastic"
integration = ["endpoint"]
uuid = "fd3f9982-fd8c-4f0f-bbe6-e589752c34db"
name = "Execution via Network Logon by occurrence frequency"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.",
"Execution via legit Microsoft processes like powershell and cmd need to further investigated via aggregation by process.command_line.",
"Aggregation can be also done by process.executable, normalizing process path by removing random patterns using the REPLACE function via regex.",
]
mitre = [ "T1021",]
query = '''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*), hosts = count_distinct(host.id) by process.hash.sha256, process.Ext.session_info.client_address, user.name, process.parent.name
/* unique hash limited to one host and number of execution is 1 */
| where hosts == 1 and total == 1
'''
@@ -1,24 +1,40 @@
[hunt]
author = "Elastic"
description = """
This hunt aggregates process execution and remote network logons by source address, account name and process hash. It then limits the results by unique host within a 7 day period. This may indicate lateral movement via remote services.
"""
integration = ["endpoint"]
uuid = "ae07c580-290e-4421-add8-d6ca30509b6a"
name = "Execution via Network Logon by occurrence frequency by top Source IP"
name = "Frequency of Process Execution via Network Logon by Source Address"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.",
"Execution via legit Microsoft processes like powershell and cmd need to further investigated via aggregation by process.command_line.",
"Aggregation can be also done by process.executable, normalizing process path by removing random patterns using the REPLACE function via regex.",
"The second query highest occurrence of source addresses/accounts performing remote process execution",
"`process.Ext.session_info.*` is populated for Elastic Defend versions 8.6.0+ and above.",
"Execution via legitimate Microsoft processes for PowerShell and cmd need to be further investigated via aggregation by `process.command_line`.",
"Aggregation can be also done by `process.executable`, normalizing process path by removing random patterns using the ES|QL REPLACE function.",
]
mitre = [ "T1021",]
query = '''
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*) by process.Ext.session_info.client_address, user.name
/* sort by top source.ip and account */
| sort total desc
'''
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type and the execution is within 30 seconds of the logon time */
process.Ext.session_info.logon_type == "Network" and process.Ext.session_info.relative_logon_time <= 30
| stats total = count(*), hosts = count_distinct(host.id) by process.hash.sha256, process.Ext.session_info.client_address, user.name, process.parent.name
/* unique hash limited to one host and number of execution is 1 */
| where hosts == 1 and total == 1
'''
]
@@ -1,23 +1,28 @@
[hunt]
author = "Elastic"
description = """
This hunt aggregates process execution via remote network logon by source address, account name and where the parent process is related to remote services such as WMI, WinRM, DCOM and remote PowerShell. This may indicate lateral movement via remote services.
"""
integration = ["endpoint"]
uuid = "e6e54717-2676-4785-a4a6-503577bfb0ea"
name = "Execution via Remote Services by Client Address"
language = "ES|QL"
license = "Elastic License v2"
notes = [
"process.Ext.session_info.* is populated for Elastic Defend version 8.6 and above.",
"`process.Ext.session_info.*` is populated for Elastic Defend versions 8.6.0+.",
]
mitre = [ "T1021", "T1021.003", "T1021.006", "T1047",]
mitre = [ "T1021", "T1021.003", "T1021.006", "T1047"]
query = '''
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
| where @timestamp > now() - 7 day and host.os.family == "windows" and
event.category == "process" and event.action == "start" and
/* network logon type */
process.Ext.session_info.logon_type == "Network" and
process.Ext.session_info.logon_type == "Network" and
(process.parent.name .caseless in ("wmiprvse.exe", "wsmprovhost.exe", "winrshost.exe") or (process.parent.name == "svchost.exe" and process.parent.args == "DcomLaunch"))
| stats total = count(*), hosts = count_distinct(host.id) by process.Ext.session_info.client_address, user.name, process.parent.name
/* sort by top source.ip and account */
| sort total desc
'''
'''
]

Some files were not shown because too many files have changed in this diff Show More