Skip to content

Commit

Permalink
[New Hunts] Adding Several Hunting PRs into this Main PR (#4342)
Browse files Browse the repository at this point in the history
* [New Hunt] Linux PAM Persistence

* Fixed notes

* [New Hunt] Persistence via Dynamic Linker Hijacking

* [New Hunt & Tuning] Persistence via LKMs

* [New Hunt] Persistence via Web Shells

* Update query

* [New Rule] Persistence via DPKG/RPM Package

* [New Hunt] Persistence via Container

* Update hunting/linux/queries/persistence_via_pluggable_authentication_module.toml

* [Hunt Addition] System User Interactive Session

* Merge branch 'main' into new-hunts-PAM

* Updates

* ++

* Match RTA bin executor

---------

Co-authored-by: Shashank K S <[email protected]>

(cherry picked from commit a2b280a)
  • Loading branch information
Aegrah authored and github-actions[bot] committed Jan 7, 2025
1 parent 5d36e65 commit a15a626
Show file tree
Hide file tree
Showing 26 changed files with 1,046 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ from logs-aws.cloudtrail-*
and aws.cloudtrail.request_parameters RLIKE ".*arn:aws:iam.*"
| dissect aws.cloudtrail.request_parameters "%{}AWS\": \"arn:aws:iam::%{target_account_id}:"
| where cloud.account.id != target_account_id
| keep @timestamp, event.provider, event.action, aws.cloudtrail.request_parameters, target_account_id, cloud.account.id
```

## Notes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# AWS IAM Customer-Managed Policy Attachment for Privilege Escalation
# AWS IAM Customer-Managed Policy Attachment to Existing Roles

---

Expand All @@ -10,7 +10,7 @@
- **UUID:** `418baaf2-9ae1-11ef-be63-f661ea17fbcd`
- **Integration:** [aws.cloudtrail](https://docs.elastic.co/integrations/aws/cloudtrail)
- **Language:** `[ES|QL]`
- **Source File:** [AWS IAM Customer-Managed Policy Attachment for Privilege Escalation](../queries/iam_customer_managed_policies_attached_to_existing_roles.toml)
- **Source File:** [AWS IAM Customer-Managed Policy Attachment to Existing Roles](../queries/iam_customer_managed_policies_attached_to_existing_roles.toml)

## Query

Expand All @@ -29,11 +29,11 @@ from logs-aws.cloudtrail*

## Notes

- Review the `target_account_id` field to verify the AWS account in which the role is being modified, especially if this account is outside of your organization’s typical accounts.
- Examine `aws.cloudtrail.request_parameters` for details on the role and attached policy. Customer-managed policies granting overly permissive access, such as `AdministratorAccess`, may signal unauthorized privilege escalation.
- Cross-reference `event.action` values where `AttachRolePolicy` appears to further investigate attached policies that could enable lateral movement or persistence.
- Evaluate `aws.cloudtrail.user_identity.arn` to confirm if the actor attaching the policy has legitimate permissions for this action. Anomalous or unauthorized actors may indicate privilege abuse.
- Look for patterns of multiple `AttachRolePolicy` actions across roles by the same user or entity. High frequency of these actions could suggest an attempt to establish persistent control across roles within your AWS environment.
- Review the `attached_policy_name` and `target_role_name` fields to identify the customer-managed policy and role involved in the attachment.
- Review the permissions of the attached policy to determine the potential impact of the privilege escalation attempt.
- Review all entities that `target_role_name` may be attached to as these entities may have been compromised or misused.
- Consider reviewing the `aws.cloudtrail.user_identity.arn` field to identify the actor responsible for the privilege escalation attempt.
- Review the user agent of the actor to determine the source of the privilege escalation attempt, such as an AWS CLI or SDK.

## MITRE ATT&CK Techniques

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ from logs-aws.cloudtrail-*
| dissect aws.cloudtrail.request_parameters "{%{?principal_key}=%{principal_id}, %{?function_name_key}=%{function_name}, %{?statement_key}=%{statement_value}, %{?action_key}=lambda:%{action_value}}"
| eval write_action = (starts_with(action_value, "Invoke") or starts_with("Update", action_value) or starts_with("Put", action_value))
| where write_action == true
| keep @timestamp, principal_id, event.provider, event.action, aws.cloudtrail.request_parameters, principal_id, function_name, action_value, statement_value, write_action
```

## Notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ from logs-aws.cloudtrail-*
and aws.cloudtrail.user_identity.type == "FederatedUser"
| dissect aws.cloudtrail.additional_eventdata "{%{?mobile_version_key}=%{mobile_version}, %{?mfa_used_key}=%{mfa_used}}"
| where mfa_used == "No"
| keep @timestamp, event.provider, event.action, aws.cloudtrail.event_type, aws.cloudtrail.user_identity.type, aws.cloudtrail.additional_eventdata, mobile_version, mfa_used
```

## Notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ from logs-aws.cloudtrail-*
and aws.cloudtrail.user_identity.type == "AssumedRole"
and event.action == "SendCommand"
and user.id like "*:i-*"
| keep @timestamp, event.provider, event.action, aws.cloudtrail.user_identity.type, user.id, aws.cloudtrail.request_parameters
```

## Notes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ from logs-aws.cloudtrail-*
| dissect aws.cloudtrail.request_parameters "{%{}policyArns=[%{policies_applied}]"
| eval duration_minutes = to_integer(duration_requested) / 60
| where (duration_minutes > 1440) or (policies_applied RLIKE ".*AdministratorAccess.*")
| keep @timestamp, event.dataset, event.provider, event.action, aws.cloudtrail.request_parameters, user_name, duration_requested, duration_minutes, policies_applied
```

## Notes
Expand Down
6 changes: 6 additions & 0 deletions hunting/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,18 @@ Here are the queries currently available:
- [OSQuery SUID Hunting](./linux/docs/privilege_escalation_via_suid_binaries.md) (ES|QL)
- [Persistence Through Reverse/Bind Shells](./linux/docs/persistence_reverse_bind_shells.md) (ES|QL)
- [Persistence via Cron](./linux/docs/persistence_via_cron.md) (ES|QL)
- [Persistence via DPKG/RPM Package](./linux/docs/persistence_via_rpm_dpkg_installer_packages.md) (ES|QL)
- [Persistence via Docker Container](./linux/docs/persistence_via_malicious_docker_container.md) (ES|QL)
- [Persistence via Dynamic Linker Hijacking](./linux/docs/persistence_via_dynamic_linker_hijacking.md) (ES|QL)
- [Persistence via Loadable Kernel Modules](./linux/docs/persistence_via_loadable_kernel_modules.md) (ES|QL)
- [Persistence via Message-of-the-Day](./linux/docs/persistence_via_message_of_the_day.md) (ES|QL)
- [Persistence via Package Manager](./linux/docs/persistence_via_package_manager.md) (ES|QL)
- [Persistence via Pluggable Authentication Modules (PAM)](./linux/docs/persistence_via_pluggable_authentication_module.md) (ES|QL)
- [Persistence via SSH Configurations and/or Keys](./linux/docs/persistence_via_ssh_configurations_and_keys.md) (ES|QL)
- [Persistence via System V Init](./linux/docs/persistence_via_sysv_init.md) (ES|QL)
- [Persistence via Systemd (Timers)](./linux/docs/persistence_via_systemd_timers.md) (ES|QL)
- [Persistence via Udev](./linux/docs/persistence_via_udev.md) (ES|QL)
- [Persistence via Web Shell](./linux/docs/persistence_via_web_shell.md) (ES|QL)
- [Persistence via rc.local/rc.common](./linux/docs/persistence_via_rc_local.md) (ES|QL)
- [Potential Defense Evasion via Multi-Dot Process Execution](./linux/docs/defense_evasion_via_multi_dot_process_execution.md) (ES|QL)
- [Privilege Escalation Identification via Existing Sudoers File](./linux/docs/privilege_escalation_via_existing_sudoers.md) (ES|QL)
Expand Down
30 changes: 30 additions & 0 deletions hunting/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,36 @@ linux:
mitre:
- T1037.004
- T1546.003
2a3c46b8-7bd6-4bc4-a4a8-a1af114ea152:
name: Persistence via Pluggable Authentication Modules (PAM)
path: ./linux/queries/persistence_via_pluggable_authentication_module.toml
mitre:
- T1556.003
664d65ec-029e-4746-bf97-7bf3a0113e6a:
name: Persistence via Dynamic Linker Hijacking
path: ./linux/queries/persistence_via_dynamic_linker_hijacking.toml
mitre:
- T1574.006
d667d328-fadc-4a52-9b46-f42b1a83181c:
name: Persistence via Loadable Kernel Modules
path: ./linux/queries/persistence_via_loadable_kernel_modules.toml
mitre:
- T1547.006
e2e4a1ad-5e03-4968-927c-9ef13c49a3b8:
name: Persistence via Web Shell
path: ./linux/queries/persistence_via_web_shell.toml
mitre:
- T1505.003
1d7cae97-2dea-4f01-b04c-85fa4bd991d0:
name: Persistence via DPKG/RPM Package
path: ./linux/queries/persistence_via_rpm_dpkg_installer_packages.toml
mitre:
- T1546.016
b9b4f11f-1db9-491a-ab43-0e69e3f6d5be:
name: Persistence via Docker Container
path: ./linux/queries/persistence_via_malicious_docker_container.toml
mitre:
- T1610
okta:
0b936024-71d9-11ef-a9be-f661ea17fbcc:
name: Failed OAuth Access Token Retrieval via Public Client App
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@

```sql
from logs-auditd_manager.auditd-*, logs-auditd.log-*, auditbeat-*
| keep @timestamp, host.os.type, event.category, event.action, auditd.data.syscall, auditd.data.name, process.executable, process.name, agent.id
| 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
// Process name is different from executable in some cases
| stats agent_count = count_distinct(agent.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
| where agent_count == 1 and total_count <= 3
| limit 100
| sort auditd.data.name asc
```
Expand Down
105 changes: 105 additions & 0 deletions hunting/linux/docs/persistence_via_dynamic_linker_hijacking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Persistence via Dynamic Linker Hijacking

---

## Metadata

- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms via dynamic linker hijacking on Linux systems. Attackers can manipulate environment variables like LD_PRELOAD and LD_LIBRARY_PATH to execute malicious shared libraries, hijacking the dynamic linker process for persistence or privilege escalation. This hunt monitors for suspicious usage of these environment variables, the creation of shared library files (.so), and access to critical dynamic linker configuration files.

- **UUID:** `664d65ec-029e-4746-bf97-7bf3a0113e6a`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
- **Source File:** [Persistence via Dynamic Linker Hijacking](../queries/persistence_via_dynamic_linker_hijacking.toml)

## Query

```sql
from logs-endpoint.events.process-*
| keep @timestamp, host.os.type, event.type, event.action, process.env_vars, agent.id
| where @timestamp > now() - 30 days
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and
process.env_vars like "LD_PRELOAD=*.so" or
process.env_vars like "LD_LIBRARY_PATH=*"
| stats env_count = count(process.env_vars) by agent.id, process.env_vars
```

```sql
from logs-endpoint.events.file-*
| keep @timestamp, host.os.type, event.type, event.action, file.extension, file.path, process.executable, agent.id
| where @timestamp > now() - 30 days
| where host.os.type == "linux" and event.type == "creation" and file.extension == "so" and not (
// Add your exclusions here
file.path like "/run/initramfs/*" or
file.path like "/var/tmp/mkinitramfs*"
)
| stats cc = count(), agent_count = count_distinct(agent.id) by file.path, process.executable
| where agent_count <= 3
| sort cc asc
| limit 100
```

```sql
SELECT * FROM process_envs
WHERE key = "LD_PRELOAD"
OR key = "LD_LIBRARY_PATH";
```

```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/ld.so.preload"
OR f.path = "/etc/ld.so.conf"
OR f.path = "/etc/ld.so.cache"
OR f.path LIKE "/etc/ld.so.conf.d/%";
```

```sql
SELECT
p.pid,
p.name AS process_name,
p.path AS process_path,
p.cmdline AS command_line,
pe.key AS env_key,
pe.value AS env_value,
(strftime('%s', 'now') - p.start_time) AS runtime_seconds
FROM
processes p
JOIN
process_envs pe ON p.pid = pe.pid
WHERE
pe.key IN ('LD_PRELOAD', 'LD_LIBRARY_PATH')
AND (strftime('%s', 'now') - p.start_time) > 3600;
```

## Notes

- Identifies processes with suspicious environment variables, specifically LD_PRELOAD and LD_LIBRARY_PATH, which are often used in dynamic linker hijacking attacks.
- Monitors the creation of shared object (.so) files in non-standard or uncommon directories to detect potential malicious libraries.
- Tracks modifications to critical dynamic linker files like /etc/ld.so.preload, /etc/ld.so.conf, and related directories, which are common targets for attackers.
- Uses process environment variables and metadata to detect running processes that rely on suspicious linker configurations, focusing on processes that persist longer than typical short-lived tasks.
- Provides complementary OSQuery queries for detailed file metadata, including file ownership and timestamps, to support forensic investigations.
- This hunt leverages the process.env_vars field, which is a field that must be manually enabled within the Elastic Defend policy advanced settings tab.

## MITRE ATT&CK Techniques

- [T1574.006](https://attack.mitre.org/techniques/T1574/006)

## License

- `Elastic License v2`
89 changes: 89 additions & 0 deletions hunting/linux/docs/persistence_via_loadable_kernel_modules.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Persistence via Loadable Kernel Modules

---

## Metadata

- **Author:** Elastic
- **Description:** This hunt identifies potential persistence mechanisms leveraging Loadable Kernel Modules (LKMs) on Linux systems. LKMs enable dynamic extension of kernel functionality but can be abused by attackers to load malicious code into the kernel, granting them high privileges or persistence. This hunt monitors suspicious kernel module file creations, LKM-related process executions, and access to kernel module configuration files.

- **UUID:** `d667d328-fadc-4a52-9b46-f42b1a83181c`
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
- **Language:** `[ES|QL, SQL]`
- **Source File:** [Persistence via Loadable Kernel Modules](../queries/persistence_via_loadable_kernel_modules.toml)

## Query

```sql
from logs-endpoint.events.file-*
| keep @timestamp, host.os.type, event.type, event.action, file.extension, file.path, process.executable, agent.id
| where @timestamp > now() - 30 day
| where host.os.type == "linux" and event.type == "creation" and file.extension == "ko" and not (
// Add your exclusions here
file.path like "/run/initramfs/*" or
file.path like "/var/tmp/mkinitramfs*"
)
| stats cc = count(), agent_count = count_distinct(agent.id) by file.path, process.executable
| where agent_count <= 3
| sort cc asc
| limit 100
```

```sql
from logs-endpoint.events.process-*
| keep @timestamp, host.os.type, event.type, event.action, process.name, agent.id, process.args, process.args_count
| where @timestamp > now() - 30 days
| where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name in ("kmod", "modprobe", "insmod", "rmmod")
| stats cc = count(), agent_count = count_distinct(agent.id) by process.args, process.args_count
| where cc == 1 and agent_count == 1 and process.args_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 LIKE '/etc/modprobe.d/%'
OR f.path LIKE '/usr/lib/modprobe.d/%'
OR f.path LIKE '/usr/lib/security/%'
OR f.path LIKE '/etc/modules-load.d/%'
OR f.path LIKE '/run/modules-load.d/%'
OR f.path LIKE '/usr/local/lib/modules-load.d/%'
OR f.path like '/usr/lib/modules-load.d/%'
OR f.path = '/etc/modules'
```

```sql
SELECT * FROM kernel_modules;
```

## Notes

- Tracks the creation of loadable kernel module files (.ko) in non-standard directories to identify potential malicious modules.
- Monitors the execution of processes related to kernel module management, such as kmod, modprobe, insmod, and rmmod, to detect suspicious or unusual activity.
- Identifies changes to critical kernel module configuration files, including /etc/modprobe.d/, /etc/modules, and related paths.
- Uses OSQuery queries to gather detailed metadata on kernel modules currently loaded, supporting forensic analysis of potential persistence mechanisms.
- Provides statistics and counts to help identify rare or anomalous kernel module-related events.

## MITRE ATT&CK Techniques

- [T1547.006](https://attack.mitre.org/techniques/T1547/006)

## License

- `Elastic License v2`
Loading

0 comments on commit a15a626

Please sign in to comment.