[New Hunt] Add Initial Linux Hunting Files (#3847)

* added 'Uncommon Process Execution from Suspicious Directory' hunt

* adds all linux hunting files

* moves linux hunting files to queries folder

* adds generated docs

* fixing windows hunts

* fixing windows hunts

* updated README

* Removed 2, updated a few, changed some names/descriptions and added list of str

* updated windows for language schema changes, regenerated docs; updated README and index

* changed UUIDs to hex only with standard hyphen format

* removing unecessary docs

* Fixed queries based on Samir feedback

* ++

* regenerating linux docs

* Update hunting/linux/queries/command_and_control_via_network_connections_with_low_occurrence_frequency_for_unique_agents.toml

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

* Update hunting/linux/queries/defense_evasion_via_hidden_process_execution.toml

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

* Update hunting/linux/queries/command_and_control_via_unusual_file_downloads_from_source_addresses.toml

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

* Update hunting/linux/queries/defense_evasion_via_capitalized_process_execution.toml

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

* Update hunting/linux/queries/defense_evasion_via_hidden_process_execution.toml

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

* Updates

* Update

* Update hunting/linux/queries/command_and_control_via_network_connections_with_low_occurrence_frequency_for_unique_agents.toml

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

* Updates

* regenerating linux docs

---------

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

(cherry picked from commit f0b2cb7c87)
This commit is contained in:
Terrance DeJesus
2024-07-05 14:01:12 -04:00
committed by github-actions[bot]
parent c9f50a2d5c
commit 532245cc20
137 changed files with 3930 additions and 178 deletions
+20 -17
View File
@@ -2,15 +2,23 @@
---
Welcome to the `hunting` folder within the `detection-rules` repository! This directory houses a curated collection of threat hunting queries designed to enhance security monitoring and threat detection capabilities using the Elastic Stack. Each file in this directory provides a query tailored for identifying specific security threats or suspicious activities.
Welcome to the `hunting` folder within the `detection-rules` repository! This directory houses a curated collection of threat hunting queries designed to enhance security monitoring and threat detection capabilities using the Elastic Stack. Each file in this directory provides a query tailored for the initial evidence gathering of specific hunts.
These queries are designed for use with the Elastic Security platform, part of the broader Elastic Stack, enabling security teams to proactively hunt for potential threats in their environment.
Each hunt has a designated TOML and Markdown file, intended to be used either programatically or via copy and pasted. Notes about data considerations, pivoting, exploring data further and more have been added to each hunting query. These queries are designed for use with the Elastic Security platform, part of the broader Elastic Stack, enabling security teams to proactively hunt for potential threats in their environment.
- KQL
- EQL
- ES|QL
- OsQuery
- YARA
Note that some hunting files will include a mix of queries with different languages whose sole purpose is to provide optional queries to gather evidence for the hunt.
- [KQL](https://www.elastic.co/guide/en/kibana/current/kuery-query.html)
- [EQL](https://www.elastic.co/guide/en/elasticsearch/reference/current/eql.html)
- [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html)
- [OsQuery/SQL](https://www.elastic.co/guide/en/kibana/current/osquery.html)
- [YARA](https://yara.readthedocs.io/en/stable/writingrules.html)
The hunting queries shared in this folder are a mix of the following hunting methods:
- Hypothesis-Driven - Assumed breach method with specific hypothesis of where adversary dwells or where footprints exist.
- CTI-Driven - Retro-active searches for specific indicators-of-compromise or tactics, techniques and procedures (TTPs) related to adversaries and/or tooling.
- Data-Driven - Initial evidence collecting query that requires more advanced data analysis to uncover anomalies.
## How to Contribute
@@ -18,25 +26,20 @@ Contributing to the `hunting` folder is a great way to share your expertise and
### Names and Related Queries
All query names should be unique and descriptive. If a query's intent is identical or related to another query, consider
adding a suffix with the integration(s) to the name to indicate the relationship and distinguish them from each other.
All query names should be unique and descriptive. If a query's intent is identical or related to another query, consider
adding a suffix with the integration(s) to the name to indicate the relationship and distinguish them from each other.
Otherwise, the names do not require the integration, since it is already annotated within the `integration` field.
The filename should reflect the query name.
For example:
- `Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Elastic Defend`
- `Detect DLL Hijack via Masquerading as Microsoft Native Libraries - Sysmon`
### Adding New Queries
- **TOML File Naming and Organization**: Ensure that any new queries are named descriptively and grouped by the type of threat they address. Place your TOML files inside the `queries` folder and ensure they are named in a way that reflects the nature of the threat or behavior they are designed to detect.
- **TOML Fields**: To ensure the hunt queries are consistent and comprehensive, it's important to structure the threat detection rules with specific fields. When contributing a new rule, please include the following fields in the TOML file to describe and configure the analytic:
- **author**: The name of the individual or organization authoring the rule.
- **description**: The purpose of the hunt with a clear threat explanation and hunting goal.
- **integration**: The specific integration or data source the rule applies to, such as `aws_bedrock.invocation`.
- **uuid**: A unique identifier for the rule to maintain version control and tracking.
- **name**: A descriptive name for the rule that clearly indicates its purpose.
- **language**: The query language used in the rule, such as `KQL`, `EQL`, `ES|QL`, `OsQuery`, or `YARA`.
- **query**: The actual query or analytic expression written in the appropriate query language that executes the detection logic.
- **language**: The query language(s) used in the rule, such as `KQL`, `EQL`, `ES|QL`, `OsQuery`, or `YARA`.
- **query**: An array of actual queries or analytic expressions written in the appropriate query language that executes the detection logic.
- **notes**: An array of strings providing detailed insights into the rationale behind the rule, suggestions for further investigation, and tips on distinguishing false positives from true activity.
- **mitre**: Reference to applicable MITRE ATT&CK tactics or techniques that the rule addresses, enhancing the contextual understanding of its security implications.
- **references**: Links to external documents, research papers, or websites that provide additional information or validation for the detection logic.
+3 -3
View File
@@ -32,7 +32,7 @@ class Hunt:
integration: list[str]
uuid: str
name: str
language: str
language: list[str]
license: str
query: list[str]
notes: Optional[List[str]] = field(default_factory=list)
@@ -85,7 +85,7 @@ def convert_toml_to_markdown(hunt_config: Hunt, file_path: Path) -> str:
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 += f"- **Language:** `{hunt_config.language}`\n\n".replace("'", "").replace('"', "")
markdown += "## Query\n\n"
for query in hunt_config.query:
markdown += f"```sql\n{query}```\n\n"
@@ -127,7 +127,7 @@ def process_toml_files(base_path: Path) -> None:
index_content += f"\n\n## {folder}\n"
for file_path, rule_name, language in sorted(files):
index_path = "./" + str(file_path)
index_content += f"- [{rule_name}]({index_path}) ({language})\n"
index_content += f"- [{rule_name}]({index_path}) ({", ".join(language)})\n"
# Write the index file at the base directory level
index_path = base_path / "index.md"
+33
View File
@@ -2,6 +2,39 @@
Here are the queries currently available:
## linux
- [Network Connections with Low Occurrence Frequency for Unique Agent ID](./linux/docs/command_and_control_via_network_connections_with_low_occurrence_frequency_for_unique_agents.md) (ES|QL)
- [Unusual File Downloads from Source Addresses](./linux/docs/command_and_control_via_unusual_file_downloads_from_source_addresses.md) (ES|QL)
- [Defense Evasion via Capitalized Process Execution](./linux/docs/defense_evasion_via_capitalized_process_execution.md) (ES|QL)
- [Hidden Process Execution](./linux/docs/defense_evasion_via_hidden_process_execution.md) (ES|QL)
- [Potential Defense Evasion via Multi-Dot Process Execution](./linux/docs/defense_evasion_via_multi_dot_process_execution.md) (ES|QL)
- [Excessive SSH Network Activity to Unique Destinations](./linux/docs/excessive_ssh_network_activity_unique_destinations.md) (ES|QL)
- [Uncommon Process Execution from Suspicious Directory](./linux/docs/execution_uncommon_process_execution_from_suspicious_directory.md) (ES|QL)
- [Logon Activity by Source IP](./linux/docs/login_activity_by_source_address.md) (ES|QL)
- [Low Volume External Network Connections from Process by Unique Agent](./linux/docs/low_volume_external_network_connections_from_process.md) (ES|QL)
- [Low Volume GTFOBins External Network Connections](./linux/docs/low_volume_gtfobins_external_network_connections.md) (ES|QL)
- [Low Volume Modifications to Critical System Binaries by Unique Host](./linux/docs/low_volume_modifications_to_critical_system_binaries.md) (ES|QL)
- [Low Volume Process Injection-Related Syscalls by Process Executable](./linux/docs/low_volume_process_injection_syscalls_by_executable.md) (ES|QL)
- [Persistence Through Reverse/Bind Shells](./linux/docs/persistence_reverse_bind_shells.md) (SQL)
- [Persistence via Cron](./linux/docs/persistence_via_cron.md) (ES|QL, SQL)
- [Drivers Load with Low Occurrence Frequency](./linux/docs/persistence_via_driver_load_with_low_occurrence_frequency.md) (ES|QL)
- [Git Hook/Pager Persistence](./linux/docs/persistence_via_git_hook_pager.md) (ES|QL, SQL)
- [Persistence via Message-of-the-Day](./linux/docs/persistence_via_message_of_the_day.md) (ES|QL, SQL)
- [Persistence via Packager Manager](./linux/docs/persistence_via_package_manager.md) (ES|QL, SQL)
- [Persistence via rc.local/rc.common](./linux/docs/persistence_via_rc_local.md) (ES|QL, SQL)
- [Shell Modification Persistence](./linux/docs/persistence_via_shell_modification_persistence.md) (ES|QL, SQL)
- [Persistence via SSH Configurations and/or Keys](./linux/docs/persistence_via_ssh_configurations_and_keys.md) (SQL)
- [Persistence via Systemd (Timers)](./linux/docs/persistence_via_systemd_timers.md) (ES|QL, SQL)
- [Persistence via Udev](./linux/docs/persistence_via_udev.md) (ES|QL, SQL)
- [Unusual System Binary Parent (Potential System Binary Hijacking Attempt)](./linux/docs/persistence_via_unusual_system_binary_parent.md) (ES|QL)
- [Privilege Escalation/Persistence via User/Group Creation and/or Modification](./linux/docs/persistence_via_user_group_creation_modification.md) (SQL)
- [XDG Persistence](./linux/docs/persistence_via_xdg_autostart_modifications.md) (ES|QL, SQL)
- [Privilege Escalation Identification via Existing Sudoers File](./linux/docs/privilege_escalation_via_existing_sudoers.md) (SQL)
- [Process Capability Hunting](./linux/docs/privilege_escalation_via_process_capabilities.md) (ES|QL)
- [Segmentation Fault & Potential Buffer Overflow Hunting](./linux/docs/privilege_escalation_via_segmentation_fault_and_buffer_overflow.md) (ES|QL)
- [OSQuery SUID Hunting](./linux/docs/privilege_escalation_via_suid_binaries.md) (SQL)
## llm
- [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)
@@ -0,0 +1,78 @@
# Network Connections with Low Occurrence Frequency for Unique Agent ID
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies network connections with low occurrence frequency for unique agent IDs on Linux systems. It monitors network connection attempts and acceptances, focusing on those initiated by processes that are rarely seen in the environment. By accounting for known low-frequency legitimate binaries (LoLBins) and suspicious directories, this hunt aims to detect unusual network activity that may indicate malicious behavior.
- **UUID:** `ecd84bc7-32ae-474b-93a8-d1d9736c3464`
- **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.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable
| where agent_count == 1 and cc > 0 and cc <= 3
| limit 100
| sort cc asc
```
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and (
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "socat", "java", "awk", "gawk", "mawk", "nawk", "openssl", "nc", "ncat", "netcat", "nc.openbsd", "telnet") or
process.name like "python*" or
process.name like "perl*" or
process.name like "ruby*" or
process.name like "lua*" or
process.name like "php*"
) and
destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.name
| where agent_count <= 3 and cc > 0 and cc <= 5
| limit 100
| sort cc asc
```
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and (
process.executable like "./*" or
process.executable like "/dev/shm/*" or
process.executable like "/var/www/*" or
process.executable like "/boot/*" or
process.executable like "/srv/*" or
process.executable rlike "/tmp/[^/]+" or
process.executable rlike "/var/tmp/[^/]+" or
process.executable rlike "/run/[^/]+" or
process.executable rlike "/var/run/[^/]+"
) and
destination.ip IS NOT null and not CIDR_MATCH(destination.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable
| where agent_count <= 3 and cc > 0 and cc <= 5
| limit 100
| sort cc asc
```
## Notes
- Monitors for network connections initiated by processes that have low occurrence frequency, focusing on unique agent IDs.
- Excludes common internal IP ranges to minimize false positives.
- Accounts for known low-frequency legitimate binaries (LoLBins) to reduce noise.
- Identifies suspicious directories where processes are executed from, which can indicate malicious activity.
## MITRE ATT&CK Techniques
- [T1071.001](https://attack.mitre.org/techniques/T1071/001)
- [T1071.004](https://attack.mitre.org/techniques/T1071/004)
## License
- `Elastic License v2`
@@ -0,0 +1,39 @@
# Unusual File Downloads from Source Addresses
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies unusual file download activities on Linux systems. It detects instances where commonly used download utilities such as curl and wget are executed with command lines that contain IP addresses, which can indicate potentially suspicious file downloads.
- **UUID:** `0d061fad-cf35-43a6-b9b7-986c348bf182`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and process.name in ("curl", "wget") and process.command_line rlike """.*[0-9]{1,3}(\.[0-9]{1,3}){3}.*"""
| stats cc = count(), host_count = count_distinct(host.id) by process.command_line, process.executable
| where cc <= 10 and host_count <= 5
| sort cc asc
| limit 100
```
## Notes
- Detects instances where download utilities like curl and wget are used with IP addresses in their command lines.
- Monitors for potentially suspicious file downloads, which are often seen in malicious activities.
- Uses process command line counting in conjunction with host counting to minimize false positives caused by legitimate downloads.
- The process command line count threshold is set to <= 10, and the host count threshold is set to <= 5 to balance detection and noise.
## MITRE ATT&CK Techniques
- [T1071.001](https://attack.mitre.org/techniques/T1071/001)
- [T1071.004](https://attack.mitre.org/techniques/T1071/004)
## License
- `Elastic License v2`
@@ -0,0 +1,41 @@
# Defense Evasion via Capitalized Process Execution
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential defense evasion techniques via capitalized process execution on Linux systems. It detects processes that have two or more consecutive capital letters within their names, which can indicate an attempt to evade detection. Such naming conventions are often used in malicious payloads to blend in with legitimate processes.
- **UUID:** `9d485892-1ca2-464b-9e4e-6b21ab379b9a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 10 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
(process.name rlike """[A-Z]{2,}[a-z]{1,}[0-9]{0,}""") or
(process.name rlike """[A-Z]{1,}[0-9]{0,}""")
)
| stats cc = count(), host_count = count_distinct(host.name) by process.name
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| limit 100
```
## Notes
- Detects processes that have two or more consecutive capital letters within their names, with optional digits.
- This technique is often used in malicious payloads, such as Metasploit payloads, to evade detection.
- Included a process count of <= 3 and a host count of <= 3 to eliminate common processes across different hosts.
## MITRE ATT&CK Techniques
- [T1036.004](https://attack.mitre.org/techniques/T1036/004)
- [T1070](https://attack.mitre.org/techniques/T1070)
## License
- `Elastic License v2`
@@ -0,0 +1,39 @@
# Hidden Process Execution
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies hidden process executions on Linux systems. It detects processes executed from hidden files, which are often used by malicious actors to conceal their activities. By focusing on hidden files rather than directories, this hunt aims to catch stealthy processes while minimizing noise.
- **UUID:** `00461198-9a2d-4823-b4cc-f3d1b5c17935`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and
process.executable rlike "/[^/]+/\\.[^/]+"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable, user.id
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| sort cc asc
| limit 100
```
## Notes
- Included only hidden files, excluding hidden directories, as hidden directories are common in Unix.
- Included a process or parent process count of <= 3, and a host count of <= 3 to eliminate common processes across different hosts.
## MITRE ATT&CK Techniques
- [T1036.004](https://attack.mitre.org/techniques/T1036/004)
- [T1059](https://attack.mitre.org/techniques/T1059)
## License
- `Elastic License v2`
@@ -0,0 +1,38 @@
# Potential Defense Evasion via Multi-Dot Process Execution
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential defense evasion techniques via multi-dot process execution on Linux systems. It looks for processes with executables that contain three or more consecutive dots in their names. Such naming conventions can be used by malicious actors to evade detection and blend in with legitimate processes.
- **UUID:** `11810497-8ce3-4960-9777-9d0e97052682`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.executable rlike """.*\.{3,}.*"""
| stats cc = count() by process.executable
// Alter this threshold to make sense for your environment
| where cc <= 10
| sort cc asc
| limit 100
```
## Notes
- This query identifies processes with executables containing three or more consecutive dots in their names.
- The process count threshold of <= 10 can be adjusted based on the environment's baseline activity.
## MITRE ATT&CK Techniques
- [T1036.004](https://attack.mitre.org/techniques/T1036/004)
- [T1070](https://attack.mitre.org/techniques/T1070)
## License
- `Elastic License v2`
@@ -0,0 +1,40 @@
# Excessive SSH Network Activity to Unique Destinations
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies excessive SSH network activity to unique destinations on Linux systems. It monitors network connections over TCP to port 22 (SSH) and counts the number of unique destination IP addresses. A high number of unique destinations could indicate suspicious activity such as discovery or lateral movement.
- **UUID:** `223f812c-a962-4d58-961d-134d8f8b15da`
- **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.type == "linux" and event.category == "network" and network.transport == "tcp" and destination.port == 22 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
// Alter this threshold to make sense for your environment
| where count_unique_dst >= 10
| limit 100
| sort user.name asc
```
## Notes
- Monitors network connections to port 22 (SSH) and counts the number of unique destination IP addresses per host and user.
- A high number of unique destinations can indicate suspicious activity such as discovery or lateral movement.
- The threshold of 10 unique destinations can be adjusted to suit the environment's baseline activity.
## MITRE ATT&CK Techniques
- [T1021.004](https://attack.mitre.org/techniques/T1021/004)
- [T1078.003](https://attack.mitre.org/techniques/T1078/003)
## License
- `Elastic License v2`
@@ -0,0 +1,59 @@
# Uncommon Process Execution from Suspicious Directory
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies uncommon process executions from suspicious directories on Linux systems. It looks for processes executed from directories that are often associated with malicious activity, such as /dev/shm, /var/www, /boot, /srv, /tmp, /var/tmp, /run, and /var/run. The goal is to detect potentially malicious processes while excluding common, benign ones.
- **UUID:** `0ea47044-b161-4785-ba99-e11f46d6ac51`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
// Add paths to monitor from your environment here
process.executable like "/dev/shm/*" or
process.executable like "/var/www/*" or
process.executable like "/boot/*" or
process.executable like "/srv/*" or
process.executable rlike "/tmp/[^/]+" or
process.executable rlike "/var/tmp/[^/]+" or
process.executable rlike "/run/[^/]+" or
process.executable rlike "/var/run/[^/]+"
) and not (
// Exclude noisy (parent) processes, users or directories from your environment here
process.parent.executable in ("/usr/sbin/dpkg-preconfigure") or
// Exclude /tmp and /var/tmp instances starting or ending with digits (usually benign files)
process.executable rlike "/tmp/[0-9].*" or
process.executable rlike "/tmp/.*[0-9]/?" or
process.executable rlike "/var/tmp/[0-9].*" or
process.executable rlike "/var/tmp/.*[0-9]/?"
)
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| sort cc asc
| limit 100
```
## Notes
- Excluded /tmp, /var/tmp, /run, /var/run subdirectories to reduce noise.
- Excluded /tmp, /var/tmp files starting or ending with digits to exclude real temporary files.
- Included a process or parent process count of <= 3, and a host count of <= 3 to eliminate common processes across different hosts.
## MITRE ATT&CK Techniques
- [T1036.004](https://attack.mitre.org/techniques/T1036/004)
- [T1049](https://attack.mitre.org/techniques/T1049)
- [T1059](https://attack.mitre.org/techniques/T1059)
- [T1059.004](https://attack.mitre.org/techniques/T1059/004)
## License
- `Elastic License v2`
@@ -0,0 +1,39 @@
# Logon Activity by Source IP
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies unusual logon activity by source IP on Linux systems. It monitors authentication events, focusing on failed logon attempts from specific IP addresses. A high number of failed logon attempts combined with a low number of successful logons and multiple distinct usernames can indicate a potential brute force or credential stuffing attack.
- **UUID:** `95c1467d-d566-4645-b5f1-37a4b0093bb6`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-system.auth-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "authentication" and event.action in ("ssh_login", "user_login") and
event.outcome == "failure" and source.ip IS NOT null and not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")
| eval failed = case(event.outcome == "failure", source.ip, null), success = case(event.outcome == "success", source.ip, null)
| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.name) by source.ip
/* below threshold should be adjusted to your env logon patterns */
| where count_failed >= 100 and count_success <= 10 and count_user >= 20
```
## Notes
- Monitors authentication events and counts failed and successful logon attempts by source IP address.
- A high number of failed logon attempts combined with a low number of successful logons and multiple distinct usernames can indicate a potential brute force or credential stuffing attack.
- The thresholds for failed attempts, successful logons, and distinct usernames should be adjusted based on the environment's normal logon patterns.
## MITRE ATT&CK Techniques
- [T1110](https://attack.mitre.org/techniques/T1110)
- [T1078](https://attack.mitre.org/techniques/T1078)
## License
- `Elastic License v2`
@@ -0,0 +1,50 @@
# Low Volume External Network Connections from Process by Unique Agent
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies low volume external network connections initiated by processes on Linux systems. It focuses on connections attempted by processes that have been seen infrequently (five or fewer connections) and by unique agents. This can help identify potentially suspicious activity that might be missed due to low volume.
- **UUID:** `12526f14-5e35-4f5f-884c-96c6a353a544`
- **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.type == "linux" and event.category == "network" and event.type == "start" and event.action == "connection_attempted" and not process.name is null 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")
| stats connection_count = count(*), unique_agent_count = count_distinct(agent.id) by process.name
| where connection_count <= 5 and unique_agent_count == 1
| limit 100
| sort connection_count, unique_agent_count asc
```
```sql
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "network" and event.type == "start" and event.action == "connection_attempted" and user.id == "0" and not process.name is null 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")
| stats connection_count = count(*), unique_agent_count = count_distinct(agent.id) by process.name
| where connection_count <= 5 and unique_agent_count == 1
| limit 100
| sort connection_count, unique_agent_count asc
```
## Notes
- Monitors for network connections attempted by processes that have a low occurrence frequency (five or fewer connections) and are seen by a unique agent.
- Excludes common internal IP ranges to minimize false positives.
- A separate query is included to specifically monitor low volume network connections initiated by the root user, as these can be particularly indicative of malicious activity.
## MITRE ATT&CK Techniques
- [T1071.001](https://attack.mitre.org/techniques/T1071/001)
- [T1071.004](https://attack.mitre.org/techniques/T1071/004)
## License
- `Elastic License v2`
@@ -0,0 +1,46 @@
# Low Volume GTFOBins External Network Connections
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies low volume external network connections initiated by GTFOBins on Linux systems. GTFOBins are Unix binaries that can be exploited by attackers to bypass local security restrictions. The hunt focuses on network connections made by these binaries, excluding common internal IP ranges, to detect potentially malicious activity.
- **UUID:** `783d6091-b98d-45a8-a880-a07f112a8aa2`
- **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.type == "linux" and event.type == "start" and process.name in (
"ab", "aria2c", "bash", "cpan", "curl", "easy_install", "finger", "ftp",
"gdb", "gimp", "irb", "jjs", "jrunscript", "julia", "ksh", "lua", "lwp-download",
"nc", "nmap", "node", "openssl", "php", "pip", "python", "ruby", "rview", "rvim",
"scp", "sftp", "smbclient", "socat", "ssh", "tar", "tftp", "view", "vim", "vimdiff",
"wget", "whois", "yum"
) and
destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep process.name, destination.port, destination.ip, user.name, host.name
| stats cc = count(*) by destination.port, process.name
| where cc <= 5
| sort cc asc, destination.port
```
## Notes
- Monitors for external network connections initiated by known GTFOBins such as bash, curl, nc, wget, and others.
- Excludes common internal IP ranges to minimize false positives.
- Counts the occurrences of these connections by process name and limits to those seen infrequently (five or fewer connections).
- This can help identify potentially malicious activity involving the exploitation of GTFOBins.
## MITRE ATT&CK Techniques
- [T1219](https://attack.mitre.org/techniques/T1219)
- [T1071.001](https://attack.mitre.org/techniques/T1071/001)
## License
- `Elastic License v2`
@@ -0,0 +1,49 @@
# Low Volume Modifications to Critical System Binaries by Unique Host
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies low volume modifications to critical system binaries on Linux systems. It monitors file modification events in critical directories such as /bin, /usr/bin, /sbin, and /usr/sbin. The hunt focuses on modifications made by unique hosts, excluding expected update processes like package managers. This can help detect unauthorized or suspicious modifications to system binaries.
- **UUID:** `c7044817-d9a5-4755-abab-9059e50dab24`
- **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.type == "linux" and
(file.path like "/bin/*" or file.path like "/usr/bin/*" or file.path like "/sbin/*" or file.path like "/usr/sbin/*") and
not (
// Exclude expected update processes, e.g., package managers
process.executable in ("/usr/bin/apt", "/usr/bin/dpkg", "/usr/bin/yum", "/usr/bin/rpm", "/usr/bin/pacman",
"/usr/bin/pamac-daemon", "/usr/bin/update-alternatives", "/usr/bin/dockerd", "/usr/bin/microdnf", "/sbin/apk") or
// Exclude certain benign or expected modification patterns, if applicable
file.path like "/usr/bin/gzip*" // Example exclusion, adjust based on your environment
)
| stats modification_count = count(file.path), unique_files_modified = count_distinct(file.path), host_count = count_distinct(host.name) by process.executable
| where modification_count >= 1 and host_count == 1
| sort modification_count asc
| limit 100
```
## Notes
- Monitors for file modifications in critical directories like /bin, /usr/bin, /sbin, and /usr/sbin.
- Excludes modifications made by expected update processes such as package managers to reduce false positives.
- Counts the number of unique files modified by each host and the number of modifications made.
- Focuses on modifications made by unique hosts to detect unauthorized or suspicious changes.
## MITRE ATT&CK Techniques
- [T1070.004](https://attack.mitre.org/techniques/T1070/004)
- [T1569.002](https://attack.mitre.org/techniques/T1569/002)
## License
- `Elastic License v2`
@@ -0,0 +1,38 @@
# Low Volume Process Injection-Related Syscalls by Process Executable
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies low volume process injection-related syscalls on Linux systems. It monitors audit logs for syscalls related to process injection, such as ptrace and memfd_create. The hunt focuses on processes that make these syscalls infrequently, which can indicate potential malicious activity.
- **UUID:** `c9931736-d5ec-4c89-b4d2-d71dcf5ca12a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-auditd_manager.auditd-*, logs-auditd.log-*, auditbeat-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and auditd.data.syscall in ("ptrace", "memfd_create")
| stats cc = count(*) by process.executable, auditd.data.syscall
| where cc <= 10
| limit 100
| sort cc asc
```
## Notes
- Monitors for process injection-related syscalls such as ptrace and memfd_create.
- Counts the occurrences of these syscalls by process executable to identify processes that make these syscalls infrequently.
- Focuses on low volume occurrences to detect potential malicious activity related to process injection.
## MITRE ATT&CK Techniques
- [T1055.001](https://attack.mitre.org/techniques/T1055/001)
- [T1055.009](https://attack.mitre.org/techniques/T1055/009)
## License
- `Elastic License v2`
@@ -0,0 +1,58 @@
# Persistence Through Reverse/Bind Shells
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt provides several OSQuery queries that can aid in the detection of reverse/bind shells. Reverse shells are a type of shell in which the target machine communicates back to the attacking machine. Bind shells are a type of shell in which the target machine opens a communication port on the victim machine and waits for an attacker to connect to it. These shells can be used by attackers to gain remote access to a system.
- **UUID:** `7422faf1-ba51-49c3-b8ba-13759e6bcec4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[SQL]`
## Query
```sql
SELECT (
CASE family
WHEN 2 THEN 'IP4'
WHEN 10 THEN 'IP6'
ELSE family END
) AS family, (
CASE protocol
WHEN 6 THEN 'TCP'
WHEN 17 THEN 'UDP'
ELSE protocol END
) AS protocol, local_address, local_port,
remote_address, remote_port
FROM process_open_sockets
WHERE family IN (2, 10)
AND protocol IN (6, 17)
```
```sql
SELECT cmdline, name, path, pid, state, threads, total_size
FROM processes
WHERE cmdline != ''
```
```sql
SELECT pid, address, port, socket, protocol, path FROM listening_ports
```
## Notes
- The hunt provides OSQuery queries to detect reverse/bind shells on Linux systems.
- The first hunt query retrieves information about open sockets on the system.
- The second hunt query retrieves information about running processes on the system.
- The third hunt query retrieves information about listening ports on the system.
- Investigate strange or unexpected open sockets, processes, or listening ports on the system.
- Use the information from each hunt to pivot and investigate further for potential reverse/bind shells.
## MITRE ATT&CK Techniques
- [T1059.004](https://attack.mitre.org/techniques/T1059/004)
## License
- `Elastic License v2`
+111
View File
@@ -0,0 +1,111 @@
# Persistence via Cron
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via cron on Linux systems. It monitors for file creation or modification events related to cron configurations and processes spawned by cron, fcron, or atd. These activities can indicate attempts to establish persistence through scheduled tasks.
- **UUID:** `e1cffb7c-4acf-4e7a-8d72-b8b7657cf7b8`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path in ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab") or
file.path like "/etc/cron.*/*" or
file.path like "/var/spool/cron/crontabs/*" or
file.path like "/var/spool/anacron/*" or
file.path like "/var/spool/cron/atjobs/*" or
file.path like "/var/spool/fcron/*" or
file.path like "/home/*/.tsp/*"
) and not (
process.name in ("dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "anacron") or
file.extension in ("dpkg-remove", "swx", "swp") or
file.name like "tmp.*"
)
| eval persistence = case(
file.path in ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab") or
file.path like "/etc/cron.*/*" or
file.path like "/var/spool/cron/crontabs/*" or
file.path like "/var/spool/anacron/*" or
file.path like "/var/spool/cron/atjobs/*" or
file.path like "/var/spool/fcron/*" or
file.path like "/home/*/.tsp/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 3
| sort pers_count asc
| limit 100
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("cron", "fcron", "atd")
| stats cc = count(), host_count = count_distinct(host.id) by process.command_line
| where host_count <= 3
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path IN ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab")
OR f.path LIKE "/etc/cron.%/*"
OR f.path LIKE "/var/spool/cron/crontabs/%"
OR f.path LIKE "/var/spool/anacron/%"
OR f.path LIKE "/var/spool/cron/atjobs/%"
OR f.path LIKE "/var/spool/fcron/%"
OR f.path LIKE "/home/%/.tsp/%"
OR f.path LIKE "/etc/cron.allow.d/%"
OR f.path LIKE "/etc/cron.d/%"
OR f.path LIKE "/etc/cron.hourly/%"
OR f.path LIKE "/etc/cron.daily/%"
OR f.path LIKE "/etc/cron.weekly/%"
OR f.path LIKE "/etc/cron.monthly/%"
```
```sql
SELECT * FROM crontab
```
## Notes
- This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via cron on Linux systems.
- Detects file creation or modification events in directories and files associated with cron configurations, such as /etc/cron.allow, /etc/cron.deny, /etc/crontab, all /etc/cron.* directories and various /var/spool directories.
- Excludes common legitimate processes and file types to minimize false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by cron, fcron, or atd to detect potential persistence mechanisms.
- OSQuery queries are provided to complement the detection by retrieving detailed file information and crontab entries.
## MITRE ATT&CK Techniques
- [T1053.003](https://attack.mitre.org/techniques/T1053/003)
- [T1053.005](https://attack.mitre.org/techniques/T1053/005)
## License
- `Elastic License v2`
@@ -0,0 +1,39 @@
# Drivers Load with Low Occurrence Frequency
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies drivers loaded with low occurrence frequency on Linux systems. It monitors for the loading of kernel modules (drivers) that have only been seen once across a single host within a year. Such activity can indicate the presence of rare or potentially malicious drivers.
- **UUID:** `e1f59c9a-7a2a-4eb8-a524-97b16a041a4a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-auditd_manager.auditd-*, logs-auditd.log-*, auditbeat-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.category == "driver" and event.action == "loaded-kernel-module" and auditd.data.syscall in ("init_module", "finit_module")
| stats host_count = count_distinct(host.id), total_count = count(*) by auditd.data.name, process.executable, process.name
// Alter this threshold to make sense for your environment
| where host_count == 1 and total_count == 1
| limit 100
| sort auditd.data.name asc
```
## Notes
- Monitors for kernel modules loaded with syscall 'init_module' or 'finit_module', indicating driver load events.
- Counts the occurrence of each driver across all hosts and identifies those seen only once on a single host within the past year.
- Such rare driver loads can indicate potentially malicious activity or the presence of uncommon drivers.
## MITRE ATT&CK Techniques
- [T1547.006](https://attack.mitre.org/techniques/T1547/006)
- [T1069.002](https://attack.mitre.org/techniques/T1069/002)
## License
- `Elastic License v2`
@@ -0,0 +1,90 @@
# Git Hook/Pager Persistence
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via Git hooks and configurations on Linux systems. It monitors file creation or modification events in Git configuration and hook directories, as well as processes started by Git hooks. These activities can indicate attempts to establish persistence through Git configurations. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `2d7bb29d-d53f-47ab-a0b4-1818adb91423`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path == "/etc/gitconfig" or
file.path like "*/.git/config" or
file.path like "/home/*/.gitconfig" or
file.path like "*/.git/hooks/*"
) and process.name != "git"
| eval persistence = case(
file.path == "/etc/gitconfig" or
file.path like "*/.git/config" or
file.path like "/home/*/.gitconfig" or
file.path like "*/.git/hooks/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 4
| sort pers_count asc
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.executable like "*.git/hooks/*"
| stats cc = count(), host_count = count_distinct(host.name) by process.parent.executable, process.executable
| where cc < 50 and host_count <= 5
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change time,
datetime(f.btime, 'unixepoch') AS file created time,
f.size AS size bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path == '/etc/gitconfig'
OR f.path LIKE '/%%/.git/config'
OR f.path LIKE '/home/%/.gitconfig'
OR f.path LIKE '/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/%%/%%/.git/hooks/%'
```
## Notes
- Monitors for file creation or modification events in Git configuration and hook directories such as /etc/gitconfig, .git/config, /home/*/.gitconfig, and .git/hooks/.
- Excludes modifications made by the Git process itself to reduce false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by Git hooks to detect suspicious activity related to Git configurations.
- OSQuery query is provided to retrieve detailed file information related to Git configurations and hooks.
- OSQuery has limited support for wildcard queries, therefore the query includes multiple LIKE conditions for directories. These can be increased and decreased based on the environment's Git configuration paths.
## MITRE ATT&CK Techniques
- [T1546.004](https://attack.mitre.org/techniques/T1546/004)
- [T1059.004](https://attack.mitre.org/techniques/T1059/004)
## License
- `Elastic License v2`
@@ -0,0 +1,80 @@
# Persistence via Message-of-the-Day
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via the message-of-the-day (motd) on Linux systems. It monitors for file creation or modification events in the /etc/update-motd.d directory and processes started by these motd scripts. These scripts launch on SSH/terminal connection events, and execute the scripts as root. These activities can indicate attempts to establish persistence through motd modifications.
- **UUID:** `5984a354-d76c-43e6-bdd9-228456f1b371`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and file.path like "/etc/update-motd.d/*" and
not process.name in ("dpkg", "dockerd", "yum", "dnf", "snapd", "pacman")
| eval persistence = case(file.path like "/etc/update-motd.d/*", process.name, null)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 5
| sort pers_count asc
| limit 100
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.executable like "/etc/update-motd.d/*" and
not process.args like "/tmp/tmp.*"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable
| where host_count <= 5
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN ('/etc/update-motd.d/')
ORDER BY
f.mtime DESC;
```
## Notes
- This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via the message-of-the-day (motd) on Linux systems.
- Detects file creation or modification events in the /etc/update-motd.d directory, which is used for message-of-the-day scripts.
- Excludes common legitimate processes to minimize false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by motd scripts to detect potential persistence mechanisms.
- OSQuery query is provided to complement the detection by retrieving detailed file information related to motd scripts.
## MITRE ATT&CK Techniques
- [T1036.005](https://attack.mitre.org/techniques/T1036/005)
- [T1546.003](https://attack.mitre.org/techniques/T1546/003)
## License
- `Elastic License v2`
@@ -0,0 +1,100 @@
# Persistence via Packager Manager
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via package manager configurations on Linux systems. It monitors file creation or modification events in directories related to APT, YUM, and DNF package managers. Additionally, it monitors processes started by these package managers. These activities can indicate attempts to establish persistence through package manager configurations. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `2d01a413-8d97-407a-8698-02dfc7119c97`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path like "/etc/apt/apt.conf.d/*" or
file.path like "/usr/lib/python*/site-packages/dnf-plugins/*" or
file.path like "/etc/dnf/plugins/*" or
file.path like "/usr/lib/yum-plugins/*" or
file.path like "/etc/yum/pluginconf.d/*"
) and not process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"microdnf", "podman", "apk", "yumBackend.py"
)
| eval persistence = case(
file.path like "/etc/apt/apt.conf.d/*" or
file.path like "/usr/lib/python*/site-packages/dnf-plugins/*" or
file.path like "/etc/dnf/plugins/*" or
file.path like "/usr/lib/yum-plugins/*" or
file.path like "/etc/yum/pluginconf.d/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 4
| sort pers_count asc
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("apt", "yum", "dnf")
| stats cc = count(), host_count = count_distinct(host.name) by process.executable
| where host_count <= 5 and cc < 50
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group owner,
datetime(f.atime, 'unixepoch') AS file_last_access time,
datetime(f.mtime, 'unixepoch') AS file last_modified time,
datetime(f.ctime, 'unixepoch') AS file last_status change time,
datetime(f.btime, 'unixepoch') AS file created time,
f.size AS size bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE '/etc/apt/apt.conf.d/%'
OR f.path LIKE '/usr/lib/python%/site-packages/dnf-plugins/%'
OR f.path LIKE '/etc/dnf/plugins/%'
OR f.path LIKE '/usr/lib/yum-plugins/%'
OR f.path LIKE '/etc/yum/pluginconf.d/%'
```
```sql
SELECT * FROM apt_sources
```
```sql
SELECT * FROM yum_sources
```
## Notes
- Monitors for file creation or modification events in directories related to APT, YUM, and DNF package managers such as /etc/apt/apt.conf.d/, /etc/dnf/plugins/, /usr/lib/yum-plugins/, and others.
- Excludes modifications made by expected update processes such as package managers to reduce false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by package managers to detect suspicious activity related to package manager configurations.
- OSQuery queries are provided to retrieve detailed file information related to package manager configurations, as well as sources for APT and YUM.
## MITRE ATT&CK Techniques
- [T1546.004](https://attack.mitre.org/techniques/T1546/004)
- [T1059.004](https://attack.mitre.org/techniques/T1059/004)
## License
- `Elastic License v2`
@@ -0,0 +1,81 @@
# Persistence via rc.local/rc.common
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via rc.local and rc.common on Linux systems. RC scripts are used to start custom applications, services, scripts or commands during start-up. RC scripts have mostly been replaced by Systemd. However, through the "systemd-rc-local-generator", these files can be converted to services that run at boot. The query monitors for file creation or modification events in the /etc/rc.local and /etc/rc.common files, as well as processes started by these scripts. These activities can indicate attempts to establish persistence through rc.local modifications.
- **UUID:** `a95f778f-2193-4a3d-bbbe-7b02d5740638`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [system](https://docs.elastic.co/integrations/system)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (file.path == "/etc/rc.local" or file.path == "/etc/rc.common")
| eval persistence = case(file.path == "/etc/rc.local" or file.path == "/etc/rc.common", process.name, null)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable
| where pers_count > 0 and pers_count <= 3 and agent_count <= 3
| sort pers_count asc
| limit 100
```
```sql
from logs-system.syslog-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and process.name in ("rc.local", "rc.common")
| stats cc = count(), host_count = count_distinct(host.name) by message
| where host_count <= 3 and cc < 10
| sort cc asc
| limit 100
```
```sql
SELECT * FROM systemd_units WHERE id = "rc-local.service"
```
```sql
SELECT * FROM startup_items WHERE name = "rc-local.service"
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path in ('/etc/rc.local', '/etc/rc.common')
```
## Notes
- This hunt includes multiple ES|QL and OSQuery queries to detect potential persistence mechanisms via rc.local on Linux systems.
- Detects file creation or modification events in the /etc/rc.local and /etc/rc.common files, which are used for system initialization scripts.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by rc.local and rc.common scripts to detect potential persistence mechanisms.
- Syslog hunting query is provided to complement the detection by analyzing syslog entries related to rc.local and rc.common processes.
- OSQuery queries are provided to retrieve systemd unit states, startup items, and detailed file information related to rc.local and rc.common.
## MITRE ATT&CK Techniques
- [T1037.004](https://attack.mitre.org/techniques/T1037/004)
- [T1546.003](https://attack.mitre.org/techniques/T1546/003)
## License
- `Elastic License v2`
@@ -0,0 +1,110 @@
# Shell Modification Persistence
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via modifications to shell profile files on Linux systems. It monitors file creation or modification events in system-wide and user-specific profile files, which can indicate attempts to establish persistence through shell modifications. It also monitors processes started by SSH daemons to detect suspicious activity related to SSH logins.
- **UUID:** `20a02fad-2a09-44c0-a8ce-ce4502859c8a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide profile files
file.path in ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout") or
file.path like "/etc/profile.d/*" or
// User-specific profile files
file.path like "/home/*/.profile" or
file.path like "/home/*/.bash_profile" or
file.path like "/home/*/.bash_login" or
file.path like "/home/*/.bash_logout" or
file.path like "/home/*/.bashrc"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "microdnf", "podman", "apk"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide profile files
file.path in ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout") or
file.path like "/etc/profile.d/*" or
// User-specific profile files
file.path like "/home/*/.profile" or
file.path like "/home/*/.bash_profile" or
file.path like "/home/*/.bash_login" or
file.path like "/home/*/.bash_logout" or
file.path like "/home/*/.bashrc",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.parent.name == "sshd"
| stats cc = count(*) by process.command_line
| where cc <= 20
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path IN ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout")
OR f.path LIKE "/etc/profile.d/%"
OR f.path LIKE "/home/%/.profile"
OR f.path LIKE "/home/%/.bash_profile"
OR f.path LIKE "/home/%/.bash_login"
OR f.path LIKE "/home/%/.bash_logout"
OR f.path LIKE "/home/%/.bashrc"
```
## Notes
- Monitors for file creation or modification events in system-wide and user-specific profile files, such as /etc/profile, /etc/bash.bashrc, /home/*/.bashrc, and others.
- Excludes modifications made by expected update processes such as package managers to reduce false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by SSH daemons (sshd) to detect suspicious activity related to SSH logins.
- OSQuery query is provided to retrieve detailed file information related to profile files.
## MITRE ATT&CK Techniques
- [T1546.004](https://attack.mitre.org/techniques/T1546/004)
- [T1053.005](https://attack.mitre.org/techniques/T1053/005)
## License
- `Elastic License v2`
@@ -0,0 +1,68 @@
# Persistence via SSH Configurations and/or Keys
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential SSH persistence mechanisms on Linux systems using OSQuery. It monitors SSH keys, authorized_keys files, SSH configuration files, and SSH file information to detect unauthorized access or persistence techniques. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `aa759db0-4499-42f2-9f2f-be3e00fdebfa`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[SQL]`
## Query
```sql
SELECT * FROM user_ssh_keys
```
```sql
SELECT authorized_keys.*
FROM users
JOIN authorized_keys
USING(uid)
```
```sql
SELECT * FROM ssh_configs
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE "/root/.ssh/%"
OR f.path LIKE "/home/%/.ssh/%"
OR f.path LIKE "/etc/ssh/%"
OR f.path LIKE "/etc/ssh/sshd_config.d/%"
OR f.path LIKE "/etc/ssh/ssh_config.d/%"
```
## Notes
- Monitors SSH keys, authorized_keys files, and SSH configuration files using OSQuery to detect potential unauthorized access or persistence techniques.
- Lists detailed information about SSH files, including paths, owners, and permissions.
- Requires additional data analysis and investigation into results to identify malicious or unauthorized SSH configurations and keys.
## MITRE ATT&CK Techniques
- [T1098.004](https://attack.mitre.org/techniques/T1098/004)
- [T1563.001](https://attack.mitre.org/techniques/T1563/001)
## License
- `Elastic License v2`
@@ -0,0 +1,202 @@
# Persistence via Systemd (Timers)
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via systemd (timers) on Linux systems. It monitors for file creation or modification events related to systemd service and timer configurations, as well as generators, which can indicate attempts to establish persistence through scheduled tasks.
- **UUID:** `d2d24ad6-a315-4e05-a3f9-e205eb805df4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide/user-specific services/timers (root permissions required)
file.path like "/run/systemd/system/*" or
file.path like "/etc/systemd/system/*" or
file.path like "/etc/systemd/user/*" or
file.path like "/usr/local/lib/systemd/system/*" or
file.path like "/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/user/*" or
// user-specific services/timers (user permissions required)
file.path like "/home/*/.config/systemd/user/*" or
file.path like "/home/*/.local/share/systemd/user/*" or
// System-wide generators (root permissions required)
file.path like "/etc/systemd/system-generators/*" or
file.path like "/usr/local/lib/systemd/system-generators/*" or
file.path like "/lib/systemd/system-generators/*" or
file.path like "/etc/systemd/user-generators/*" or
file.path like "/usr/local/lib/systemd/user-generators/*" or
file.path like "/usr/lib/systemd/user-generators/*"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"netplan", "systemd", "generate"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide/user-specific services/timers (root permissions required)
file.path like "/run/systemd/system/*" or
file.path like "/etc/systemd/system/*" or
file.path like "/etc/systemd/user/*" or
file.path like "/usr/local/lib/systemd/system/*" or
file.path like "/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/user/*" or
// user-specific services/timers (user permissions required)
file.path like "/home/*/.config/systemd/user/*" or
file.path like "/home/*/.local/share/systemd/user/*" or
// System-wide generators (root permissions required)
file.path like "/etc/systemd/system-generators/*" or
file.path like "/usr/local/lib/systemd/system-generators/*" or
file.path like "/lib/systemd/system-generators/*" or
file.path like "/etc/systemd/user-generators/*" or
file.path like "/usr/local/lib/systemd/user-generators/*" or
file.path like "/usr/lib/systemd/user-generators/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
(f.path LIKE "/run/systemd/system/%"
OR f.path LIKE "/etc/systemd/system/%"
OR f.path LIKE "/etc/systemd/user/%"
OR f.path LIKE "/usr/local/lib/systemd/system/%"
OR f.path LIKE "/lib/systemd/system/%"
OR f.path LIKE "/usr/lib/systemd/system/%"
OR f.path LIKE "/usr/lib/systemd/user/%"
OR f.path LIKE "/home/%/.config/systemd/user/%"
OR f.path LIKE "/home/%/.local/share/systemd/user/%")
AND f.filename LIKE "%.service"
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/run/systemd/system',
'/etc/systemd/system',
'/etc/systemd/user',
'/usr/local/lib/systemd/system',
'/lib/systemd/system',
'/usr/lib/systemd/system',
'/usr/lib/systemd/user',
'/home/.config/systemd/user',
'/home/.local/share/systemd/user'
)
AND f.filename LIKE "%.timer"
ORDER BY
f.mtime DESC;
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/etc/systemd/system-generators/',
'/usr/local/lib/systemd/system-generators/',
'/lib/systemd/system-generators/',
'/etc/systemd/user-generators/',
'/usr/local/lib/systemd/user-generators/',
'/usr/lib/systemd/user-generators/'
)
ORDER BY
f.mtime DESC;
```
```sql
SELECT name, path, source, status, type FROM startup_items
WHERE type == "systemd unit" AND status == "active" AND
name LIKE "%.service" OR name LIKE "%.timer"
```
## Notes
- This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via systemd timers on Linux systems.
- Detects file creation or modification events in directories and files associated with systemd services, timers, and generators, such as /run/systemd/system, /etc/systemd/system, /etc/systemd/user, and various /usr/lib/systemd directories.
- Excludes common legitimate processes and file types to minimize false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- OSQuery queries are provided to complement the detection by retrieving detailed file information and entries related to systemd services, timers, and generators.
## MITRE ATT&CK Techniques
- [T1053.005](https://attack.mitre.org/techniques/T1053/005)
- [T1546.002](https://attack.mitre.org/techniques/T1546/002)
## License
- `Elastic License v2`
@@ -0,0 +1,99 @@
# Persistence via Udev
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via Udev rules on Linux systems. Udev is a device manager for the Linux kernel that manages device nodes in /dev. Udev is responsible for creating and removing device nodes in /dev when devices are added or removed from the system. Udev executes scripts when devices are added or removed from the system. This query monitors file creation or modification events in Udev rule directories and processes started by Udevadm. These activities can indicate attempts to establish persistence through Udev configurations. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `8d42a644-5b60-4165-a8f1-84d5bcdd4ade`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path like "/etc/udev/rules.d/*" or
file.path like "/run/udev/rules.d/*" or
file.path like "/usr/lib/udev/rules.d/*" or
file.path like "/lib/udev/*"
) and not process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"microdnf", "podman", "apk", "netplan", "generate"
)
| eval persistence = case(
file.path like "/etc/udev/rules.d/*" or
file.path like "/run/udev/rules.d/*" or
file.path like "/usr/lib/udev/rules.d/*" or
file.path like "/lib/udev/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name == "udevadm" and
// Excluding these because this is typical udev behavior.
// If you suspect Udev persistence, remove this exclusion in order to do a more elaborate search
not (process.executable like "/lib/*" or process.executable like "/usr/lib/*")
| stats cc = count(), host_count = count_distinct(host.name) by process.executable
// Tweak the process/host count if you suspect Udev persistence
| where host_count <= 5 and cc < 50
| sort cc asc
| limit 100
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/etc/udev/rules.d/',
'/run/udev/rules.d/',
'/usr/lib/udev/rules.d/',
'/lib/udev/'
)
ORDER BY
f.mtime DESC;
```
## Notes
- Monitors for file creation or modification events in Udev rule directories such as /etc/udev/rules.d/, /run/udev/rules.d/, /usr/lib/udev/rules.d/, and /lib/udev/.
- Excludes modifications made by expected update processes such as package managers to reduce false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by Udevadm to detect suspicious activity related to Udev rules.
- OSQuery query is provided to retrieve detailed file information related to Udev rules.
## MITRE ATT&CK Techniques
- [T1547.010](https://attack.mitre.org/techniques/T1547/010)
## License
- `Elastic License v2`
@@ -0,0 +1,39 @@
# Unusual System Binary Parent (Potential System Binary Hijacking Attempt)
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential system binary hijacking attempts on Linux systems. It monitors process execution events where common system binaries such as ls, cat, mkdir, touch, mv, and cp are the parent processes. These activities can indicate attempts to hijack system binaries for malicious purposes. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `d22cbe8f-c84d-4811-aa6d-f1ee00c806b2`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("ls", "cat", "mkdir", "touch", "mv", "cp")
| stats cc = count(), host_count = count_distinct(host.name) by process.parent.executable, process.executable
| where host_count <= 5
| sort cc asc
| limit 100
```
## Notes
- Monitors process execution events where common system binaries such as ls, cat, mkdir, touch, mv, and cp are the parent processes.
- Focuses on identifying unusual or suspicious child processes spawned by these common system binaries.
- Uses stats to count occurrences and identify unusual activity by looking at the number of unique hosts and processes involved.
- Requires additional data analysis and investigation into results to identify malicious or unauthorized use of system binaries.
## MITRE ATT&CK Techniques
- [T1546.004](https://attack.mitre.org/techniques/T1546/004)
- [T1059.004](https://attack.mitre.org/techniques/T1059/004)
## License
- `Elastic License v2`
@@ -0,0 +1,55 @@
# Privilege Escalation/Persistence via User/Group Creation and/or Modification
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies user and group creation or modification activities on Linux systems using OSQuery. It monitors changes to the shadow file, user and group information, and user processes. These activities can indicate potential unauthorized access or privilege escalation attempts. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `f00c9757-d21b-432c-90a6-8372f18075d0`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[SQL]`
## Query
```sql
SELECT * FROM shadow
```
```sql
SELECT * FROM shadow
WHERE password_status != "locked"
```
```sql
SELECT username, gid, uid, shell, description FROM users
WHERE username != 'root' AND uid LIKE "0"
```
```sql
SELECT * FROM users WHERE username = "newuser"
```
```sql
SELECT * FROM logged_in_users WHERE user = "newuser"
```
```sql
SELECT pid, username, name FROM processes p JOIN users u ON u.uid = p.uid ORDER BY username
```
## Notes
- Monitors changes to the shadow file and user/group information using OSQuery to detect potentially unauthorized access or privilege escalation attempts.
- Lists detailed information about users, including authentication status and running processes.
- Requires additional data analysis and investigation into results to identify malicious or unauthorized user and group modifications.
## MITRE ATT&CK Techniques
- [T1136](https://attack.mitre.org/techniques/T1136)
- [T1136.001](https://attack.mitre.org/techniques/T1136/001)
- [T1136.002](https://attack.mitre.org/techniques/T1136/002)
## License
- `Elastic License v2`
@@ -0,0 +1,134 @@
# XDG Persistence
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via modifications to XDG autostart directories on Linux systems. XDG Autostart entries can be used to execute arbitrary commands or scripts when a user logs in. It monitors file creation or modification events in system-wide, user-specific, and root-specific autostart directories. Additionally, it monitors processes started by common Linux desktop session managers to detect suspicious activity related to autostart entries.
- **UUID:** `8dcc2161-65e0-4448-a03a-1c4e0cbc9330`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
## Query
```sql
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide autostart directories
file.path like "/etc/xdg/autostart/*" or
file.path like "/usr/share/autostart/*" or
// User-specific autostart directories
file.path like "/home/*/.config/autostart/*" or
file.path like "/home/*/.local/share/autostart/*" or
file.path like "/home/*/.config/autostart-scripts/*" or
// Root-specific autostart directories
file.path like "/root/.config/autostart/*" or
file.path like "/root/.local/share/autostart/*" or
file.path like "/root/.config/autostart-scripts/*"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "microdnf", "podman", "apk"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide autostart directories
file.path like "/etc/xdg/autostart/*" or
file.path like "/usr/share/autostart/*" or
// User-specific autostart directories
file.path like "/home/*/.config/autostart/*" or
file.path like "/home/*/.local/share/autostart/*" or
file.path like "/home/*/.config/autostart-scripts/*" or
// Root-specific autostart directories
file.path like "/root/.config/autostart/*" or
file.path like "/root/.local/share/autostart/*" or
file.path like "/root/.config/autostart-scripts/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.parent.name in (
"plasmashell", "gnome-session", "xfce4-session", "gnome-session-binary", "mate-session", "cinnamon-session",
"lxsession", "lxqt-session", "unity-session", "pantheon-session", "enlightenment_start"
)
| stats cc = count(*) by process.command_line, process.parent.executable
| where cc <= 20
| sort cc asc
| limit 100
```
```sql
SELECT name, path, source, status, type FROM startup_items
WHERE type == "Startup Item" AND status == "enabled" AND (
source LIKE "/etc/xdg/autostart/%"
OR source LIKE "/usr/share/autostart/%"
OR source LIKE "/home/%/.config/autostart/%"
OR source LIKE "/home/%/.local/share/autostart/%"
OR source LIKE "/home/%/.config/autostart-scripts/%"
OR source LIKE "/root/.config/autostart/%"
OR source LIKE "/root/.local/share/autostart/%"
OR source LIKE "/root/.config/autostart-scripts/%"
)
```
```sql
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE "/etc/xdg/autostart/%"
OR f.path LIKE "/usr/share/autostart/%"
OR f.path LIKE "/home/%/.config/autostart/%"
OR f.path LIKE "/home/%/.local/share/autostart/%"
OR f.path LIKE "/home/%/.config/autostart-scripts/%"
OR f.path LIKE "/root/.config/autostart/%"
OR f.path LIKE "/root/.local/share/autostart/%"
OR f.path LIKE "/root/.config/autostart-scripts/%"
```
## Notes
- Monitors for file creation or modification events in system-wide, user-specific, and root-specific XDG autostart directories.
- Excludes modifications made by expected update processes such as package managers to reduce false positives.
- Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.
- Monitors processes started by common Linux desktop session managers to detect suspicious activity related to autostart entries.
- OSQuery queries are provided to retrieve enabled XDG startup items and detailed file information related to autostart directories.
## MITRE ATT&CK Techniques
- [T1547.001](https://attack.mitre.org/techniques/T1547/001)
- [T1053.005](https://attack.mitre.org/techniques/T1053/005)
## License
- `Elastic License v2`
@@ -0,0 +1,31 @@
# Privilege Escalation Identification via Existing Sudoers File
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies entries in the sudoers file on Linux systems using OSQuery. The sudoers file controls which users have administrative privileges and can be a target for attackers seeking to escalate their privileges. This hunt lists all sudoers rules for further analysis.
- **UUID:** `6e57e6a6-f150-405d-b8be-e4e666a3a86d`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[SQL]`
## Query
```sql
SELECT * FROM sudoers
```
## Notes
- Lists all entries in the sudoers file using OSQuery to detect potentially unauthorized or suspicious rules.
- Requires additional data analysis and investigation into results to identify malicious or misconfigured sudoers entries.
- Focuses on monitoring and analyzing administrative privileges granted through the sudoers file.
## MITRE ATT&CK Techniques
- [T1548.003](https://attack.mitre.org/techniques/T1548/003)
## License
- `Elastic License v2`
@@ -0,0 +1,59 @@
# Process Capability Hunting
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies processes on Linux systems with specific capabilities set. It monitors process execution events where processes have effective or permitted capabilities, which can be indicative of elevated privileges. The hunt focuses on non-root users to detect potential privilege escalation attempts. The hunt lists detailed information for further analysis and investigation.
- **UUID:** `6f67704d-e5b1-4613-912c-e2965660fe17`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and (process.thread.capabilities.effective is not null or process.thread.capabilities.permitted is not null) and user.id != "0" and
not (
// Remove these if you expect persistence through capabilities
process.executable like "/var/lib/docker/*" or
process.name == "gnome-keyring-daemon" or
process.thread.capabilities.permitted == "CAP_WAKE_ALARM"
)
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.thread.capabilities.effective, process.thread.capabilities.permitted
| where host_count <= 3 and cc < 5
| sort cc asc
| limit 100
```
```sql
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and (
process.thread.capabilities.effective in ("CAP_SYS_MODULE", "CAP_SYS_PTRACE", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_SETUID", "CAP_SETGID", "CAP_SYS_ADMIN") or
process.thread.capabilities.permitted in ("CAP_SYS_MODULE", "CAP_SYS_PTRACE", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_SETUID", "CAP_SETGID", "CAP_SYS_ADMIN")
) and user.id != "0"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.thread.capabilities.effective, process.thread.capabilities.permitted
| where host_count <= 3 and cc < 5
| sort cc asc
| limit 100
```
## Notes
- Monitors process execution events where processes have specific capabilities set, such as CAP_SYS_MODULE, CAP_SYS_PTRACE, and others.
- Excludes certain processes and capabilities to reduce false positives, but these can be adjusted based on your environment.
- Uses EVAL to tag potential privilege escalation events and counts occurrences to identify unusual activity.
- Focuses on non-root users to detect potential privilege escalation attempts.
- Requires additional data analysis and investigation into results to identify malicious or unauthorized use of process capabilities.
## MITRE ATT&CK Techniques
- [T1548.001](https://attack.mitre.org/techniques/T1548/001)
- [T1548.003](https://attack.mitre.org/techniques/T1548/003)
## License
- `Elastic License v2`
@@ -0,0 +1,51 @@
# Segmentation Fault & Potential Buffer Overflow Hunting
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies segmentation faults (segfaults) and potential buffer overflow attacks on Linux systems by parsing syslog messages related to segfaults. It captures details about the crashing process, shared object file, and other relevant information to help identify and investigate potential exploitation attempts.
- **UUID:** `3f3fd2b9-940c-4310-adb1-d8b7d726e281`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `[ES|QL]`
## Query
```sql
from logs-system.syslog*
| where @timestamp > now() - 12 hour
| where host.os.type == "linux" and process.name == "kernel" and message like "*segfault*"
| grok message "\\[%{NUMBER:timestamp}\\] %{WORD:process}\\[%{NUMBER:pid}\\]: segfault at %{BASE16NUM:segfault_address} ip %{BASE16NUM:instruction_pointer} sp %{BASE16NUM:stack_pointer} error %{NUMBER:error_code} in %{DATA:so_file}\\[%{BASE16NUM:so_base_address}\\+%{BASE16NUM:so_offset}\\]"
| keep timestamp, process, pid, so_file, segfault_address, instruction_pointer, stack_pointer, error_code, so_base_address, so_offset
```
```sql
from logs-system.syslog*
| where host.os.type == "linux" and process.name == "kernel" and message like "*segfault*"
| where @timestamp > now() - 12 hour
| grok message "\\[%{DATA:timestamp}\\] %{WORD:process}\\[%{NUMBER:pid}\\]: segfault at %{BASE16NUM:segfault_address} ip %{BASE16NUM:instruction_pointer} sp %{BASE16NUM:stack_pointer} error %{NUMBER:error_code} in %{DATA:so_name}\\[%{BASE16NUM:so_base_address}\\+%{BASE16NUM:so_offset}\\] likely on CPU %{NUMBER:cpu} \\(core %{NUMBER:core}, socket %{NUMBER:socket}\\)"
| eval timestamp = REPLACE(timestamp, "\\s+", "")
| keep timestamp, process, pid, segfault_address, instruction_pointer, stack_pointer, error_code, so_name, so_base_address, so_offset, cpu, core, socket
| stats cc = count() by process, so_name
// Alter this threshold to make sense for your environment
| where cc > 100
| limit 10
```
## Notes
- Detects segfaults and parses syslog messages related to segfaults to identify the crashing process and shared object file along with additional crash details.
- Uses GROK to extract relevant fields from syslog messages.
- Counts occurrences of segfaults within a plain text message field to potentially detect buffer overflow attacks and unsuccessful process injection attempts.
- Removes prepending spaces from syslog messages using EVAL to ensure consistent parsing.
- Depending on the Syslog configuration, additional parsing may be required to extract the necessary fields from the message.
## MITRE ATT&CK Techniques
- [T1203](https://attack.mitre.org/techniques/T1203)
- [T1068](https://attack.mitre.org/techniques/T1068)
## License
- `Elastic License v2`
@@ -0,0 +1,66 @@
# OSQuery SUID Hunting
---
## Metadata
- **Author:** Elastic
- **Description:** This hunt identifies SUID binaries on Linux systems using OSQuery. SUID binaries can be exploited by attackers to gain elevated privileges. The hunt includes queries to list all SUID binaries and detailed information about these files, focusing on regular files owned by root with SUID or SGID bits set.
- **UUID:** `2db642d2-621a-4183-88b5-b2659dc2c940`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[SQL]`
## Query
```sql
SELECT * FROM suid_bin
```
```sql
SELECT
f.filename,
f.path,
f.mode,
f.uid,
f.gid,
f.type,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.type == "regular" AND
(f.uid == 0 or f.gid == 0) AND
(f.mode LIKE "2%" OR f.mode LIKE "4%") AND
(
f.path LIKE "/%%" OR
f.path LIKE "/%%/%%" OR
f.path LIKE "/%%/%%/%%" OR
f.path LIKE "/%%/%%/%%/%%"
)
```
## Notes
- Identifies SUID binaries using OSQuery to detect potentially exploitable files with SUID or SGID bits set.
- Lists all SUID binaries and provides detailed information about these files, including their paths, owners, and permissions.
- Focuses on regular files owned by root with SUID or SGID bits set to identify potential privilege escalation vectors.
- OSQuery has limited support for wildcard queries, therefore the query includes multiple LIKE conditions for directories. These can be increased and decreased, based on the environment
## MITRE ATT&CK Techniques
- [T1548.001](https://attack.mitre.org/techniques/T1548/001)
- [T1574.002](https://attack.mitre.org/techniques/T1574/002)
## License
- `Elastic License v2`
@@ -0,0 +1,66 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies network connections with low occurrence frequency for unique agent IDs on Linux systems. It monitors network connection attempts and acceptances, focusing on those initiated by processes that are rarely seen in the environment. By accounting for known low-frequency legitimate binaries (LoLBins) and suspicious directories, this hunt aims to detect unusual network activity that may indicate malicious behavior.
"""
integration = ["endpoint"]
uuid = "ecd84bc7-32ae-474b-93a8-d1d9736c3464"
name = "Network Connections with Low Occurrence Frequency for Unique Agent ID"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for network connections initiated by processes that have low occurrence frequency, focusing on unique agent IDs.",
"Excludes common internal IP ranges to minimize false positives.",
"Accounts for known low-frequency legitimate binaries (LoLBins) to reduce noise.",
"Identifies suspicious directories where processes are executed from, which can indicate malicious activity."
]
mitre = ["T1071.001", "T1071.004"]
query = [
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable
| where agent_count == 1 and cc > 0 and cc <= 3
| limit 100
| sort cc asc
''',
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and (
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish", "socat", "java", "awk", "gawk", "mawk", "nawk", "openssl", "nc", "ncat", "netcat", "nc.openbsd", "telnet") or
process.name like "python*" or
process.name like "perl*" or
process.name like "ruby*" or
process.name like "lua*" or
process.name like "php*"
) and
destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.name
| where agent_count <= 3 and cc > 0 and cc <= 5
| limit 100
| sort cc asc
''',
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action in ("connection_attempted", "connection_accepted") and (
process.executable like "./*" or
process.executable like "/dev/shm/*" or
process.executable like "/var/www/*" or
process.executable like "/boot/*" or
process.executable like "/srv/*" or
process.executable rlike "/tmp/[^/]+" or
process.executable rlike "/var/tmp/[^/]+" or
process.executable rlike "/run/[^/]+" or
process.executable rlike "/var/run/[^/]+"
) and
destination.ip IS NOT null and not CIDR_MATCH(destination.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable
| where agent_count <= 3 and cc > 0 and cc <= 5
| limit 100
| sort cc asc
'''
]
@@ -0,0 +1,29 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies unusual file download activities on Linux systems. It detects instances where commonly used download utilities such as curl and wget are executed with command lines that contain IP addresses, which can indicate potentially suspicious file downloads.
"""
integration = ["endpoint"]
uuid = "0d061fad-cf35-43a6-b9b7-986c348bf182"
name = "Unusual File Downloads from Source Addresses"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Detects instances where download utilities like curl and wget are used with IP addresses in their command lines.",
"Monitors for potentially suspicious file downloads, which are often seen in malicious activities.",
"Uses process command line counting in conjunction with host counting to minimize false positives caused by legitimate downloads.",
"The process command line count threshold is set to <= 10, and the host count threshold is set to <= 5 to balance detection and noise."
]
mitre = ["T1071.001", "T1071.004"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and process.name in ("curl", "wget") and process.command_line rlike """.*[0-9]{1,3}(\.[0-9]{1,3}){3}.*"""
| stats cc = count(), host_count = count_distinct(host.id) by process.command_line, process.executable
| where cc <= 10 and host_count <= 5
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,31 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential defense evasion techniques via capitalized process execution on Linux systems. It detects processes that have two or more consecutive capital letters within their names, which can indicate an attempt to evade detection. Such naming conventions are often used in malicious payloads to blend in with legitimate processes.
"""
integration = ["endpoint"]
uuid = "9d485892-1ca2-464b-9e4e-6b21ab379b9a"
name = "Defense Evasion via Capitalized Process Execution"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Detects processes that have two or more consecutive capital letters within their names, with optional digits.",
"This technique is often used in malicious payloads, such as Metasploit payloads, to evade detection.",
"Included a process count of <= 3 and a host count of <= 3 to eliminate common processes across different hosts."
]
mitre = ["T1036.004", "T1070"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 10 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
(process.name rlike """[A-Z]{2,}[a-z]{1,}[0-9]{0,}""") or
(process.name rlike """[A-Z]{1,}[0-9]{0,}""")
)
| stats cc = count(), host_count = count_distinct(host.name) by process.name
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| limit 100
'''
]
@@ -0,0 +1,29 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies hidden process executions on Linux systems. It detects processes executed from hidden files, which are often used by malicious actors to conceal their activities. By focusing on hidden files rather than directories, this hunt aims to catch stealthy processes while minimizing noise.
"""
integration = ["endpoint"]
uuid = "00461198-9a2d-4823-b4cc-f3d1b5c17935"
name = "Hidden Process Execution"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Included only hidden files, excluding hidden directories, as hidden directories are common in Unix.",
"Included a process or parent process count of <= 3, and a host count of <= 3 to eliminate common processes across different hosts.",
]
mitre = ["T1036.004", "T1059"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and
process.executable rlike "/[^/]+/\\.[^/]+"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable, user.id
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,28 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential defense evasion techniques via multi-dot process execution on Linux systems. It looks for processes with executables that contain three or more consecutive dots in their names. Such naming conventions can be used by malicious actors to evade detection and blend in with legitimate processes.
"""
integration = ["endpoint"]
uuid = "11810497-8ce3-4960-9777-9d0e97052682"
name = "Potential Defense Evasion via Multi-Dot Process Execution"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"This query identifies processes with executables containing three or more consecutive dots in their names.",
"The process count threshold of <= 10 can be adjusted based on the environment's baseline activity."
]
mitre = ["T1036.004", "T1070"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.executable rlike """.*\.{3,}.*"""
| stats cc = count() by process.executable
// Alter this threshold to make sense for your environment
| where cc <= 10
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,30 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies excessive SSH network activity to unique destinations on Linux systems. It monitors network connections over TCP to port 22 (SSH) and counts the number of unique destination IP addresses. A high number of unique destinations could indicate suspicious activity such as discovery or lateral movement.
"""
integration = ["endpoint"]
uuid = "223f812c-a962-4d58-961d-134d8f8b15da"
name = "Excessive SSH Network Activity to Unique Destinations"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors network connections to port 22 (SSH) and counts the number of unique destination IP addresses per host and user.",
"A high number of unique destinations can indicate suspicious activity such as discovery or lateral movement.",
"The threshold of 10 unique destinations can be adjusted to suit the environment's baseline activity."
]
mitre = ["T1021.004", "T1078.003"]
query = [
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "network" and network.transport == "tcp" and destination.port == 22 and source.port >= 49152
| keep destination.ip, host.id, user.name
| stats count_unique_dst = count_distinct(destination.ip) by host.id, user.name
// Alter this threshold to make sense for your environment
| where count_unique_dst >= 10
| limit 100
| sort user.name asc
'''
]
@@ -0,0 +1,47 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies uncommon process executions from suspicious directories on Linux systems. It looks for processes executed from directories that are often associated with malicious activity, such as /dev/shm, /var/www, /boot, /srv, /tmp, /var/tmp, /run, and /var/run. The goal is to detect potentially malicious processes while excluding common, benign ones.
"""
integration = ["endpoint"]
uuid = "0ea47044-b161-4785-ba99-e11f46d6ac51"
name = "Uncommon Process Execution from Suspicious Directory"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Excluded /tmp, /var/tmp, /run, /var/run subdirectories to reduce noise.",
"Excluded /tmp, /var/tmp files starting or ending with digits to exclude real temporary files.",
"Included a process or parent process count of <= 3, and a host count of <= 3 to eliminate common processes across different hosts.",
]
mitre = ["T1036.004", "T1049", "T1059", "T1059.004"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and (
// Add paths to monitor from your environment here
process.executable like "/dev/shm/*" or
process.executable like "/var/www/*" or
process.executable like "/boot/*" or
process.executable like "/srv/*" or
process.executable rlike "/tmp/[^/]+" or
process.executable rlike "/var/tmp/[^/]+" or
process.executable rlike "/run/[^/]+" or
process.executable rlike "/var/run/[^/]+"
) and not (
// Exclude noisy (parent) processes, users or directories from your environment here
process.parent.executable in ("/usr/sbin/dpkg-preconfigure") or
// Exclude /tmp and /var/tmp instances starting or ending with digits (usually benign files)
process.executable rlike "/tmp/[0-9].*" or
process.executable rlike "/tmp/.*[0-9]/?" or
process.executable rlike "/var/tmp/[0-9].*" or
process.executable rlike "/var/tmp/.*[0-9]/?"
)
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable
// Alter this threshold to make sense for your environment
| where cc <= 3 and host_count <= 3
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,29 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies unusual logon activity by source IP on Linux systems. It monitors authentication events, focusing on failed logon attempts from specific IP addresses. A high number of failed logon attempts combined with a low number of successful logons and multiple distinct usernames can indicate a potential brute force or credential stuffing attack.
"""
integration = ["endpoint"]
uuid = "95c1467d-d566-4645-b5f1-37a4b0093bb6"
name = "Logon Activity by Source IP"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors authentication events and counts failed and successful logon attempts by source IP address.",
"A high number of failed logon attempts combined with a low number of successful logons and multiple distinct usernames can indicate a potential brute force or credential stuffing attack.",
"The thresholds for failed attempts, successful logons, and distinct usernames should be adjusted based on the environment's normal logon patterns."
]
mitre = ["T1110", "T1078"]
query = [
'''
from logs-system.auth-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "authentication" and event.action in ("ssh_login", "user_login") and
event.outcome == "failure" and source.ip IS NOT null and not CIDR_MATCH(source.ip, "127.0.0.0/8", "169.254.0.0/16", "224.0.0.0/4", "::1")
| eval failed = case(event.outcome == "failure", source.ip, null), success = case(event.outcome == "success", source.ip, null)
| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.name) by source.ip
/* below threshold should be adjusted to your env logon patterns */
| where count_failed >= 100 and count_success <= 10 and count_user >= 20
'''
]
@@ -0,0 +1,39 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies low volume external network connections initiated by processes on Linux systems. It focuses on connections attempted by processes that have been seen infrequently (five or fewer connections) and by unique agents. This can help identify potentially suspicious activity that might be missed due to low volume.
"""
integration = ["endpoint"]
uuid = "12526f14-5e35-4f5f-884c-96c6a353a544"
name = "Low Volume External Network Connections from Process by Unique Agent"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for network connections attempted by processes that have a low occurrence frequency (five or fewer connections) and are seen by a unique agent.",
"Excludes common internal IP ranges to minimize false positives.",
"A separate query is included to specifically monitor low volume network connections initiated by the root user, as these can be particularly indicative of malicious activity."
]
mitre = ["T1071.001", "T1071.004"]
query = [
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "network" and event.type == "start" and event.action == "connection_attempted" and not process.name is null 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")
| stats connection_count = count(*), unique_agent_count = count_distinct(agent.id) by process.name
| where connection_count <= 5 and unique_agent_count == 1
| limit 100
| sort connection_count, unique_agent_count asc
''',
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.category == "network" and event.type == "start" and event.action == "connection_attempted" and user.id == "0" and not process.name is null 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")
| stats connection_count = count(*), unique_agent_count = count_distinct(agent.id) by process.name
| where connection_count <= 5 and unique_agent_count == 1
| limit 100
| sort connection_count, unique_agent_count asc
'''
]
@@ -0,0 +1,36 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies low volume external network connections initiated by GTFOBins on Linux systems. GTFOBins are Unix binaries that can be exploited by attackers to bypass local security restrictions. The hunt focuses on network connections made by these binaries, excluding common internal IP ranges, to detect potentially malicious activity.
"""
integration = ["endpoint"]
uuid = "783d6091-b98d-45a8-a880-a07f112a8aa2"
name = "Low Volume GTFOBins External Network Connections"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for external network connections initiated by known GTFOBins such as bash, curl, nc, wget, and others.",
"Excludes common internal IP ranges to minimize false positives.",
"Counts the occurrences of these connections by process name and limits to those seen infrequently (five or fewer connections).",
"This can help identify potentially malicious activity involving the exploitation of GTFOBins."
]
mitre = ["T1219", "T1071.001"]
query = [
'''
from logs-endpoint.events.network-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and event.type == "start" and process.name in (
"ab", "aria2c", "bash", "cpan", "curl", "easy_install", "finger", "ftp",
"gdb", "gimp", "irb", "jjs", "jrunscript", "julia", "ksh", "lua", "lwp-download",
"nc", "nmap", "node", "openssl", "php", "pip", "python", "ruby", "rview", "rvim",
"scp", "sftp", "smbclient", "socat", "ssh", "tar", "tftp", "view", "vim", "vimdiff",
"wget", "whois", "yum"
) and
destination.ip IS NOT null 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", "224.0.0.0/4", "240.0.0.0/4", "::1","FE80::/10", "FF00::/8")
| keep process.name, destination.port, destination.ip, user.name, host.name
| stats cc = count(*) by destination.port, process.name
| where cc <= 5
| sort cc asc, destination.port
'''
]
@@ -0,0 +1,39 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies low volume modifications to critical system binaries on Linux systems. It monitors file modification events in critical directories such as /bin, /usr/bin, /sbin, and /usr/sbin. The hunt focuses on modifications made by unique hosts, excluding expected update processes like package managers. This can help detect unauthorized or suspicious modifications to system binaries.
"""
integration = ["endpoint"]
uuid = "c7044817-d9a5-4755-abab-9059e50dab24"
name = "Low Volume Modifications to Critical System Binaries by Unique Host"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for file modifications in critical directories like /bin, /usr/bin, /sbin, and /usr/sbin.",
"Excludes modifications made by expected update processes such as package managers to reduce false positives.",
"Counts the number of unique files modified by each host and the number of modifications made.",
"Focuses on modifications made by unique hosts to detect unauthorized or suspicious changes."
]
mitre = ["T1070.004", "T1569.002"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 7 day
| where host.os.type == "linux" and
(file.path like "/bin/*" or file.path like "/usr/bin/*" or file.path like "/sbin/*" or file.path like "/usr/sbin/*") and
not (
// Exclude expected update processes, e.g., package managers
process.executable in ("/usr/bin/apt", "/usr/bin/dpkg", "/usr/bin/yum", "/usr/bin/rpm", "/usr/bin/pacman",
"/usr/bin/pamac-daemon", "/usr/bin/update-alternatives", "/usr/bin/dockerd", "/usr/bin/microdnf", "/sbin/apk") or
// Exclude certain benign or expected modification patterns, if applicable
file.path like "/usr/bin/gzip*" // Example exclusion, adjust based on your environment
)
| stats modification_count = count(file.path), unique_files_modified = count_distinct(file.path), host_count = count_distinct(host.name) by process.executable
| where modification_count >= 1 and host_count == 1
| sort modification_count asc
| limit 100
'''
]
@@ -0,0 +1,28 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies low volume process injection-related syscalls on Linux systems. It monitors audit logs for syscalls related to process injection, such as ptrace and memfd_create. The hunt focuses on processes that make these syscalls infrequently, which can indicate potential malicious activity.
"""
integration = ["endpoint"]
uuid = "c9931736-d5ec-4c89-b4d2-d71dcf5ca12a"
name = "Low Volume Process Injection-Related Syscalls by Process Executable"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for process injection-related syscalls such as ptrace and memfd_create.",
"Counts the occurrences of these syscalls by process executable to identify processes that make these syscalls infrequently.",
"Focuses on low volume occurrences to detect potential malicious activity related to process injection."
]
mitre = ["T1055.001", "T1055.009"]
query = [
'''
from logs-auditd_manager.auditd-*, logs-auditd.log-*, auditbeat-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and auditd.data.syscall in ("ptrace", "memfd_create")
| stats cc = count(*) by process.executable, auditd.data.syscall
| where cc <= 10
| limit 100
| sort cc asc
'''
]
@@ -0,0 +1,47 @@
[hunt]
author = "Elastic"
description = """
This hunt provides several OSQuery queries that can aid in the detection of reverse/bind shells. Reverse shells are a type of shell in which the target machine communicates back to the attacking machine. Bind shells are a type of shell in which the target machine opens a communication port on the victim machine and waits for an attacker to connect to it. These shells can be used by attackers to gain remote access to a system.
"""
integration = ["endpoint"]
uuid = "7422faf1-ba51-49c3-b8ba-13759e6bcec4"
name = "Persistence Through Reverse/Bind Shells"
language = ["SQL"]
license = "Elastic License v2"
notes = [
"The hunt provides OSQuery queries to detect reverse/bind shells on Linux systems.",
"The first hunt query retrieves information about open sockets on the system.",
"The second hunt query retrieves information about running processes on the system.",
"The third hunt query retrieves information about listening ports on the system.",
"Investigate strange or unexpected open sockets, processes, or listening ports on the system.",
"Use the information from each hunt to pivot and investigate further for potential reverse/bind shells."
]
mitre = ["T1059.004"]
query = [
'''
SELECT (
CASE family
WHEN 2 THEN 'IP4'
WHEN 10 THEN 'IP6'
ELSE family END
) AS family, (
CASE protocol
WHEN 6 THEN 'TCP'
WHEN 17 THEN 'UDP'
ELSE protocol END
) AS protocol, local_address, local_port,
remote_address, remote_port
FROM process_open_sockets
WHERE family IN (2, 10)
AND protocol IN (6, 17)
''',
'''
SELECT cmdline, name, path, pid, state, threads, total_size
FROM processes
WHERE cmdline != ''
''',
'''
SELECT pid, address, port, socket, protocol, path FROM listening_ports
'''
]
@@ -0,0 +1,98 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via cron on Linux systems. It monitors for file creation or modification events related to cron configurations and processes spawned by cron, fcron, or atd. These activities can indicate attempts to establish persistence through scheduled tasks.
"""
integration = ["endpoint"]
uuid = "e1cffb7c-4acf-4e7a-8d72-b8b7657cf7b8"
name = "Persistence via Cron"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via cron on Linux systems.",
"Detects file creation or modification events in directories and files associated with cron configurations, such as /etc/cron.allow, /etc/cron.deny, /etc/crontab, all /etc/cron.* directories and various /var/spool directories.",
"Excludes common legitimate processes and file types to minimize false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by cron, fcron, or atd to detect potential persistence mechanisms.",
"OSQuery queries are provided to complement the detection by retrieving detailed file information and crontab entries."
]
mitre = ["T1053.003", "T1053.005"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path in ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab") or
file.path like "/etc/cron.*/*" or
file.path like "/var/spool/cron/crontabs/*" or
file.path like "/var/spool/anacron/*" or
file.path like "/var/spool/cron/atjobs/*" or
file.path like "/var/spool/fcron/*" or
file.path like "/home/*/.tsp/*"
) and not (
process.name in ("dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "anacron") or
file.extension in ("dpkg-remove", "swx", "swp") or
file.name like "tmp.*"
)
| eval persistence = case(
file.path in ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab") or
file.path like "/etc/cron.*/*" or
file.path like "/var/spool/cron/crontabs/*" or
file.path like "/var/spool/anacron/*" or
file.path like "/var/spool/cron/atjobs/*" or
file.path like "/var/spool/fcron/*" or
file.path like "/home/*/.tsp/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 3
| sort pers_count asc
| limit 100
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("cron", "fcron", "atd")
| stats cc = count(), host_count = count_distinct(host.id) by process.command_line
| where host_count <= 3
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path IN ("/etc/cron.allow", "/etc/cron.deny", "/etc/crontab")
OR f.path LIKE "/etc/cron.%/*"
OR f.path LIKE "/var/spool/cron/crontabs/%"
OR f.path LIKE "/var/spool/anacron/%"
OR f.path LIKE "/var/spool/cron/atjobs/%"
OR f.path LIKE "/var/spool/fcron/%"
OR f.path LIKE "/home/%/.tsp/%"
OR f.path LIKE "/etc/cron.allow.d/%"
OR f.path LIKE "/etc/cron.d/%"
OR f.path LIKE "/etc/cron.hourly/%"
OR f.path LIKE "/etc/cron.daily/%"
OR f.path LIKE "/etc/cron.weekly/%"
OR f.path LIKE "/etc/cron.monthly/%"
''',
'''
SELECT * FROM crontab
'''
]
@@ -0,0 +1,29 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies drivers loaded with low occurrence frequency on Linux systems. It monitors for the loading of kernel modules (drivers) that have only been seen once across a single host within a year. Such activity can indicate the presence of rare or potentially malicious drivers.
"""
integration = ["endpoint"]
uuid = "e1f59c9a-7a2a-4eb8-a524-97b16a041a4a"
name = "Drivers Load with Low Occurrence Frequency"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors for kernel modules loaded with syscall 'init_module' or 'finit_module', indicating driver load events.",
"Counts the occurrence of each driver across all hosts and identifies those seen only once on a single host within the past year.",
"Such rare driver loads can indicate potentially malicious activity or the presence of uncommon drivers."
]
mitre = ["T1547.006", "T1069.002"]
query = [
'''
from logs-auditd_manager.auditd-*, logs-auditd.log-*, auditbeat-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.category == "driver" and event.action == "loaded-kernel-module" and auditd.data.syscall in ("init_module", "finit_module")
| stats host_count = count_distinct(host.id), total_count = count(*) by auditd.data.name, process.executable, process.name
// Alter this threshold to make sense for your environment
| where host_count == 1 and total_count == 1
| limit 100
| sort auditd.data.name asc
'''
]
@@ -0,0 +1,78 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via Git hooks and configurations on Linux systems. It monitors file creation or modification events in Git configuration and hook directories, as well as processes started by Git hooks. These activities can indicate attempts to establish persistence through Git configurations. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "2d7bb29d-d53f-47ab-a0b4-1818adb91423"
name = "Git Hook/Pager Persistence"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"Monitors for file creation or modification events in Git configuration and hook directories such as /etc/gitconfig, .git/config, /home/*/.gitconfig, and .git/hooks/.",
"Excludes modifications made by the Git process itself to reduce false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by Git hooks to detect suspicious activity related to Git configurations.",
"OSQuery query is provided to retrieve detailed file information related to Git configurations and hooks.",
"OSQuery has limited support for wildcard queries, therefore the query includes multiple LIKE conditions for directories. These can be increased and decreased based on the environment's Git configuration paths."
]
mitre = ["T1546.004", "T1059.004"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path == "/etc/gitconfig" or
file.path like "*/.git/config" or
file.path like "/home/*/.gitconfig" or
file.path like "*/.git/hooks/*"
) and process.name != "git"
| eval persistence = case(
file.path == "/etc/gitconfig" or
file.path like "*/.git/config" or
file.path like "/home/*/.gitconfig" or
file.path like "*/.git/hooks/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 4
| sort pers_count asc
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.executable like "*.git/hooks/*"
| stats cc = count(), host_count = count_distinct(host.name) by process.parent.executable, process.executable
| where cc < 50 and host_count <= 5
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change time,
datetime(f.btime, 'unixepoch') AS file created time,
f.size AS size bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path == '/etc/gitconfig'
OR f.path LIKE '/%%/.git/config'
OR f.path LIKE '/home/%/.gitconfig'
OR f.path LIKE '/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/%%/.git/hooks/%'
OR f.path LIKE '/%%/%%/%%/%%/.git/hooks/%'
'''
]
@@ -0,0 +1,68 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via the message-of-the-day (motd) on Linux systems. It monitors for file creation or modification events in the /etc/update-motd.d directory and processes started by these motd scripts. These scripts launch on SSH/terminal connection events, and execute the scripts as root. These activities can indicate attempts to establish persistence through motd modifications.
"""
integration = ["endpoint"]
uuid = "5984a354-d76c-43e6-bdd9-228456f1b371"
name = "Persistence via Message-of-the-Day"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via the message-of-the-day (motd) on Linux systems.",
"Detects file creation or modification events in the /etc/update-motd.d directory, which is used for message-of-the-day scripts.",
"Excludes common legitimate processes to minimize false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by motd scripts to detect potential persistence mechanisms.",
"OSQuery query is provided to complement the detection by retrieving detailed file information related to motd scripts."
]
mitre = ["T1036.005", "T1546.003"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and file.path like "/etc/update-motd.d/*" and
not process.name in ("dpkg", "dockerd", "yum", "dnf", "snapd", "pacman")
| eval persistence = case(file.path like "/etc/update-motd.d/*", process.name, null)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 5
| sort pers_count asc
| limit 100
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.executable like "/etc/update-motd.d/*" and
not process.args like "/tmp/tmp.*"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.parent.executable
| where host_count <= 5
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN ('/etc/update-motd.d/')
ORDER BY
f.mtime DESC;
'''
]
@@ -0,0 +1,86 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via package manager configurations on Linux systems. It monitors file creation or modification events in directories related to APT, YUM, and DNF package managers. Additionally, it monitors processes started by these package managers. These activities can indicate attempts to establish persistence through package manager configurations. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "2d01a413-8d97-407a-8698-02dfc7119c97"
name = "Persistence via Packager Manager"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"Monitors for file creation or modification events in directories related to APT, YUM, and DNF package managers such as /etc/apt/apt.conf.d/, /etc/dnf/plugins/, /usr/lib/yum-plugins/, and others.",
"Excludes modifications made by expected update processes such as package managers to reduce false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by package managers to detect suspicious activity related to package manager configurations.",
"OSQuery queries are provided to retrieve detailed file information related to package manager configurations, as well as sources for APT and YUM."
]
mitre = ["T1546.004", "T1059.004"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path like "/etc/apt/apt.conf.d/*" or
file.path like "/usr/lib/python*/site-packages/dnf-plugins/*" or
file.path like "/etc/dnf/plugins/*" or
file.path like "/usr/lib/yum-plugins/*" or
file.path like "/etc/yum/pluginconf.d/*"
) and not process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"microdnf", "podman", "apk", "yumBackend.py"
)
| eval persistence = case(
file.path like "/etc/apt/apt.conf.d/*" or
file.path like "/usr/lib/python*/site-packages/dnf-plugins/*" or
file.path like "/etc/dnf/plugins/*" or
file.path like "/usr/lib/yum-plugins/*" or
file.path like "/etc/yum/pluginconf.d/*",
process.name,
null
)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20 and agent_count <= 4
| sort pers_count asc
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("apt", "yum", "dnf")
| stats cc = count(), host_count = count_distinct(host.name) by process.executable
| where host_count <= 5 and cc < 50
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group owner,
datetime(f.atime, 'unixepoch') AS file_last_access time,
datetime(f.mtime, 'unixepoch') AS file last_modified time,
datetime(f.ctime, 'unixepoch') AS file last_status change time,
datetime(f.btime, 'unixepoch') AS file created time,
f.size AS size bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE '/etc/apt/apt.conf.d/%'
OR f.path LIKE '/usr/lib/python%/site-packages/dnf-plugins/%'
OR f.path LIKE '/etc/dnf/plugins/%'
OR f.path LIKE '/usr/lib/yum-plugins/%'
OR f.path LIKE '/etc/yum/pluginconf.d/%'
''',
'''
SELECT * FROM apt_sources
''',
'''
SELECT * FROM yum_sources
'''
]
@@ -0,0 +1,67 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via rc.local and rc.common on Linux systems. RC scripts are used to start custom applications, services, scripts or commands during start-up. RC scripts have mostly been replaced by Systemd. However, through the "systemd-rc-local-generator", these files can be converted to services that run at boot. The query monitors for file creation or modification events in the /etc/rc.local and /etc/rc.common files, as well as processes started by these scripts. These activities can indicate attempts to establish persistence through rc.local modifications.
"""
integration = ["endpoint", "system"]
uuid = "a95f778f-2193-4a3d-bbbe-7b02d5740638"
name = "Persistence via rc.local/rc.common"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"This hunt includes multiple ES|QL and OSQuery queries to detect potential persistence mechanisms via rc.local on Linux systems.",
"Detects file creation or modification events in the /etc/rc.local and /etc/rc.common files, which are used for system initialization scripts.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by rc.local and rc.common scripts to detect potential persistence mechanisms.",
"Syslog hunting query is provided to complement the detection by analyzing syslog entries related to rc.local and rc.common processes.",
"OSQuery queries are provided to retrieve systemd unit states, startup items, and detailed file information related to rc.local and rc.common."
]
mitre = ["T1037.004", "T1546.003"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (file.path == "/etc/rc.local" or file.path == "/etc/rc.common")
| eval persistence = case(file.path == "/etc/rc.local" or file.path == "/etc/rc.common", process.name, null)
| stats pers_count = count(persistence), agent_count = count_distinct(agent.id) by process.executable
| where pers_count > 0 and pers_count <= 3 and agent_count <= 3
| sort pers_count asc
| limit 100
''',
'''
from logs-system.syslog-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and process.name in ("rc.local", "rc.common")
| stats cc = count(), host_count = count_distinct(host.name) by message
| where host_count <= 3 and cc < 10
| sort cc asc
| limit 100
''',
'''
SELECT * FROM systemd_units WHERE id = "rc-local.service"
''',
'''
SELECT * FROM startup_items WHERE name = "rc-local.service"
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path in ('/etc/rc.local', '/etc/rc.common')
'''
]
@@ -0,0 +1,98 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via modifications to shell profile files on Linux systems. It monitors file creation or modification events in system-wide and user-specific profile files, which can indicate attempts to establish persistence through shell modifications. It also monitors processes started by SSH daemons to detect suspicious activity related to SSH logins.
"""
integration = ["endpoint"]
uuid = "20a02fad-2a09-44c0-a8ce-ce4502859c8a"
name = "Shell Modification Persistence"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"Monitors for file creation or modification events in system-wide and user-specific profile files, such as /etc/profile, /etc/bash.bashrc, /home/*/.bashrc, and others.",
"Excludes modifications made by expected update processes such as package managers to reduce false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by SSH daemons (sshd) to detect suspicious activity related to SSH logins.",
"OSQuery query is provided to retrieve detailed file information related to profile files."
]
mitre = ["T1546.004", "T1053.005"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide profile files
file.path in ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout") or
file.path like "/etc/profile.d/*" or
// User-specific profile files
file.path like "/home/*/.profile" or
file.path like "/home/*/.bash_profile" or
file.path like "/home/*/.bash_login" or
file.path like "/home/*/.bash_logout" or
file.path like "/home/*/.bashrc"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "microdnf", "podman", "apk"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide profile files
file.path in ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout") or
file.path like "/etc/profile.d/*" or
// User-specific profile files
file.path like "/home/*/.profile" or
file.path like "/home/*/.bash_profile" or
file.path like "/home/*/.bash_login" or
file.path like "/home/*/.bash_logout" or
file.path like "/home/*/.bashrc",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.parent.name == "sshd"
| stats cc = count(*) by process.command_line
| where cc <= 20
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path IN ("/etc/profile", "/etc/bash.bashrc", "/etc/bash.bash_logout")
OR f.path LIKE "/etc/profile.d/%"
OR f.path LIKE "/home/%/.profile"
OR f.path LIKE "/home/%/.bash_profile"
OR f.path LIKE "/home/%/.bash_login"
OR f.path LIKE "/home/%/.bash_logout"
OR f.path LIKE "/home/%/.bashrc"
'''
]
@@ -0,0 +1,55 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential SSH persistence mechanisms on Linux systems using OSQuery. It monitors SSH keys, authorized_keys files, SSH configuration files, and SSH file information to detect unauthorized access or persistence techniques. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "aa759db0-4499-42f2-9f2f-be3e00fdebfa"
name = "Persistence via SSH Configurations and/or Keys"
language = ["SQL"]
license = "Elastic License v2"
notes = [
"Monitors SSH keys, authorized_keys files, and SSH configuration files using OSQuery to detect potential unauthorized access or persistence techniques.",
"Lists detailed information about SSH files, including paths, owners, and permissions.",
"Requires additional data analysis and investigation into results to identify malicious or unauthorized SSH configurations and keys."
]
mitre = ["T1098.004", "T1563.001"]
query = [
'''
SELECT * FROM user_ssh_keys
''',
'''
SELECT authorized_keys.*
FROM users
JOIN authorized_keys
USING(uid)
''',
'''
SELECT * FROM ssh_configs
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE "/root/.ssh/%"
OR f.path LIKE "/home/%/.ssh/%"
OR f.path LIKE "/etc/ssh/%"
OR f.path LIKE "/etc/ssh/sshd_config.d/%"
OR f.path LIKE "/etc/ssh/ssh_config.d/%"
'''
]
@@ -0,0 +1,188 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via systemd (timers) on Linux systems. It monitors for file creation or modification events related to systemd service and timer configurations, as well as generators, which can indicate attempts to establish persistence through scheduled tasks.
"""
integration = ["endpoint"]
uuid = "d2d24ad6-a315-4e05-a3f9-e205eb805df4"
name = "Persistence via Systemd (Timers)"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"This hunt includes multiple ES|QL and OSQuery queries to identify potential persistence mechanisms via systemd timers on Linux systems.",
"Detects file creation or modification events in directories and files associated with systemd services, timers, and generators, such as /run/systemd/system, /etc/systemd/system, /etc/systemd/user, and various /usr/lib/systemd directories.",
"Excludes common legitimate processes and file types to minimize false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"OSQuery queries are provided to complement the detection by retrieving detailed file information and entries related to systemd services, timers, and generators."
]
mitre = ["T1053.005", "T1546.002"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide/user-specific services/timers (root permissions required)
file.path like "/run/systemd/system/*" or
file.path like "/etc/systemd/system/*" or
file.path like "/etc/systemd/user/*" or
file.path like "/usr/local/lib/systemd/system/*" or
file.path like "/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/user/*" or
// user-specific services/timers (user permissions required)
file.path like "/home/*/.config/systemd/user/*" or
file.path like "/home/*/.local/share/systemd/user/*" or
// System-wide generators (root permissions required)
file.path like "/etc/systemd/system-generators/*" or
file.path like "/usr/local/lib/systemd/system-generators/*" or
file.path like "/lib/systemd/system-generators/*" or
file.path like "/etc/systemd/user-generators/*" or
file.path like "/usr/local/lib/systemd/user-generators/*" or
file.path like "/usr/lib/systemd/user-generators/*"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"netplan", "systemd", "generate"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide/user-specific services/timers (root permissions required)
file.path like "/run/systemd/system/*" or
file.path like "/etc/systemd/system/*" or
file.path like "/etc/systemd/user/*" or
file.path like "/usr/local/lib/systemd/system/*" or
file.path like "/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/system/*" or
file.path like "/usr/lib/systemd/user/*" or
// user-specific services/timers (user permissions required)
file.path like "/home/*/.config/systemd/user/*" or
file.path like "/home/*/.local/share/systemd/user/*" or
// System-wide generators (root permissions required)
file.path like "/etc/systemd/system-generators/*" or
file.path like "/usr/local/lib/systemd/system-generators/*" or
file.path like "/lib/systemd/system-generators/*" or
file.path like "/etc/systemd/user-generators/*" or
file.path like "/usr/local/lib/systemd/user-generators/*" or
file.path like "/usr/lib/systemd/user-generators/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
(f.path LIKE "/run/systemd/system/%"
OR f.path LIKE "/etc/systemd/system/%"
OR f.path LIKE "/etc/systemd/user/%"
OR f.path LIKE "/usr/local/lib/systemd/system/%"
OR f.path LIKE "/lib/systemd/system/%"
OR f.path LIKE "/usr/lib/systemd/system/%"
OR f.path LIKE "/usr/lib/systemd/user/%"
OR f.path LIKE "/home/%/.config/systemd/user/%"
OR f.path LIKE "/home/%/.local/share/systemd/user/%")
AND f.filename LIKE "%.service"
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/run/systemd/system',
'/etc/systemd/system',
'/etc/systemd/user',
'/usr/local/lib/systemd/system',
'/lib/systemd/system',
'/usr/lib/systemd/system',
'/usr/lib/systemd/user',
'/home/.config/systemd/user',
'/home/.local/share/systemd/user'
)
AND f.filename LIKE "%.timer"
ORDER BY
f.mtime DESC;
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/etc/systemd/system-generators/',
'/usr/local/lib/systemd/system-generators/',
'/lib/systemd/system-generators/',
'/etc/systemd/user-generators/',
'/usr/local/lib/systemd/user-generators/',
'/usr/lib/systemd/user-generators/'
)
ORDER BY
f.mtime DESC;
''',
'''
SELECT name, path, source, status, type FROM startup_items
WHERE type == "systemd unit" AND status == "active" AND
name LIKE "%.service" OR name LIKE "%.timer"
'''
]
@@ -0,0 +1,88 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via Udev rules on Linux systems. Udev is a device manager for the Linux kernel that manages device nodes in /dev. Udev is responsible for creating and removing device nodes in /dev when devices are added or removed from the system. Udev executes scripts when devices are added or removed from the system. This query monitors file creation or modification events in Udev rule directories and processes started by Udevadm. These activities can indicate attempts to establish persistence through Udev configurations. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "8d42a644-5b60-4165-a8f1-84d5bcdd4ade"
name = "Persistence via Udev"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"Monitors for file creation or modification events in Udev rule directories such as /etc/udev/rules.d/, /run/udev/rules.d/, /usr/lib/udev/rules.d/, and /lib/udev/.",
"Excludes modifications made by expected update processes such as package managers to reduce false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by Udevadm to detect suspicious activity related to Udev rules.",
"OSQuery query is provided to retrieve detailed file information related to Udev rules."
]
mitre = ["T1547.010"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
file.path like "/etc/udev/rules.d/*" or
file.path like "/run/udev/rules.d/*" or
file.path like "/usr/lib/udev/rules.d/*" or
file.path like "/lib/udev/*"
) and not process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon",
"microdnf", "podman", "apk", "netplan", "generate"
)
| eval persistence = case(
file.path like "/etc/udev/rules.d/*" or
file.path like "/run/udev/rules.d/*" or
file.path like "/usr/lib/udev/rules.d/*" or
file.path like "/lib/udev/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name == "udevadm" and
// Excluding these because this is typical udev behavior.
// If you suspect Udev persistence, remove this exclusion in order to do a more elaborate search
not (process.executable like "/lib/*" or process.executable like "/usr/lib/*")
| stats cc = count(), host_count = count_distinct(host.name) by process.executable
// Tweak the process/host count if you suspect Udev persistence
| where host_count <= 5 and cc < 50
| sort cc asc
| limit 100
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size bytes,
h.md5
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
LEFT JOIN
hash h ON f.path = h.path
WHERE
f.directory IN (
'/etc/udev/rules.d/',
'/run/udev/rules.d/',
'/usr/lib/udev/rules.d/',
'/lib/udev/'
)
ORDER BY
f.mtime DESC;
'''
]
@@ -0,0 +1,29 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential system binary hijacking attempts on Linux systems. It monitors process execution events where common system binaries such as ls, cat, mkdir, touch, mv, and cp are the parent processes. These activities can indicate attempts to hijack system binaries for malicious purposes. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "d22cbe8f-c84d-4811-aa6d-f1ee00c806b2"
name = "Unusual System Binary Parent (Potential System Binary Hijacking Attempt)"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors process execution events where common system binaries such as ls, cat, mkdir, touch, mv, and cp are the parent processes.",
"Focuses on identifying unusual or suspicious child processes spawned by these common system binaries.",
"Uses stats to count occurrences and identify unusual activity by looking at the number of unique hosts and processes involved.",
"Requires additional data analysis and investigation into results to identify malicious or unauthorized use of system binaries."
]
mitre = ["T1546.004", "T1059.004"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and process.parent.name in ("ls", "cat", "mkdir", "touch", "mv", "cp")
| stats cc = count(), host_count = count_distinct(host.name) by process.parent.executable, process.executable
| where host_count <= 5
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,39 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies user and group creation or modification activities on Linux systems using OSQuery. It monitors changes to the shadow file, user and group information, and user processes. These activities can indicate potential unauthorized access or privilege escalation attempts. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "f00c9757-d21b-432c-90a6-8372f18075d0"
name = "Privilege Escalation/Persistence via User/Group Creation and/or Modification"
language = ["SQL"]
license = "Elastic License v2"
notes = [
"Monitors changes to the shadow file and user/group information using OSQuery to detect potentially unauthorized access or privilege escalation attempts.",
"Lists detailed information about users, including authentication status and running processes.",
"Requires additional data analysis and investigation into results to identify malicious or unauthorized user and group modifications."
]
mitre = ["T1136", "T1136.001", "T1136.002"]
query = [
'''
SELECT * FROM shadow
''',
'''
SELECT * FROM shadow
WHERE password_status != "locked"
''',
'''
SELECT username, gid, uid, shell, description FROM users
WHERE username != 'root' AND uid LIKE "0"
''',
'''
SELECT * FROM users WHERE username = "newuser"
''',
'''
SELECT * FROM logged_in_users WHERE user = "newuser"
''',
'''
SELECT pid, username, name FROM processes p JOIN users u ON u.uid = p.uid ORDER BY username
'''
]
@@ -0,0 +1,121 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies potential persistence mechanisms via modifications to XDG autostart directories on Linux systems. XDG Autostart entries can be used to execute arbitrary commands or scripts when a user logs in. It monitors file creation or modification events in system-wide, user-specific, and root-specific autostart directories. Additionally, it monitors processes started by common Linux desktop session managers to detect suspicious activity related to autostart entries.
"""
integration = ["endpoint"]
uuid = "8dcc2161-65e0-4448-a03a-1c4e0cbc9330"
name = "XDG Persistence"
language = ["ES|QL", "SQL"]
license = "Elastic License v2"
notes = [
"Monitors for file creation or modification events in system-wide, user-specific, and root-specific XDG autostart directories.",
"Excludes modifications made by expected update processes such as package managers to reduce false positives.",
"Uses EVAL to tag potential persistence events and counts occurrences to identify unusual activity.",
"Monitors processes started by common Linux desktop session managers to detect suspicious activity related to autostart entries.",
"OSQuery queries are provided to retrieve enabled XDG startup items and detailed file information related to autostart directories."
]
mitre = ["T1547.001", "T1053.005"]
query = [
'''
from logs-endpoint.events.file-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type in ("creation", "change") and (
// System-wide autostart directories
file.path like "/etc/xdg/autostart/*" or
file.path like "/usr/share/autostart/*" or
// User-specific autostart directories
file.path like "/home/*/.config/autostart/*" or
file.path like "/home/*/.local/share/autostart/*" or
file.path like "/home/*/.config/autostart-scripts/*" or
// Root-specific autostart directories
file.path like "/root/.config/autostart/*" or
file.path like "/root/.local/share/autostart/*" or
file.path like "/root/.config/autostart-scripts/*"
) and not (
process.name in (
"dpkg", "dockerd", "yum", "dnf", "snapd", "pacman", "pamac-daemon", "microdnf", "podman", "apk"
) or
process.executable == "/proc/self/exe" or
process.executable like "/dev/fd/*" or
file.extension in ("dpkg-remove", "swx", "swp")
)
| eval persistence = case(
// System-wide autostart directories
file.path like "/etc/xdg/autostart/*" or
file.path like "/usr/share/autostart/*" or
// User-specific autostart directories
file.path like "/home/*/.config/autostart/*" or
file.path like "/home/*/.local/share/autostart/*" or
file.path like "/home/*/.config/autostart-scripts/*" or
// Root-specific autostart directories
file.path like "/root/.config/autostart/*" or
file.path like "/root/.local/share/autostart/*" or
file.path like "/root/.config/autostart-scripts/*",
process.name,
null
)
| stats pers_count = count(persistence) by process.executable, file.path
| where pers_count > 0 and pers_count <= 20
| sort pers_count asc
| limit 100
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.parent.name in (
"plasmashell", "gnome-session", "xfce4-session", "gnome-session-binary", "mate-session", "cinnamon-session",
"lxsession", "lxqt-session", "unity-session", "pantheon-session", "enlightenment_start"
)
| stats cc = count(*) by process.command_line, process.parent.executable
| where cc <= 20
| sort cc asc
| limit 100
''',
'''
SELECT name, path, source, status, type FROM startup_items
WHERE type == "Startup Item" AND status == "enabled" AND (
source LIKE "/etc/xdg/autostart/%"
OR source LIKE "/usr/share/autostart/%"
OR source LIKE "/home/%/.config/autostart/%"
OR source LIKE "/home/%/.local/share/autostart/%"
OR source LIKE "/home/%/.config/autostart-scripts/%"
OR source LIKE "/root/.config/autostart/%"
OR source LIKE "/root/.local/share/autostart/%"
OR source LIKE "/root/.config/autostart-scripts/%"
)
''',
'''
SELECT
f.filename,
f.path,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.path LIKE "/etc/xdg/autostart/%"
OR f.path LIKE "/usr/share/autostart/%"
OR f.path LIKE "/home/%/.config/autostart/%"
OR f.path LIKE "/home/%/.local/share/autostart/%"
OR f.path LIKE "/home/%/.config/autostart-scripts/%"
OR f.path LIKE "/root/.config/autostart/%"
OR f.path LIKE "/root/.local/share/autostart/%"
OR f.path LIKE "/root/.config/autostart-scripts/%"
'''
]
@@ -0,0 +1,22 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies entries in the sudoers file on Linux systems using OSQuery. The sudoers file controls which users have administrative privileges and can be a target for attackers seeking to escalate their privileges. This hunt lists all sudoers rules for further analysis.
"""
integration = ["endpoint"]
uuid = "6e57e6a6-f150-405d-b8be-e4e666a3a86d"
name = "Privilege Escalation Identification via Existing Sudoers File"
language = ["SQL"]
license = "Elastic License v2"
notes = [
"Lists all entries in the sudoers file using OSQuery to detect potentially unauthorized or suspicious rules.",
"Requires additional data analysis and investigation into results to identify malicious or misconfigured sudoers entries.",
"Focuses on monitoring and analyzing administrative privileges granted through the sudoers file."
]
mitre = ["T1548.003"]
query = [
'''
SELECT * FROM sudoers
'''
]
@@ -0,0 +1,48 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies processes on Linux systems with specific capabilities set. It monitors process execution events where processes have effective or permitted capabilities, which can be indicative of elevated privileges. The hunt focuses on non-root users to detect potential privilege escalation attempts. The hunt lists detailed information for further analysis and investigation.
"""
integration = ["endpoint"]
uuid = "6f67704d-e5b1-4613-912c-e2965660fe17"
name = "Process Capability Hunting"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Monitors process execution events where processes have specific capabilities set, such as CAP_SYS_MODULE, CAP_SYS_PTRACE, and others.",
"Excludes certain processes and capabilities to reduce false positives, but these can be adjusted based on your environment.",
"Uses EVAL to tag potential privilege escalation events and counts occurrences to identify unusual activity.",
"Focuses on non-root users to detect potential privilege escalation attempts.",
"Requires additional data analysis and investigation into results to identify malicious or unauthorized use of process capabilities."
]
mitre = ["T1548.001", "T1548.003"]
query = [
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and (process.thread.capabilities.effective is not null or process.thread.capabilities.permitted is not null) and user.id != "0" and
not (
// Remove these if you expect persistence through capabilities
process.executable like "/var/lib/docker/*" or
process.name == "gnome-keyring-daemon" or
process.thread.capabilities.permitted == "CAP_WAKE_ALARM"
)
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.thread.capabilities.effective, process.thread.capabilities.permitted
| where host_count <= 3 and cc < 5
| sort cc asc
| limit 100
''',
'''
from logs-endpoint.events.process-*
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.action == "exec" and event.type == "start" and (
process.thread.capabilities.effective in ("CAP_SYS_MODULE", "CAP_SYS_PTRACE", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_SETUID", "CAP_SETGID", "CAP_SYS_ADMIN") or
process.thread.capabilities.permitted in ("CAP_SYS_MODULE", "CAP_SYS_PTRACE", "CAP_DAC_OVERRIDE", "CAP_DAC_READ_SEARCH", "CAP_SETUID", "CAP_SETGID", "CAP_SYS_ADMIN")
) and user.id != "0"
| stats cc = count(), host_count = count_distinct(host.name) by process.executable, process.thread.capabilities.effective, process.thread.capabilities.permitted
| where host_count <= 3 and cc < 5
| sort cc asc
| limit 100
'''
]
@@ -0,0 +1,40 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies segmentation faults (segfaults) and potential buffer overflow attacks on Linux systems by parsing syslog messages related to segfaults. It captures details about the crashing process, shared object file, and other relevant information to help identify and investigate potential exploitation attempts.
"""
integration = ["system"]
uuid = "3f3fd2b9-940c-4310-adb1-d8b7d726e281"
name = "Segmentation Fault & Potential Buffer Overflow Hunting"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"Detects segfaults and parses syslog messages related to segfaults to identify the crashing process and shared object file along with additional crash details.",
"Uses GROK to extract relevant fields from syslog messages.",
"Counts occurrences of segfaults within a plain text message field to potentially detect buffer overflow attacks and unsuccessful process injection attempts.",
"Removes prepending spaces from syslog messages using EVAL to ensure consistent parsing.",
"Depending on the Syslog configuration, additional parsing may be required to extract the necessary fields from the message."
]
mitre = ["T1203", "T1068"]
query = [
'''
from logs-system.syslog*
| where @timestamp > now() - 12 hour
| where host.os.type == "linux" and process.name == "kernel" and message like "*segfault*"
| grok message "\\[%{NUMBER:timestamp}\\] %{WORD:process}\\[%{NUMBER:pid}\\]: segfault at %{BASE16NUM:segfault_address} ip %{BASE16NUM:instruction_pointer} sp %{BASE16NUM:stack_pointer} error %{NUMBER:error_code} in %{DATA:so_file}\\[%{BASE16NUM:so_base_address}\\+%{BASE16NUM:so_offset}\\]"
| keep timestamp, process, pid, so_file, segfault_address, instruction_pointer, stack_pointer, error_code, so_base_address, so_offset
''',
'''
from logs-system.syslog*
| where host.os.type == "linux" and process.name == "kernel" and message like "*segfault*"
| where @timestamp > now() - 12 hour
| grok message "\\[%{DATA:timestamp}\\] %{WORD:process}\\[%{NUMBER:pid}\\]: segfault at %{BASE16NUM:segfault_address} ip %{BASE16NUM:instruction_pointer} sp %{BASE16NUM:stack_pointer} error %{NUMBER:error_code} in %{DATA:so_name}\\[%{BASE16NUM:so_base_address}\\+%{BASE16NUM:so_offset}\\] likely on CPU %{NUMBER:cpu} \\(core %{NUMBER:core}, socket %{NUMBER:socket}\\)"
| eval timestamp = REPLACE(timestamp, "\\s+", "")
| keep timestamp, process, pid, segfault_address, instruction_pointer, stack_pointer, error_code, so_name, so_base_address, so_offset, cpu, core, socket
| stats cc = count() by process, so_name
// Alter this threshold to make sense for your environment
| where cc > 100
| limit 10
'''
]
@@ -0,0 +1,55 @@
[hunt]
author = "Elastic"
description = """
This hunt identifies SUID binaries on Linux systems using OSQuery. SUID binaries can be exploited by attackers to gain elevated privileges. The hunt includes queries to list all SUID binaries and detailed information about these files, focusing on regular files owned by root with SUID or SGID bits set.
"""
integration = ["endpoint"]
uuid = "2db642d2-621a-4183-88b5-b2659dc2c940"
name = "OSQuery SUID Hunting"
language = ["SQL"]
license = "Elastic License v2"
notes = [
"Identifies SUID binaries using OSQuery to detect potentially exploitable files with SUID or SGID bits set.",
"Lists all SUID binaries and provides detailed information about these files, including their paths, owners, and permissions.",
"Focuses on regular files owned by root with SUID or SGID bits set to identify potential privilege escalation vectors.",
"OSQuery has limited support for wildcard queries, therefore the query includes multiple LIKE conditions for directories. These can be increased and decreased, based on the environment"
]
mitre = ["T1548.001", "T1574.002"]
query = [
'''
SELECT * FROM suid_bin
''',
'''
SELECT
f.filename,
f.path,
f.mode,
f.uid,
f.gid,
f.type,
u.username AS file_owner,
g.groupname AS group_owner,
datetime(f.atime, 'unixepoch') AS file_last_access_time,
datetime(f.mtime, 'unixepoch') AS file_last_modified_time,
datetime(f.ctime, 'unixepoch') AS file_last_status_change_time,
datetime(f.btime, 'unixepoch') AS file_created_time,
f.size AS size_bytes
FROM
file f
LEFT JOIN
users u ON f.uid = u.uid
LEFT JOIN
groups g ON f.gid = g.gid
WHERE
f.type == "regular" AND
(f.uid == 0 or f.gid == 0) AND
(f.mode LIKE "2%" OR f.mode LIKE "4%") AND
(
f.path LIKE "/%%" OR
f.path LIKE "/%%/%%" OR
f.path LIKE "/%%/%%/%%" OR
f.path LIKE "/%%/%%/%%/%%"
)
'''
]
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `00023411-192e-4472-90aa-da7562bc3f2a`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `991b55c3-6327-4af6-8e0c-5d4870748369`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `11e33a8f-805b-4394-bee0-08ae8d78b025`
- **Integration:** [aws_bedrock.invocation](https://docs.elastic.co/integrations/aws_bedrock)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -4,9 +4,9 @@ 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"
uuid = "00023411-192e-4472-90aa-da7562bc3f2a"
name = "AWS Bedrock LLM Denial-of-Service or Resource Exhaustion"
language = "ES|QL"
language = ["ES|QL"]
license = "Elastic License v2"
query = [
'''
@@ -4,9 +4,9 @@ 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"
uuid = "991b55c3-6327-4af6-8e0c-5d4870748369"
name = "AWS Bedrock LLM Latency Anomalies"
language = "ES|QL"
language = ["ES|QL"]
license = "Elastic License v2"
query = [
'''
@@ -2,9 +2,9 @@
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"
uuid = "11e33a8f-805b-4394-bee0-08ae8d78b025"
name = "AWS Bedrock LLM Sensitive Content Refusals"
language = "ES|QL"
language = ["ES|QL"]
license = "Elastic License v2"
query = [
'''
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `dc04d70a-80aa-4c3f-ad02-2b18d54af6d4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -4,9 +4,9 @@ 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"
uuid = "dc04d70a-80aa-4c3f-ad02-2b18d54af6d4"
name = "Suspicious Network Connections by Unsigned Mach-O"
language = "ES|QL"
language = ["ES|QL"]
license = "Elastic License v2"
notes = [
"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.",
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `4f878255-53b8-4914-9a7d-4b668bd2ea6a`
- **Integration:** [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `d06bc067-6174-412f-b1c9-bf8f15149519`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `a2006c66-d6ab-43ee-871e-d650e38f7972`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `34a7aadb-fb0f-45ea-9260-830f39c3343b`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `d0aed6f5-f84c-4da8-bb2a-b5ca0fbb55e0`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `1c7be6db-12eb-4281-878d-b6abe0454f36`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `cebfbb4d-5b2a-44d8-b763-5512b654fb26`
- **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`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `f7d2054f-b571-4cd0-b39e-a779576e9398`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `8a95f552-f149-4c71-888e-f2690f5add15`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -8,9 +8,9 @@
- **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`
- **UUID:** `b786bcd7-b119-4ff7-b839-3927c2ff7f1f`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `24108755-4d1f-4d7a-ad5f-04c2ca55e9a3`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `5fd5da54-0515-4d6b-b8d7-30fd05f5be33`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `52a958e8-0368-4e74-bd4b-a64faf397bf4`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `a95e69af-22ad-4ab7-919e-794501f10c95`
- **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`
- **Language:** `[ES|QL]`
## Query
@@ -28,7 +28,7 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-sys
| 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"
to_lower(process.parent.name) == "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,})""", "")
@@ -40,7 +40,7 @@ from logs-endpoint.events.process-*, logs-windows.sysmon_operational-*, logs-sys
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)
to_lower(process.parent.name) == "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
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `0d960760-8a40-49c1-bbdd-4deb32c7fd67`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `a0a84a86-115f-42f9-90a5-4cb7ceeef981`
- **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`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `5e5aa9c2-96a8-4d5b-bbca-ff2ec8fefa5b`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `c00f1afe-4f25-4542-8cc9-277b23581121`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `f1b8519a-4dae-475f-965a-f53559233eab`
- **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`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `386f9cec-bb44-4dd2-8368-45e6fa0a425b`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `814894a4-c951-4f33-ab0b-09354e1cb957`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `df4ee961-254d-4ad1-af15-c65c3b65abcd`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -6,9 +6,9 @@
- **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`
- **UUID:** `ea950361-33e4-4045-96a5-d36ca28fbc91`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint), [windows](https://docs.elastic.co/integrations/windows)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `69fc4f40-8fb1-4652-99b7-52755cd370fe`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `24925575-defd-4581-bfda-a8753dcfb46e`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `44e6adc6-e183-4bfa-b06d-db41669641fa`
- **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`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `df50f65e-e820-47f4-a039-671611582f51`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `44223fd6-8241-4c21-9d54-21201fa15b12`
- **Integration:** [system](https://docs.elastic.co/integrations/system)
- **Language:** `ES|QL`
- **Language:** `[ES|QL]`
## Query
@@ -7,9 +7,9 @@
- **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`
- **UUID:** `2e583d3c-7ad6-4544-a0db-c685b2066493`
- **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`
- **Language:** `[ES|QL]`
## Query

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