Initial Access via File Upload Followed by GET Request

This rule detects potential initial access activity where an adversary uploads a web shell or malicious script to a web server via a file upload mechanism (e.g., through a web form using multipart/form-data), followed by a GET or POST request to access the uploaded file. By checking the body content of HTTP requests for file upload indicators such as "Content-Disposition: form-data" and "filename=", the rule identifies suspicious upload activities. This sequence of actions is commonly used by attackers to gain and maintain access to compromised web servers.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/11/27"
  3integration = ["endpoint", "network_traffic"]
  4maturity = "production"
  5updated_date = "2025/12/08"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10This rule detects potential initial access activity where an adversary uploads a web shell or malicious script
 11to a web server via a file upload mechanism (e.g., through a web form using multipart/form-data), followed by
 12a GET or POST request to access the uploaded file. By checking the body content of HTTP requests for file upload
 13indicators such as "Content-Disposition: form-data" and "filename=", the rule identifies suspicious upload
 14activities. This sequence of actions is commonly used by attackers to gain and maintain access to compromised web
 15servers.
 16"""
 17from = "now-9m"
 18index = ["logs-endpoint.events.*", "logs-network_traffic.*"]
 19language = "eql"
 20license = "Elastic License v2"
 21name = "Initial Access via File Upload Followed by GET Request"
 22note = """## Triage and analysis
 23
 24> **Disclaimer**:
 25> This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.
 26
 27### Investigating Initial Access via File Upload Followed by GET Request
 28
 29This rule flags a common initial-access pattern: a multipart/form-data upload that drops a dynamic web script on a server, followed shortly by a request to execute that file and establish a foothold. Attackers exploit a permissive upload form to plant shell.php or shell.jsp in an uploads or temp directory, then immediately request it to spawn a web shell, enumerate files, and run commands—often leveraging redirects or 2xx/3xx responses that indicate successful placement and access.
 30
 31### Possible investigation steps
 32
 33- Correlate the upload transaction with the server-side file creation and the subsequent access to the same resource, matching timestamps, source IP, and path, and follow any redirects to the final executed file.
 34- Retrieve the uploaded artifact from disk, verify it sits in a web-accessible location, inspect content for web shell traits (eval/system/exec, obfuscation, password gates), and record hashes.
 35- Examine server process telemetry immediately after the access for interpreter or shell spawns and unexpected outbound connections originating from web server workers.
 36- Review application logs and access context to determine whether the upload was authenticated, which account or session performed it, and whether user-agent, referer, or headers deviate from normal clients.
 37- Broaden the timeline to identify related uploads, file renames, or repeated requests from the same actor, including parameterized calls that suggest command execution or directory enumeration.
 38
 39### False positive analysis
 40
 41- An authenticated administrator installs a legitimate plugin or module via the application’s upload form, which unpacks or renames .php or .jsp files and then auto-loads a setup page, producing the multipart upload, file creation/rename, and immediate GET pattern.
 42- Automated deployment or QA routines upload and deploy a .war or server-side script through a web-based admin interface and then perform health-check or warm-up requests, resulting in the same multipart upload, server-side file creation, and follow-up GET sequence.
 43
 44### Response and remediation
 45
 46- Immediately block access to the uploaded script that was invoked via GET/POST (e.g., /uploads/shell.php) and the source IPs that executed it, restrict the site to allowlisted IPs or maintenance mode, and temporarily disable the upload endpoint.
 47- Quarantine and remove the uploaded web shell and any additional executable scripts or WARs in web-accessible directories (uploads, webroot, temp), terminate interpreter or shell processes spawned by the web server account (www-data/nginx/w3wp/tomcat), and revert malicious .htaccess/web.config rewrites.
 48- Hunt for persistence and lateral-movement artifacts created after the upload, including recent .php/.jsp/.cgi file creations or renames in static asset folders, cron/systemd tasks, startup scripts, unauthorized admin users or plugins, and remove them.
 49- Restore altered application files from known-good backups or redeploy a clean container/VM, rotate database and API credentials stored in config files or environment variables, invalidate active sessions, and only re-enable uploads after confirming execution is blocked in upload directories.
 50- Escalate to incident command and privacy/legal if you observe command execution parameters on the uploaded page (?cmd=, ?exec=), shells spawning (/bin/sh, powershell.exe), database dumps, or outbound callbacks from web server processes to external hosts.
 51- Harden by storing uploads outside the webroot, denying execution in upload paths (disable PHP/CGI handlers and set noexec permissions), enforcing strict extension/MIME allowlists and AV/sandbox scanning for multipart/form-data, enabling file-integrity alerts on new .php/.jsp in served paths, and deploying WAF rules to block direct requests to uploaded executables.
 52"""
 53risk_score = 47
 54rule_id = "1d306bf0-7bcf-4acd-83fd-042f5711acc9"
 55setup = """## Setup
 56
 57This rule requires data coming in from both Elastic Defend (for file events) and Network Packet Capture integrations (for HTTP traffic analysis).
 58
 59### Network Packet Capture Integration Setup
 60
 61**IMPORTANT**: This rule requires HTTP request body capture to be enabled in order to detect the multipart/form-data content containing WebKitFormBoundary indicators. The network traffic integration must be configured to capture HTTP request bodies for POST requests with `multipart/form-data` content type.
 62
 63To enable HTTP request body capture, follow these steps:
 641. Navigate to the Fleet policy leveraging the Network Packet Capture integration in Kibana.
 652. Locate and select the "Network Packet Capture" integration, and edit the integration.
 663. Locate "Change Default", and scroll down to the "HTTP" section.
 674. Enable the "HTTP" toggle to capture HTTP traffic, add the correct ports for your web application, and click "advanced options".
 685. Edit the integration settings to enable HTTP request body capture for POST requests with `multipart/form-data` content type.
 696. Save the integration configuration and wait for the policy to deploy to the agents.
 70"""
 71severity = "medium"
 72tags = [
 73    "Domain: Endpoint",
 74    "Domain: Web",
 75    "Domain: Network",
 76    "OS: Linux",
 77    "OS: Windows",
 78    "OS: macOS",
 79    "Use Case: Threat Detection",
 80    "Tactic: Initial Access",
 81    "Tactic: Persistence",
 82    "Data Source: Elastic Defend",
 83    "Data Source: Network Traffic",
 84    "Resources: Investigation Guide",
 85]
 86type = "eql"
 87query = '''
 88sequence by agent.id with maxspan=5m
 89  [network where
 90   data_stream.dataset == "network_traffic.http" and
 91   http.request.method in ("POST", "PUT") and
 92   /* We can restrict to 200 in the future, but I prefer to broaden the scope and decrease it later if necessary */
 93   http.response.status_code in (200, 201, 204, 301, 302, 303, 409) and
 94   /* These should detect most common file upload activities, adhering to browser standards */
 95   http.request.body.content like "*Content-Disposition: form-data*" and
 96   http.request.body.content like "*filename=*"
 97   /* May add a lower/upper boundary limit to reduce FPs in the future, e.g.
 98   and http.request.body.bytes >= 500
 99   */
100  ]
101  [file where
102   event.dataset == "endpoint.events.file" and
103   event.action in ("creation", "rename") and
104   file.extension in ("php", "phtml", "pht", "php5", "asp", "aspx", "jsp", "jspx", "war", "cgi")
105   /* We can add file.path values here in the future, if telemetry is noisy */
106  ]
107  [network where
108   data_stream.dataset == "network_traffic.http" and
109   http.request.method in ("GET", "POST") and
110   /* we may restrict to 200, but keeping it broader right now */
111   http.response.status_code >= 200 and http.response.status_code < 600 and
112   url.extension in ("php", "phtml", "pht", "php5", "asp", "aspx", "jsp", "jspx", "war", "cgi")
113  ]
114'''
115
116[[rule.threat]]
117framework = "MITRE ATT&CK"
118
119[[rule.threat.technique]]
120id = "T1190"
121name = "Exploit Public-Facing Application"
122reference = "https://attack.mitre.org/techniques/T1190/"
123
124[rule.threat.tactic]
125id = "TA0001"
126name = "Initial Access"
127reference = "https://attack.mitre.org/tactics/TA0001/"
128
129[[rule.threat]]
130framework = "MITRE ATT&CK"
131
132[[rule.threat.technique]]
133id = "T1505"
134name = "Server Software Component"
135reference = "https://attack.mitre.org/techniques/T1505/"
136
137[[rule.threat.technique.subtechnique]]
138id = "T1505.003"
139name = "Web Shell"
140reference = "https://attack.mitre.org/techniques/T1505/003/"
141
142[rule.threat.tactic]
143id = "TA0003"
144name = "Persistence"
145reference = "https://attack.mitre.org/tactics/TA0003/"

Triage and analysis

Disclaimer: This investigation guide was created using generative AI technology and has been reviewed to improve its accuracy and relevance. While every effort has been made to ensure its quality, we recommend validating the content and adapting it to suit your specific environment and operational needs.

Investigating Initial Access via File Upload Followed by GET Request

This rule flags a common initial-access pattern: a multipart/form-data upload that drops a dynamic web script on a server, followed shortly by a request to execute that file and establish a foothold. Attackers exploit a permissive upload form to plant shell.php or shell.jsp in an uploads or temp directory, then immediately request it to spawn a web shell, enumerate files, and run commands—often leveraging redirects or 2xx/3xx responses that indicate successful placement and access.

Possible investigation steps

  • Correlate the upload transaction with the server-side file creation and the subsequent access to the same resource, matching timestamps, source IP, and path, and follow any redirects to the final executed file.
  • Retrieve the uploaded artifact from disk, verify it sits in a web-accessible location, inspect content for web shell traits (eval/system/exec, obfuscation, password gates), and record hashes.
  • Examine server process telemetry immediately after the access for interpreter or shell spawns and unexpected outbound connections originating from web server workers.
  • Review application logs and access context to determine whether the upload was authenticated, which account or session performed it, and whether user-agent, referer, or headers deviate from normal clients.
  • Broaden the timeline to identify related uploads, file renames, or repeated requests from the same actor, including parameterized calls that suggest command execution or directory enumeration.

False positive analysis

  • An authenticated administrator installs a legitimate plugin or module via the application’s upload form, which unpacks or renames .php or .jsp files and then auto-loads a setup page, producing the multipart upload, file creation/rename, and immediate GET pattern.
  • Automated deployment or QA routines upload and deploy a .war or server-side script through a web-based admin interface and then perform health-check or warm-up requests, resulting in the same multipart upload, server-side file creation, and follow-up GET sequence.

Response and remediation

  • Immediately block access to the uploaded script that was invoked via GET/POST (e.g., /uploads/shell.php) and the source IPs that executed it, restrict the site to allowlisted IPs or maintenance mode, and temporarily disable the upload endpoint.
  • Quarantine and remove the uploaded web shell and any additional executable scripts or WARs in web-accessible directories (uploads, webroot, temp), terminate interpreter or shell processes spawned by the web server account (www-data/nginx/w3wp/tomcat), and revert malicious .htaccess/web.config rewrites.
  • Hunt for persistence and lateral-movement artifacts created after the upload, including recent .php/.jsp/.cgi file creations or renames in static asset folders, cron/systemd tasks, startup scripts, unauthorized admin users or plugins, and remove them.
  • Restore altered application files from known-good backups or redeploy a clean container/VM, rotate database and API credentials stored in config files or environment variables, invalidate active sessions, and only re-enable uploads after confirming execution is blocked in upload directories.
  • Escalate to incident command and privacy/legal if you observe command execution parameters on the uploaded page (?cmd=, ?exec=), shells spawning (/bin/sh, powershell.exe), database dumps, or outbound callbacks from web server processes to external hosts.
  • Harden by storing uploads outside the webroot, denying execution in upload paths (disable PHP/CGI handlers and set noexec permissions), enforcing strict extension/MIME allowlists and AV/sandbox scanning for multipart/form-data, enabling file-integrity alerts on new .php/.jsp in served paths, and deploying WAF rules to block direct requests to uploaded executables.

Related rules

to-top