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/11/27"
  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"
 22risk_score = 47
 23rule_id = "1d306bf0-7bcf-4acd-83fd-042f5711acc9"
 24setup = """## Setup
 25
 26This rule requires data coming in from both Elastic Defend (for file events) and Network Packet Capture integrations (for HTTP traffic analysis).
 27
 28### Network Packet Capture Integration Setup
 29
 30**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.
 31
 32To enable HTTP request body capture, follow these steps:
 331. Navigate to the Fleet policy leveraging the Network Packet Capture integration in Kibana.
 342. Locate and select the "Network Packet Capture" integration, and edit the integration.
 353. Locate "Change Default", and scroll down to the "HTTP" section.
 364. Enable the "HTTP" toggle to capture HTTP traffic, add the correct ports for your web application, and click "advanced options".
 375. Edit the integration settings to enable HTTP request body capture for POST requests with `multipart/form-data` content type.
 386. Save the integration configuration and wait for the policy to deploy to the agents.
 39"""
 40severity = "medium"
 41tags = [
 42    "Domain: Endpoint",
 43    "Domain: Web",
 44    "Domain: Network",
 45    "OS: Linux",
 46    "OS: Windows",
 47    "OS: macOS",
 48    "Use Case: Threat Detection",
 49    "Tactic: Initial Access",
 50    "Tactic: Persistence",
 51    "Data Source: Elastic Defend",
 52    "Data Source: Network Traffic",
 53]
 54type = "eql"
 55query = '''
 56sequence by agent.id with maxspan=5m
 57  [network where
 58   data_stream.dataset == "network_traffic.http" and
 59   http.request.method in ("POST", "PUT") and
 60   /* We can restrict to 200 in the future, but I prefer to broaden the scope and decrease it later if necessary */
 61   http.response.status_code in (200, 201, 204, 301, 302, 303, 409) and
 62   /* These should detect most common file upload activities, adhering to browser standards */
 63   http.request.body.content like "*Content-Disposition: form-data*" and
 64   http.request.body.content like "*filename=*"
 65   /* May add a lower/upper boundary limit to reduce FPs in the future, e.g.
 66   and http.request.body.bytes >= 500
 67   */
 68  ]
 69  [file where
 70   event.dataset == "endpoint.events.file" and
 71   event.action in ("creation", "rename") and
 72   file.extension in ("php", "phtml", "pht", "php5", "asp", "aspx", "jsp", "jspx", "war", "cgi")
 73   /* We can add file.path values here in the future, if telemetry is noisy */
 74  ]
 75  [network where
 76   data_stream.dataset == "network_traffic.http" and
 77   http.request.method in ("GET", "POST") and
 78   /* we may restrict to 200, but keeping it broader right now */
 79   http.response.status_code >= 200 and http.response.status_code < 600 and
 80   url.extension in ("php", "phtml", "pht", "php5", "asp", "aspx", "jsp", "jspx", "war", "cgi")
 81  ]
 82'''
 83
 84[[rule.threat]]
 85framework = "MITRE ATT&CK"
 86
 87[[rule.threat.technique]]
 88id = "T1190"
 89name = "Exploit Public-Facing Application"
 90reference = "https://attack.mitre.org/techniques/T1190/"
 91
 92[rule.threat.tactic]
 93id = "TA0001"
 94name = "Initial Access"
 95reference = "https://attack.mitre.org/tactics/TA0001/"
 96
 97[[rule.threat]]
 98framework = "MITRE ATT&CK"
 99
100[[rule.threat.technique]]
101id = "T1505"
102name = "Server Software Component"
103reference = "https://attack.mitre.org/techniques/T1505/"
104
105[[rule.threat.technique.subtechnique]]
106id = "T1505.003"
107name = "Web Shell"
108reference = "https://attack.mitre.org/techniques/T1505/003/"
109
110[rule.threat.tactic]
111id = "TA0003"
112name = "Persistence"
113reference = "https://attack.mitre.org/tactics/TA0003/"

Related rules

to-top