From eb3e926a27a51516e919dedcc97f498f0e2032ee Mon Sep 17 00:00:00 2001 From: Ruben Groenewoud Date: Wed, 19 Nov 2025 15:14:26 +0100 Subject: [PATCH 1/4] [New Rule] Web Server Unusual User Agent Request --- ...ssance_web_server_unusual_user_agents.toml | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml diff --git a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml new file mode 100644 index 00000000000..e7e9268fd92 --- /dev/null +++ b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml @@ -0,0 +1,126 @@ +[metadata] +creation_date = "2025/11/19" +integration = ["nginx", "apache", "apache_tomcat", "iis", "network_traffic"] +maturity = "production" +updated_date = "2025/11/19" + +[rule] +author = ["Elastic"] +description = """ +This rule detects unusual spikes in web server requests with uncommon or suspicious user-agent strings. Such activity may +indicate reconnaissance attempts by attackers trying to identify vulnerabilities in web applications or servers. These +user-agents are often associated with automated tools used for scanning, vulnerability assessment, or brute-force attacks. +""" +from = "now-61m" +interval = "1h" +language = "esql" +license = "Elastic License v2" +name = "Web Server Unusual User Agent Request" +risk_score = 21 +rule_id = "a1b7ffa4-bf80-4bf1-86ad-c3f4dc718b35" +severity = "low" +tags = [ + "Domain Scope: Single", + "Domain: Web", + "OS: Linux", + "OS: macOS", + "OS: Windows", + "Use Case: Threat Detection", + "Tactic: Reconnaissance", + "Tactic: Credential Access", + "Data Source: Network Packet Capture", + "Data Source: Nginx", + "Data Source: Apache", + "Data Source: Apache Tomcat", + "Data Source: IIS", +] +timestamp_override = "event.ingested" +type = "esql" +query = ''' +from + logs-network_traffic.http-*, + logs-network_traffic.tls-*, + logs-nginx.access-*, + logs-apache.access-*, + logs-apache_tomcat.access-*, + logs-iis.access-* +| where + @timestamp > now() - 1 hours and + ( + user_agent.original like "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36" or // Nikto + user_agent.original like "nikto*" or // Nikto + user_agent.original like "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" or // Nessus + user_agent.original like "sqlmap/*" or // SQLMap + user_agent.original like "WPScan *" or // WPScan + user_agent.original like "feroxbuster/*" or // Feroxbuster + user_agent.original like "masscan*" or // Masscan & masscan-ng + user_agent.original like "Fuzz*" or // Ffuf + user_agent.original like "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/user_agent.original like~ 87.0.4280.88 Safari/537.36" or // Dirsearch + user_agent.original like "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" or // Dirb + user_agent.original like "DirBuster*" or // Dirbuster + user_agent.original like "gobuster/*" or // Gobuster + user_agent.original like "*nmap*" or // Nmap Scripting Engine + user_agent.original like "*hydra*" // Hydra Brute Forcer + ) +| keep + @timestamp, + event.dataset, + user_agent.original, + url.path, + source.ip, + agent.id, + host.name +| stats + Esql.event_count = count(), + Esql.url_path_count_distinct = count_distinct(url.path), + Esql.host_name_values = values(host.name), + Esql.agent_id_values = values(agent.id), + Esql.url_path_values = values(url.path), + Esql.user_agent_original_values = values(user_agent.original), + Esql.event_dataset_values = values(event.dataset) + by source.ip +| where + Esql.event_count > 50 and Esql.url_path_count_distinct > 10 +| limit 100 +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1595" +name = "Active Scanning" +reference = "https://attack.mitre.org/techniques/T1595/" + +[[rule.threat.technique.subtechnique]] +id = "T1595.001" +name = "Scanning IP Blocks" +reference = "https://attack.mitre.org/techniques/T1595/001/" + +[[rule.threat.technique.subtechnique]] +id = "T1595.002" +name = "Vulnerability Scanning" +reference = "https://attack.mitre.org/techniques/T1595/002/" + +[[rule.threat.technique.subtechnique]] +id = "T1595.003" +name = "Wordlist Scanning" +reference = "https://attack.mitre.org/techniques/T1595/003/" + +[rule.threat.tactic] +id = "TA0043" +name = "Reconnaissance" +reference = "https://attack.mitre.org/tactics/TA0043/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1110" +name = "Brute Force" +reference = "https://attack.mitre.org/techniques/T1110/" + +[rule.threat.tactic] +id = "TA0006" +name = "Credential Access" +reference = "https://attack.mitre.org/tactics/TA0006/" From 1683a4cf64e60c57b8e4649337d0b4b8157ca00c Mon Sep 17 00:00:00 2001 From: Ruben Groenewoud Date: Wed, 19 Nov 2025 15:15:07 +0100 Subject: [PATCH 2/4] [New Rule] Web Server Suspicious User Agent Request Spike --- .../reconnaissance_web_server_unusual_user_agents.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml index e7e9268fd92..375c36bf698 100644 --- a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml +++ b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml @@ -15,7 +15,7 @@ from = "now-61m" interval = "1h" language = "esql" license = "Elastic License v2" -name = "Web Server Unusual User Agent Request" +name = "Web Server Suspicious User Agent Request Spike" risk_score = 21 rule_id = "a1b7ffa4-bf80-4bf1-86ad-c3f4dc718b35" severity = "low" From 38c85839264f8361ff86c375c9cafbbd4eaa643c Mon Sep 17 00:00:00 2001 From: Ruben Groenewoud <78494512+Aegrah@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:41:36 +0100 Subject: [PATCH 3/4] Update reconnaissance_web_server_unusual_user_agents.toml --- ...connaissance_web_server_unusual_user_agents.toml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml index 375c36bf698..90293af31aa 100644 --- a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml +++ b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml @@ -22,6 +22,7 @@ severity = "low" tags = [ "Domain Scope: Single", "Domain: Web", + "Domain: Network", "OS: Linux", "OS: macOS", "OS: Windows", @@ -45,7 +46,8 @@ from logs-apache_tomcat.access-*, logs-iis.access-* | where - @timestamp > now() - 1 hours and + @timestamp > now() - 1 hours and + (url.original is not null or url.full is not null) and ( user_agent.original like "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36" or // Nikto user_agent.original like "nikto*" or // Nikto @@ -62,6 +64,10 @@ from user_agent.original like "*nmap*" or // Nmap Scripting Engine user_agent.original like "*hydra*" // Hydra Brute Forcer ) + +| eval Esql_url_text = case(url.original is not null, url.original, url.full) +| eval Esql_url_lower = to_lower(Esql_url_text) + | keep @timestamp, event.dataset, @@ -69,13 +75,14 @@ from url.path, source.ip, agent.id, - host.name + host.name, + Esql_url_lower | stats Esql.event_count = count(), Esql.url_path_count_distinct = count_distinct(url.path), Esql.host_name_values = values(host.name), Esql.agent_id_values = values(agent.id), - Esql.url_path_values = values(url.path), + Esql.url_path_values = values(Esql_url_lower), Esql.user_agent_original_values = values(user_agent.original), Esql.event_dataset_values = values(event.dataset) by source.ip From cb2fd7572502cb1b19cd28f814550b4514b44063 Mon Sep 17 00:00:00 2001 From: Ruben Groenewoud <78494512+Aegrah@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:46:57 +0100 Subject: [PATCH 4/4] Update reconnaissance_web_server_unusual_user_agents.toml --- .../reconnaissance_web_server_unusual_user_agents.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml index 90293af31aa..953990cc22f 100644 --- a/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml +++ b/rules/cross-platform/reconnaissance_web_server_unusual_user_agents.toml @@ -72,14 +72,13 @@ from @timestamp, event.dataset, user_agent.original, - url.path, source.ip, agent.id, host.name, Esql_url_lower | stats Esql.event_count = count(), - Esql.url_path_count_distinct = count_distinct(url.path), + Esql.url_path_count_distinct = count_distinct(Esql_url_lower), Esql.host_name_values = values(host.name), Esql.agent_id_values = values(agent.id), Esql.url_path_values = values(Esql_url_lower),