Detection rules › Elastic
Suspicious File Creation via Web Server
This rule detects suspicious file uploads to web servers. Attackers may exploit RCE or file upload vulnerabilities to upload malicious files to web servers to gain/maintain access and to establish a command and control channel.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Execution | |
| Persistence | |
| Command & Control |
Rule body
[rule]
description = """
This rule detects suspicious file uploads to web servers. Attackers may exploit RCE or file upload vulnerabilities to
upload malicious files to web servers to gain/maintain access and to establish a command and control channel.
"""
id = "a67ef648-f04e-475c-8f53-a2db038ee834"
license = "Elastic License v2"
name = "Suspicious File Creation via Web Server"
os_list = ["linux"]
version = "1.0.7"
query = '''
sequence by process.entity_id with maxspan=3s
[network where event.type == "start" and event.action == "connection_accepted" and not (
source.ip == null or source.ip == "0.0.0.0" or cidrmatch(
source.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"
)
)
]
[file where event.type == "change" and event.action in ("rename", "creation") and
file.extension in ("py", "pl", "rb", "elf", "so", "rs", "lua", "jpeg", "md", "sh", "jsp") and (
user.name in (
"apache", "www-data", "httpd", "nginx", "lighttpd", "tomcat", "tomcat8", "tomcat9", "ftp", "ftpuser", "ftpd"
) or
user.id in (99, 33, 498, 48)
) and (
file.path : ("/var/www/*", "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/root/*", "/home/*") and
process.name : (
"apache", "nginx", "apache2", "httpd", "lighttpd", "caddy", "php-*", "node", "mongrel_rails", "gunicorn",
"uwsgi", "openresty", "cherokee", "h2o", "resin", "puma", "unicorn", "traefik", "tornado", "hypercorn",
"daphne", "twistd", "yaws", "webfsd", "httpd.worker", "flask", "rails", "mongrel"
)
) or
(process.name : ("ruby*", "perl*", "python*", "java") and file.path : "/var/www/*") and
not (
file.name in (
"config-livewaf.php", "pageviews-busy.php", "attack-data.php", "config-synced.php", "packages.php", "README.txt"
) or
file.name like~ "cookie*.txt" or
file.path like ("/tmp/requestdir/*", "/var/www/html/storage*", "/var/www/*/Cache/*", "/var/www/*/cache/*") or
file.extension like ("log", "*-*-*", "webm") or
process.executable like~ "/root/miniconda3/bin/python*"
)
]
'''
min_endpoint_version = "7.15.0"
optional_actions = []
[[actions]]
action = "kill_process"
field = "process.entity_id"
state = 0
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1059"
name = "Command and Scripting Interpreter"
reference = "https://attack.mitre.org/techniques/T1059/"
[[threat.technique.subtechnique]]
id = "T1059.004"
name = "Unix Shell"
reference = "https://attack.mitre.org/techniques/T1059/004/"
[threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1505"
name = "Server Software Component"
reference = "https://attack.mitre.org/techniques/T1505/"
[[threat.technique.subtechnique]]
id = "T1505.003"
name = "Web Shell"
reference = "https://attack.mitre.org/techniques/T1505/003/"
[threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[[threat]]
framework = "MITRE ATT&CK"
[[threat.technique]]
id = "T1071"
name = "Application Layer Protocol"
reference = "https://attack.mitre.org/techniques/T1071/"
[threat.tactic]
id = "TA0011"
name = "Command and Control"
reference = "https://attack.mitre.org/tactics/TA0011/"
[internal]
min_endpoint_version = "7.15.0"
Stages and Predicates
Ordered sequence: each step below must occur in order within 3s, correlated by process.entity_id.
Stage 1: network
[network where event.type == "start" and event.action == "connection_accepted" and not (
source.ip == null or source.ip == "0.0.0.0" or cidrmatch(
source.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"
)
)
]
Stage 2: file
[file where event.type == "change" and event.action in ("rename", "creation") and
file.extension in ("py", "pl", "rb", "elf", "so", "rs", "lua", "jpeg", "md", "sh", "jsp") and (
user.name in (
"apache", "www-data", "httpd", "nginx", "lighttpd", "tomcat", "tomcat8", "tomcat9", "ftp", "ftpuser", "ftpd"
) or
user.id in (99, 33, 498, 48)
) and (
file.path : ("/var/www/*", "/tmp/*", "/var/tmp/*", "/dev/shm/*", "/root/*", "/home/*") and
process.name : (
"apache", "nginx", "apache2", "httpd", "lighttpd", "caddy", "php-*", "node", "mongrel_rails", "gunicorn",
"uwsgi", "openresty", "cherokee", "h2o", "resin", "puma", "unicorn", "traefik", "tornado", "hypercorn",
"daphne", "twistd", "yaws", "webfsd", "httpd.worker", "flask", "rails", "mongrel"
)
) or
(process.name : ("ruby*", "perl*", "python*", "java") and file.path : "/var/www/*") and
not (
file.name in (
"config-livewaf.php", "pageviews-busy.php", "attack-data.php", "config-synced.php", "packages.php", "README.txt"
) or
file.name like~ "cookie*.txt" or
file.path like ("/tmp/requestdir/*", "/var/www/html/storage*", "/var/www/*/Cache/*", "/var/www/*/cache/*") or
file.extension like ("log", "*-*-*", "webm") or
process.executable like~ "/root/miniconda3/bin/python*"
)
]
Exclusions
The rule actively suppresses these predicates.
| Field | Kind | Excluded values | Search |
|---|---|---|---|
source.ip | cidr_match | 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 | excludes:source.ip |
source.ip | eq | 0.0.0.0 | excludes:source.ip field:"source.ip" value:"0.0.0.0" |
source.ip | is_null | excludes:source.ip |
Indicators
These rows show field, operator, and value matches.
| Field | Kind | Values | Search |
|---|---|---|---|
event.action | eq |
| field:"EventType" kind:eq value:"connection_accepted" |
event.action | in |
| field:"EventType" kind:in |
event.type | eq |
| field:"event.type" kind:eq |
file.extension | in |
| field:"file.extension" kind:in |
file.path | wildcard |
| field:"TargetFilename" kind:wildcard |
process.name | wildcard |
| field:"process_name" kind:wildcard |
user.id | in |
| field:"user.id" kind:in |
user.name | in |
| field:"user" kind:in |