Web Server Local File Inclusion Activity

This rule detects potential Local File Inclusion (LFI) activity on web servers by identifying HTTP GET requests that attempt to access sensitive local files through directory traversal techniques or known file paths. Attackers may exploit LFI vulnerabilities to read sensitive files, gain system information, or further compromise the server.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/12/02"
  3integration = ["nginx", "apache", "apache_tomcat", "iis"]
  4maturity = "production"
  5min_stack_version = "9.2.0"
  6min_stack_comments = "The esql url_decode() operator was introduced in version 9.2.0"
  7updated_date = "2025/12/02"
  8
  9[rule]
 10author = ["Elastic"]
 11description = """
 12This rule detects potential Local File Inclusion (LFI) activity on web servers by identifying HTTP GET requests that
 13attempt to access sensitive local files through directory traversal techniques or known file paths. Attackers may
 14exploit LFI vulnerabilities to read sensitive files, gain system information, or further compromise the server.
 15"""
 16from = "now-11m"
 17interval = "10m"
 18language = "esql"
 19license = "Elastic License v2"
 20name = "Web Server Local File Inclusion Activity"
 21risk_score = 21
 22rule_id = "90e4ceab-79a5-4f8e-879b-513cac7fcad9"
 23severity = "low"
 24tags = [
 25    "Domain: Web",
 26    "Use Case: Threat Detection",
 27    "Tactic: Discovery",
 28    "Data Source: Nginx",
 29    "Data Source: Apache",
 30    "Data Source: Apache Tomcat",
 31    "Data Source: IIS",
 32]
 33timestamp_override = "event.ingested"
 34type = "esql"
 35query = '''
 36from
 37  logs-nginx.access-*,
 38  logs-apache.access-*,
 39  logs-apache_tomcat.access-*,
 40  logs-iis.access-*
 41| where
 42    http.request.method == "GET" and
 43    http.response.status_code == 200 and
 44    url.original like "*=*"
 45
 46| eval Esql.url_original_url_decoded_to_lower = to_lower(URL_DECODE(url.original))
 47
 48| where
 49  /* 1) Relative traversal */
 50    Esql.url_original_url_decoded_to_lower like "*../../../../*" or           // Unix-style traversal
 51    Esql.url_original_url_decoded_to_lower like "*..\\\\..\\\\..\\\\..*" or           // Windows-style traversal
 52    // Potential security check bypassing (enforcing multiple dots and shortening the pattern)
 53    Esql.url_original_url_decoded_to_lower like "*..././*" or
 54    Esql.url_original_url_decoded_to_lower like "*...\\*" or
 55    Esql.url_original_url_decoded_to_lower like "*....\\*" or
 56
 57  /* 2) Linux system identity / basic info */
 58    Esql.url_original_url_decoded_to_lower like "*etc/passwd*" or
 59    Esql.url_original_url_decoded_to_lower like "*etc/shadow*" or
 60    Esql.url_original_url_decoded_to_lower like "*etc/hosts*" or
 61    Esql.url_original_url_decoded_to_lower like "*etc/os-release*" or
 62    Esql.url_original_url_decoded_to_lower like "*etc/issue*" or
 63
 64  /* 3) Linux /proc enumeration */
 65    Esql.url_original_url_decoded_to_lower like "*proc/self/environ*" or
 66    Esql.url_original_url_decoded_to_lower like "*proc/self/cmdline*" or
 67    Esql.url_original_url_decoded_to_lower like "*proc/self/fd*" or
 68    Esql.url_original_url_decoded_to_lower like "*proc/self/exe*" or
 69
 70  /* 4) Linux webroots, configs & logs */
 71    Esql.url_original_url_decoded_to_lower like "*var/www*" or               // generic webroot
 72    Esql.url_original_url_decoded_to_lower like "*wp-config.php*" or         // classic WP config
 73    Esql.url_original_url_decoded_to_lower like "*etc/apache2*" or
 74    Esql.url_original_url_decoded_to_lower like "*etc/httpd*" or
 75    Esql.url_original_url_decoded_to_lower like "*etc/nginx*" or
 76    Esql.url_original_url_decoded_to_lower like "*var/log/apache2*" or
 77    Esql.url_original_url_decoded_to_lower like "*var/log/httpd*" or
 78    Esql.url_original_url_decoded_to_lower like "*var/log/nginx*" or
 79
 80  /* 5) Windows core files / identity */
 81    Esql.url_original_url_decoded_to_lower like "*windows/panther/*unattend*" or
 82    Esql.url_original_url_decoded_to_lower like "*windows/debug/netsetup.log*" or
 83    Esql.url_original_url_decoded_to_lower like "*windows/win.ini*" or
 84    Esql.url_original_url_decoded_to_lower like "*windows/system32/drivers/etc/hosts*" or
 85    Esql.url_original_url_decoded_to_lower like "*boot.ini*" or
 86    Esql.url_original_url_decoded_to_lower like "*windows/system32/config/*" or
 87    Esql.url_original_url_decoded_to_lower like "*windows/repair/sam*" or
 88    Esql.url_original_url_decoded_to_lower like "*windows/system32/license.rtf*" or
 89
 90  /* 6) Windows IIS / .NET configs, webroots & logs */
 91     Esql.url_original_url_decoded_to_lower like "*/inetpub/wwwroot*" or
 92     Esql.url_original_url_decoded_to_lower like "*/inetpub/logs/logfiles*" or
 93     Esql.url_original_url_decoded_to_lower like "*applicationhost.config*" or
 94     Esql.url_original_url_decoded_to_lower like "*/microsoft.net/framework64/*/config/web.config*" or
 95     Esql.url_original_url_decoded_to_lower like "*windows/system32/inetsrv/*" or
 96
 97  /* 7) PHP & protocol wrappers */
 98     Esql.url_original_url_decoded_to_lower like "*php://*" or
 99     Esql.url_original_url_decoded_to_lower like "*zip://*" or
100     Esql.url_original_url_decoded_to_lower like "*phar://*" or
101     Esql.url_original_url_decoded_to_lower like "*expect://*" or
102     Esql.url_original_url_decoded_to_lower like "*file://*" or
103     Esql.url_original_url_decoded_to_lower like "*data://text/plain;base64*"
104
105| keep
106    @timestamp,
107    Esql.url_original_url_decoded_to_lower,
108    source.ip,
109    agent.id,
110    host.name,
111    http.request.method,
112    http.response.status_code,
113    event.dataset,
114    data_stream.namespace
115
116| stats
117    Esql.event_count = count(),
118    Esql.url_original_url_decoded_to_lower_count_distinct = count_distinct(Esql.url_original_url_decoded_to_lower),
119    Esql.host_name_values = values(host.name),
120    Esql.agent_id_values = values(agent.id),
121    Esql.http_request_method_values = values(http.request.method),
122    Esql.http_response_status_code_values = values(http.response.status_code),
123    Esql.url_original_url_decoded_to_lower_values = values(Esql.url_original_url_decoded_to_lower),
124    Esql.event_dataset_values = values(event.dataset),
125    Esql.data_stream_namespace_values = values(data_stream.namespace)
126    by source.ip
127'''
128
129[[rule.threat]]
130framework = "MITRE ATT&CK"
131
132[[rule.threat.technique]]
133id = "T1083"
134name = "File and Directory Discovery"
135reference = "https://attack.mitre.org/techniques/T1083/"
136
137[rule.threat.tactic]
138id = "TA0007"
139name = "Discovery"
140reference = "https://attack.mitre.org/tactics/TA0007/"

Related rules

to-top