Skip to content

Commit 9798f9d

Browse files
committed
[New Hunt] Persistence via Web Shells
1 parent 2ff2965 commit 9798f9d

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed

hunting/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Here are the queries currently available:
4646
- [Persistence via System V Init](./linux/docs/persistence_via_sysv_init.md) (ES|QL)
4747
- [Persistence via Systemd (Timers)](./linux/docs/persistence_via_systemd_timers.md) (ES|QL)
4848
- [Persistence via Udev](./linux/docs/persistence_via_udev.md) (ES|QL)
49+
- [Persistence via Web Shell](./linux/docs/persistence_via_web_shell.md) (ES|QL)
4950
- [Persistence via rc.local/rc.common](./linux/docs/persistence_via_rc_local.md) (ES|QL)
5051
- [Potential Defense Evasion via Multi-Dot Process Execution](./linux/docs/defense_evasion_via_multi_dot_process_execution.md) (ES|QL)
5152
- [Privilege Escalation Identification via Existing Sudoers File](./linux/docs/privilege_escalation_via_existing_sudoers.md) (ES|QL)

hunting/index.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ linux:
220220
mitre:
221221
- T1037.004
222222
- T1546.003
223+
e2e4a1ad-5e03-4968-927c-9ef13c49a3b8:
224+
name: Persistence via Web Shell
225+
path: ./linux/queries/persistence_via_web_shell.toml
226+
mitre:
227+
- T1505.003
223228
okta:
224229
0b936024-71d9-11ef-a9be-f661ea17fbcc:
225230
name: Failed OAuth Access Token Retrieval via Public Client App
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Persistence via Web Shell
2+
3+
---
4+
5+
## Metadata
6+
7+
- **Author:** Elastic
8+
- **Description:** This hunt identifies potential persistence mechanisms leveraging web shells on Linux systems. Web shells are malicious scripts or executables that attackers deploy to provide remote access, execute arbitrary commands, or maintain persistence on compromised systems. This hunt focuses on detecting suspicious file creation events and anomalous network activity associated with known web shell behaviors.
9+
10+
- **UUID:** `e2e4a1ad-5e03-4968-927c-9ef13c49a3b8`
11+
- **Integration:** [endpoint](https://docs.elastic.co/integrations/endpoint)
12+
- **Language:** `[ES|QL]`
13+
- **Source File:** [Persistence via Web Shell](../queries/persistence_via_web_shell.toml)
14+
15+
## Query
16+
17+
```sql
18+
from logs-endpoint.events.file-*
19+
| keep @timestamp, host.os.type, event.action, file.extension, process.name, agent.id, file.name, process.executable
20+
| where @timestamp > now() - 90 day
21+
| where host.os.type == "linux" and event.action in ("rename", "creation") and
22+
file.extension in ("php", "py", "pl", "rb", "rs", "lua", "jsp") and not (
23+
// Add your noisy exclusions here
24+
process.name in ("dnf", "dpkg", "pip3", "pip", "yum", "tar", "code", "vmtoolsd")
25+
)
26+
| stats cc = count(), agent_count = count_distinct(agent.id) by file.name, process.executable
27+
| where agent_count <= 3
28+
| sort cc asc
29+
| limit 100
30+
```
31+
32+
```sql
33+
from logs-endpoint.events.network-*
34+
| keep @timestamp, host.os.type, event.type, event.action, process.name, source.ip, agent.id, process.executable, process.command_line
35+
| where @timestamp > now() - 30 days
36+
| where host.os.type == "linux" and event.type == "end" and event.action == "disconnect_received" and
37+
(
38+
process.name like "ruby*" or
39+
process.name like "perl*" or
40+
process.name like "python*" or
41+
process.name like "php*"
42+
) 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", "172.18.0.0/16")
43+
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable, process.command_line, source.ip
44+
| where agent_count <= 3
45+
| sort cc asc
46+
| limit 100
47+
```
48+
49+
## Notes
50+
51+
- Monitors for the creation or renaming of files with extensions commonly associated with web shells, such as PHP, Python, Perl, Ruby, Lua, and JSP scripts.
52+
- Analyzes network disconnect events to identify anomalous connections initiated by scripting engines, indicating potential use of web shells for remote access.
53+
- Provides statistics and counts to detect rare or unusual activity related to file modifications or network events, helping prioritize investigation efforts.
54+
55+
## MITRE ATT&CK Techniques
56+
57+
- [T1505.003](https://attack.mitre.org/techniques/T1505/003)
58+
59+
## License
60+
61+
- `Elastic License v2`
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
[hunt]
2+
author = "Elastic"
3+
description = """
4+
This hunt identifies potential persistence mechanisms leveraging web shells on Linux systems. Web shells are malicious scripts or executables that attackers deploy to provide remote access, execute arbitrary commands, or maintain persistence on compromised systems. This hunt focuses on detecting suspicious file creation events and anomalous network activity associated with known web shell behaviors.
5+
"""
6+
integration = ["endpoint"]
7+
uuid = "e2e4a1ad-5e03-4968-927c-9ef13c49a3b8"
8+
name = "Persistence via Web Shell"
9+
language = ["ES|QL"]
10+
license = "Elastic License v2"
11+
notes = [
12+
"Monitors for the creation or renaming of files with extensions commonly associated with web shells, such as PHP, Python, Perl, Ruby, Lua, and JSP scripts.",
13+
"Analyzes network disconnect events to identify anomalous connections initiated by scripting engines, indicating potential use of web shells for remote access.",
14+
"Provides statistics and counts to detect rare or unusual activity related to file modifications or network events, helping prioritize investigation efforts."
15+
]
16+
mitre = ["T1505.003"]
17+
18+
query = [
19+
'''
20+
from logs-endpoint.events.file-*
21+
| keep @timestamp, host.os.type, event.action, file.extension, process.name, agent.id, file.name, process.executable
22+
| where @timestamp > now() - 90 day
23+
| where host.os.type == "linux" and event.action in ("rename", "creation") and
24+
file.extension in ("php", "py", "pl", "rb", "rs", "lua", "jsp") and not (
25+
// Add your noisy exclusions here
26+
process.name in ("dnf", "dpkg", "pip3", "pip", "yum", "tar", "code", "vmtoolsd")
27+
)
28+
| stats cc = count(), agent_count = count_distinct(agent.id) by file.name, process.executable
29+
| where agent_count <= 3
30+
| sort cc asc
31+
| limit 100
32+
''',
33+
'''
34+
from logs-endpoint.events.network-*
35+
| keep @timestamp, host.os.type, event.type, event.action, process.name, source.ip, agent.id, process.executable, process.command_line
36+
| where @timestamp > now() - 30 days
37+
| where host.os.type == "linux" and event.type == "end" and event.action == "disconnect_received" and
38+
(
39+
process.name like "ruby*" or
40+
process.name like "perl*" or
41+
process.name like "python*" or
42+
process.name like "php*"
43+
) 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", "172.18.0.0/16")
44+
| stats cc = count(), agent_count = count_distinct(agent.id) by process.executable, process.command_line, source.ip
45+
| where agent_count <= 3
46+
| sort cc asc
47+
| limit 100
48+
'''
49+
]

0 commit comments

Comments
 (0)