Skip to content

Commit d5d9541

Browse files
committed
[New Rule] Web Server Potential Command Injection Request
1 parent f0e9281 commit d5d9541

File tree

1 file changed

+169
-0
lines changed

1 file changed

+169
-0
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
[metadata]
2+
creation_date = "2025/11/19"
3+
integration = ["nginx", "apache", "apache_tomcat", "iis", "network_traffic"]
4+
maturity = "production"
5+
updated_date = "2025/11/19"
6+
7+
[rule]
8+
author = ["Elastic"]
9+
description = """
10+
This rule detects potential command injection attempts via web server requests by identifying URLs that contain
11+
suspicious patterns commonly associated with command execution payloads. Attackers may exploit vulnerabilities in web
12+
applications to inject and execute arbitrary commands on the server, often using interpreters like Python, Perl, Ruby,
13+
PHP, or shell commands. By monitoring for these indicators in web traffic, security teams can identify and respond to
14+
potential threats early.
15+
"""
16+
from = "now-61m"
17+
interval = "1h"
18+
language = "esql"
19+
license = "Elastic License v2"
20+
name = "Web Server Potential Command Injection Request"
21+
risk_score = 21
22+
rule_id = "f3ac6734-7e52-4a0d-90b7-6847bf4308f2"
23+
severity = "low"
24+
tags = [
25+
"Domain Scope: Single",
26+
"Domain: Web",
27+
"OS: Linux",
28+
"OS: macOS",
29+
"OS: Windows",
30+
"Use Case: Threat Detection",
31+
"Tactic: Reconnaissance",
32+
"Tactic: Credential Access",
33+
"Data Source: Network Packet Capture",
34+
"Data Source: Nginx",
35+
"Data Source: Apache",
36+
"Data Source: Apache Tomcat",
37+
"Data Source: IIS",
38+
]
39+
timestamp_override = "event.ingested"
40+
type = "esql"
41+
query = '''
42+
from
43+
logs-network_traffic.http-*,
44+
logs-network_traffic.tls-*,
45+
logs-nginx.access-*,
46+
logs-apache.access-*,
47+
logs-apache_tomcat.access-*,
48+
logs-iis.access-*
49+
| where
50+
@timestamp > now() - 1d and
51+
(url.original is not null or url.full is not null)
52+
53+
| eval esql_url_text = case(url.original is not null, url.original, url.full)
54+
| eval esql_url_lower = to_lower(esql_url_text)
55+
56+
| eval contains_interpreter = case(esql_url_lower like "*python* -c*" or esql_url_lower like "*perl* -e*" or esql_url_lower like "*ruby* -e*" or esql_url_lower like "*ruby* -rsocket*" or esql_url_lower like "*lua* -e*" or esql_url_lower like "*php* -r*" or esql_url_lower like "*node* -e*", 1, 0)
57+
| eval contains_shell = case(esql_url_lower like "*/bin/bash*" or esql_url_lower like "*bash*-c*" or esql_url_lower like "*/bin/sh*" or esql_url_lower rlike "*sh.{1,2}-c*", 1, 0)
58+
| eval contains_nc = case(esql_url_lower like "*netcat*" or esql_url_lower like "*ncat*" or esql_url_lower rlike """.*nc.{1,2}[0-9]{1,3}(\.[0-9]{1,3}){3}.{1,2}[0-9]{1,5}.*""" or esql_url_lower like "*nc.openbsd*" or esql_url_lower like "*nc.traditional*" or esql_url_lower like "*socat*", 1, 0)
59+
| eval contains_devtcp = case(esql_url_lower like "*/dev/tcp/*" or esql_url_lower like "*/dev/udp/*", 1, 0)
60+
| eval contains_helpers = case(esql_url_lower like "*mkfifo*" or esql_url_lower like "*nohup*" or esql_url_lower like "*setsid*" or esql_url_lower like "*busybox*", 1, 0)
61+
| eval contains_sus_cli = case(esql_url_lower like "*import*pty*spawn*" or esql_url_lower like "*import*subprocess*call*" or esql_url_lower like "*tcpsocket.new*" or esql_url_lower like "*tcpsocket.open*" or esql_url_lower like "*io.popen*" or esql_url_lower like "*os.execute*" or esql_url_lower like "*fsockopen*", 1, 0)
62+
| eval contains_privileges = case(esql_url_lower like "*chmod*" or esql_url_lower like "*chown*", 1, 0)
63+
| eval contains_downloader = case(esql_url_lower like "*curl *" or esql_url_lower like "*wget *" , 1, 0)
64+
| eval contains_file_read_keywords = case(esql_url_lower like "*/etc/shadow*" or esql_url_lower like "*/etc/passwd*" or esql_url_lower like "*/root/.ssh/*" or esql_url_lower like "*/home/*/.ssh/*" or esql_url_lower like "*~/.ssh/*" or esql_url_lower like "*/proc/self/environ*", 1, 0)
65+
| eval contains_base64_cmd = case(esql_url_lower like "*base64*-d*" or esql_url_lower like "*xxd*" or esql_url_lower like "*echo*|*base64*", 1, 0)
66+
| eval contains_suspicious_path = case(esql_url_lower like "*/tmp/*" or esql_url_lower like "*/var/tmp/*" or esql_url_lower like "*/dev/shm/*" or esql_url_lower like "*/root/*" or esql_url_lower like "*/home/*/*" or esql_url_lower like "*/var/www/*" or esql_url_lower like "*/etc/cron.*/*", 1, 0)
67+
68+
| eval any_payload_keyword = case(
69+
contains_interpreter == 1 or contains_shell == 1 or contains_nc == 1 or contains_devtcp == 1 or
70+
contains_helpers == 1 or contains_sus_cli == 1 or contains_privileges == 1 or contains_downloader == 1 or
71+
contains_file_read_keywords == 1 or contains_base64_cmd == 1 or contains_suspicious_path == 1, 1, 0)
72+
73+
| keep
74+
@timestamp,
75+
esql_url_lower,
76+
any_payload_keyword,
77+
contains_interpreter,
78+
contains_shell,
79+
contains_nc,
80+
contains_devtcp,
81+
contains_helpers,
82+
contains_sus_cli,
83+
contains_privileges,
84+
contains_downloader,
85+
contains_file_read_keywords,
86+
contains_base64_cmd,
87+
contains_suspicious_path,
88+
source.ip,
89+
destination.ip,
90+
agent.id,
91+
http.request.method,
92+
http.response.status_code,
93+
user_agent.original
94+
95+
| where any_payload_keyword == 1
96+
| limit 100
97+
'''
98+
99+
[[rule.threat]]
100+
framework = "MITRE ATT&CK"
101+
102+
[[rule.threat.technique]]
103+
id = "T1505"
104+
name = "Server Software Component"
105+
reference = "https://attack.mitre.org/techniques/T1505/"
106+
107+
[[rule.threat.technique.subtechnique]]
108+
id = "T1505.003"
109+
name = "Web Shell"
110+
reference = "https://attack.mitre.org/techniques/T1505/003/"
111+
112+
[rule.threat.tactic]
113+
id = "TA0003"
114+
name = "Persistence"
115+
reference = "https://attack.mitre.org/tactics/TA0003/"
116+
117+
[[rule.threat]]
118+
framework = "MITRE ATT&CK"
119+
120+
[[rule.threat.technique]]
121+
id = "T1059"
122+
name = "Command and Scripting Interpreter"
123+
reference = "https://attack.mitre.org/techniques/T1059/"
124+
125+
[[rule.threat.technique.subtechnique]]
126+
id = "T1059.004"
127+
name = "Unix Shell"
128+
reference = "https://attack.mitre.org/techniques/T1059/004/"
129+
130+
[rule.threat.tactic]
131+
id = "TA0002"
132+
name = "Execution"
133+
reference = "https://attack.mitre.org/tactics/TA0002/"
134+
135+
[[rule.threat]]
136+
framework = "MITRE ATT&CK"
137+
138+
[[rule.threat.technique]]
139+
id = "T1071"
140+
name = "Application Layer Protocol"
141+
reference = "https://attack.mitre.org/techniques/T1071/"
142+
143+
[rule.threat.tactic]
144+
id = "TA0011"
145+
name = "Command and Control"
146+
reference = "https://attack.mitre.org/tactics/TA0011/"
147+
148+
[[rule.threat]]
149+
framework = "MITRE ATT&CK"
150+
151+
[[rule.threat.technique]]
152+
id = "T1595"
153+
name = "Active Scanning"
154+
reference = "https://attack.mitre.org/techniques/T1595/"
155+
156+
[[rule.threat.technique.subtechnique]]
157+
id = "T1595.002"
158+
name = "Vulnerability Scanning"
159+
reference = "https://attack.mitre.org/techniques/T1595/002/"
160+
161+
[[rule.threat.technique.subtechnique]]
162+
id = "T1595.003"
163+
name = "Wordlist Scanning"
164+
reference = "https://attack.mitre.org/techniques/T1595/003/"
165+
166+
[rule.threat.tactic]
167+
id = "TA0043"
168+
name = "Reconnaissance"
169+
reference = "https://attack.mitre.org/tactics/TA0043/"

0 commit comments

Comments
 (0)