From 27635b95ce0bb225fa76d478bc349e38fe61e61d Mon Sep 17 00:00:00 2001 From: Samirbous <64742097+Samirbous@users.noreply.github.com> Date: Wed, 18 Feb 2026 23:31:56 +0000 Subject: [PATCH] [Tuning] High Order Rules fine tuning (#5728) * [Tuning] High Order Rules fine tuning - Exclude High Order Rules as input by other HORs to avoid recursive alerting. - Adjusted the rule name for one rule. - FTS Detection rule using ES|QL - moved the `Esql.rule_name_values = VALUES(kibana.alert.rule.name)` to preserve the original alert name (it get confused with the HOR alert name). * Update impact_alert_from_a_process_with_cpu_spike.toml * Update command_and_control_socks_fortigate_endpoint.toml * Update lateral_movement_multi_alerts_new_srcip.toml * ++ * Update impact_alerts_on_host_with_cpu_spike.toml * Update multiple_alerts_by_host_ip_and_source_ip.toml * Update multiple_alerts_from_different_modules_by_user.toml Removed changes from: - rules/cross-platform/multiple_alerts_llm_attack_chain_triage_by_host.toml - rules/cross-platform/multiple_alerts_llm_compromised_user_triage.toml (selectively cherry picked from commit cf6472005a64805453f868248895884c43725b6f) --- ...and_and_control_socks_fortigate_endpoint.toml | 6 +++--- ...pact_alert_from_a_process_with_cpu_spike.toml | 3 ++- .../impact_alerts_on_host_with_cpu_spike.toml | 3 ++- .../lateral_movement_multi_alerts_new_srcip.toml | 5 +++-- ...lateral_movement_multi_alerts_new_userid.toml | 5 +++-- ...multiple_alerts_by_host_ip_and_source_ip.toml | 7 +++++-- ...e_alerts_from_different_modules_by_dstip.toml | 5 +++-- ...e_alerts_from_different_modules_by_srcip.toml | 5 +++-- ...le_alerts_from_different_modules_by_user.toml | 16 +++++++++++++--- .../multiple_alerts_involving_user.toml | 5 +++-- .../multiple_alerts_risky_host_esql.toml | 8 +++++--- .../multiple_alerts_same_tactic_by_host.toml | 5 +++-- .../multiple_external_edr_alerts_by_host.toml | 5 +++-- ...multiple_machine_learning_jobs_by_entity.toml | 5 +++-- .../newly_observed_elastic_detection_rule.toml | 8 +++++--- 15 files changed, 59 insertions(+), 32 deletions(-) diff --git a/rules/cross-platform/command_and_control_socks_fortigate_endpoint.toml b/rules/cross-platform/command_and_control_socks_fortigate_endpoint.toml index bfc0a4ad8..1c1a7132b 100644 --- a/rules/cross-platform/command_and_control_socks_fortigate_endpoint.toml +++ b/rules/cross-platform/command_and_control_socks_fortigate_endpoint.toml @@ -2,7 +2,7 @@ creation_date = "2025/11/17" integration = ["endpoint", "fortinet_fortigate"] maturity = "production" -updated_date = "2025/11/17" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -16,7 +16,7 @@ from = "now-9m" index = ["logs-endpoint.events.network-*", "logs-fortinet_fortigate.log-*"] language = "eql" license = "Elastic License v2" -name = "SOCKS Traffic from an Unusual Process" +name = "FortiGate SOCKS Traffic from an Unusual Process" references = [ "https://attack.mitre.org/techniques/T1090/", "https://www.elastic.co/docs/reference/integrations/fortinet_fortigate", @@ -44,7 +44,7 @@ sequence by source.port, source.ip, destination.ip with maxspan=1m ''' note = """## Triage and analysis -### Investigating SOCKS Traffic from an Unusual Process +### Investigating FortiGate SOCKS Traffic from an Unusual Process ### Possible investigation steps diff --git a/rules/cross-platform/impact_alert_from_a_process_with_cpu_spike.toml b/rules/cross-platform/impact_alert_from_a_process_with_cpu_spike.toml index efaddb3a1..facd02312 100644 --- a/rules/cross-platform/impact_alert_from_a_process_with_cpu_spike.toml +++ b/rules/cross-platform/impact_alert_from_a_process_with_cpu_spike.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/26" maturity = "production" -updated_date = "2026/01/26" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -65,6 +65,7 @@ type = "esql" query = ''' FROM metrics-*, .alerts-security.* METADATA _index +| where not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | eval // processes with more than 70% total CPU use cpu_metrics_pids = CASE(_index like ".ds-metrics-system.process-*" and system.process.cpu.total.norm.pct >= 0.7, process.pid, null), diff --git a/rules/cross-platform/impact_alerts_on_host_with_cpu_spike.toml b/rules/cross-platform/impact_alerts_on_host_with_cpu_spike.toml index 2f3f06ce9..7c983d6b8 100644 --- a/rules/cross-platform/impact_alerts_on_host_with_cpu_spike.toml +++ b/rules/cross-platform/impact_alerts_on_host_with_cpu_spike.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/26" maturity = "production" -updated_date = "2026/01/26" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -65,6 +65,7 @@ type = "esql" query = ''' FROM metrics-*, .alerts-security.* METADATA _index +| where not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | eval // hosts with more than 90% total CPU use cpu_metrics_host_ids = CASE(_index like ".ds-metrics-system.cpu-*" and system.cpu.total.norm.pct >= 0.9, host.id, null), diff --git a/rules/cross-platform/lateral_movement_multi_alerts_new_srcip.toml b/rules/cross-platform/lateral_movement_multi_alerts_new_srcip.toml index 4988069b7..666ddcb16 100644 --- a/rules/cross-platform/lateral_movement_multi_alerts_new_srcip.toml +++ b/rules/cross-platform/lateral_movement_multi_alerts_new_srcip.toml @@ -1,7 +1,8 @@ [metadata] creation_date = "2026/01/14" maturity = "production" -updated_date = "2026/02/11" +updated_date = "2026/02/16" + [rule] author = ["Elastic"] @@ -34,7 +35,7 @@ FROM .alerts-security.* METADATA _index // Lateral Movement related rules with fields of interest | where kibana.alert.rule.threat.tactic.name is not null and source.ip IS NOT NULL and destination.ip is not null and - host.id is not null and KQL("""kibana.alert.rule.threat.tactic.name : "Lateral Movement" """) + host.id is not null and KQL("""kibana.alert.rule.threat.tactic.name : "Lateral Movement" and not kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // aggregate stats by source.ip | stats Esql.first_time_seen = MIN(@timestamp), diff --git a/rules/cross-platform/lateral_movement_multi_alerts_new_userid.toml b/rules/cross-platform/lateral_movement_multi_alerts_new_userid.toml index 1d0b3e81c..4131539db 100644 --- a/rules/cross-platform/lateral_movement_multi_alerts_new_userid.toml +++ b/rules/cross-platform/lateral_movement_multi_alerts_new_userid.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/14" maturity = "production" -updated_date = "2026/01/14" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -27,7 +27,8 @@ FROM .alerts-security.* METADATA _index // Lateral Movement related rules | where kibana.alert.rule.threat.tactic.name is not null and user.id is not null and (to_string(user.id) like "S-1-5-21*" or to_string(user.id) like "S-1-12-*") and - host.id is not null and KQL("""kibana.alert.rule.threat.tactic.name : "Lateral Movement" """) + host.id is not null and KQL("""kibana.alert.rule.threat.tactic.name : "Lateral Movement" """) and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // aggregate stats by user.id | stats Esql.first_time_seen = MIN(@timestamp), diff --git a/rules/cross-platform/multiple_alerts_by_host_ip_and_source_ip.toml b/rules/cross-platform/multiple_alerts_by_host_ip_and_source_ip.toml index 1ac296fd2..c6700035c 100644 --- a/rules/cross-platform/multiple_alerts_by_host_ip_and_source_ip.toml +++ b/rules/cross-platform/multiple_alerts_by_host_ip_and_source_ip.toml @@ -1,7 +1,8 @@ [metadata] creation_date = "2025/12/31" maturity = "production" -updated_date = "2026/02/11" +updated_date = "2026/02/16" + [rule] author = ["Elastic"] @@ -36,7 +37,9 @@ from .alerts-security.* // any alerts excluding deprecated, low severity and threat_match rules | where kibana.alert.rule.name is not null and kibana.alert.risk_score > 21 and kibana.alert.rule.type != "threat_match" and - not kibana.alert.rule.name like "Deprecated - *" + not kibana.alert.rule.name like "Deprecated - *" and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) and + not kibana.alert.rule.name in ("Abnormally Large DNS Response", "Web Application Suspicious Activity: No User Agent") // alerts with existing source.ip or host.ip | eval alert_source_ip = CASE(source.ip is not null, source.ip, null), diff --git a/rules/cross-platform/multiple_alerts_from_different_modules_by_dstip.toml b/rules/cross-platform/multiple_alerts_from_different_modules_by_dstip.toml index 7f7a92cb9..e2305d701 100644 --- a/rules/cross-platform/multiple_alerts_from_different_modules_by_dstip.toml +++ b/rules/cross-platform/multiple_alerts_from_different_modules_by_dstip.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2025/12/15" maturity = "production" -updated_date = "2025/12/15" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -26,7 +26,8 @@ query = ''' from .alerts-security.* // any alerts excluding low severity, threat_match and machine_learning rules -| where kibana.alert.rule.name is not null and destination.ip is not null and kibana.alert.risk_score > 21 and not kibana.alert.rule.type in ("threat_match", "machine_learning") +| where kibana.alert.rule.name is not null and destination.ip is not null and kibana.alert.risk_score > 21 and not kibana.alert.rule.type in ("threat_match", "machine_learning") and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // group alerts by destination.ip and extract values of interest for alert triage | stats Esql.event_module_distinct_count = COUNT_DISTINCT(event.module), diff --git a/rules/cross-platform/multiple_alerts_from_different_modules_by_srcip.toml b/rules/cross-platform/multiple_alerts_from_different_modules_by_srcip.toml index f732328e3..bb55a3cb8 100644 --- a/rules/cross-platform/multiple_alerts_from_different_modules_by_srcip.toml +++ b/rules/cross-platform/multiple_alerts_from_different_modules_by_srcip.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2025/12/15" maturity = "production" -updated_date = "2025/12/15" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -27,7 +27,8 @@ from .alerts-security.* // any alerts excluding low severity and the noisy ones | where kibana.alert.rule.name is not null and source.ip is not null and kibana.alert.risk_score > 21 and - not kibana.alert.rule.type in ("threat_match", "machine_learning") + not kibana.alert.rule.type in ("threat_match", "machine_learning") and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // group alerts by source.ip and extract values of interest for alert triage | stats Esql.event_module_distinct_count = COUNT_DISTINCT(event.module), diff --git a/rules/cross-platform/multiple_alerts_from_different_modules_by_user.toml b/rules/cross-platform/multiple_alerts_from_different_modules_by_user.toml index 5b995d885..01e24f68e 100644 --- a/rules/cross-platform/multiple_alerts_from_different_modules_by_user.toml +++ b/rules/cross-platform/multiple_alerts_from_different_modules_by_user.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2025/12/15" maturity = "production" -updated_date = "2025/12/15" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -28,8 +28,18 @@ from .alerts-security.* // any alerts excluding low severity and the noisy ones | where kibana.alert.rule.name is not null and user.name is not null and kibana.alert.risk_score > 21 and not kibana.alert.rule.type in ("threat_match", "machine_learning") and - not user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20", "0") - + not user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20", "0") and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) and + // Top noisy influencing rules + // Agent Spoofing - Mismatched Agent ID + // Compression DLL Loaded by Unusual Process + // Process Termination followed by Deletion + // Suspicious PrintSpooler Service Executable File Creation + // Potential PrintNightmare File Modification + // Multiple Vault Web Credentials Read + // Machine Learning Detected a Suspicious Windows Event with a High Malicious Probability Score + not kibana.alert.rule.rule_id in ("3115bd2c-0baa-4df0-80ea-45e474b5ef93", "d197478e-39f0-4347-a22f-ba654718b148", "09443c92-46b3-45a4-8f25-383b028b258d", "5bb4a95d-5a08-48eb-80db-4c3a63ec78a8", "5e87f165-45c2-4b80-bfa5-52822552c997", "44fc462c-1159-4fa8-b1b7-9b6296ab4f96", "994e40aa-8c85-43de-825e-15f665375ee8") + // group alerts by user.name and extract values of interest for alert triage | stats Esql.event_module_distinct_count = COUNT_DISTINCT(event.module), Esql.rule_name_distinct_count = COUNT_DISTINCT(kibana.alert.rule.name), diff --git a/rules/cross-platform/multiple_alerts_involving_user.toml b/rules/cross-platform/multiple_alerts_involving_user.toml index b2632dc25..816005daf 100644 --- a/rules/cross-platform/multiple_alerts_involving_user.toml +++ b/rules/cross-platform/multiple_alerts_involving_user.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2022/11/16" maturity = "production" -updated_date = "2025/12/18" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -25,7 +25,8 @@ query = ''' from .alerts-security.* | where kibana.alert.rule.name is not null and user.id is not null and // Exclude low severity alerts - kibana.alert.risk_score > 21 + kibana.alert.risk_score > 21 and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | stats Esql.rule_name_distinct_count = COUNT_DISTINCT(kibana.alert.rule.name), Esql.rule_id_distinct_count = COUNT_DISTINCT(kibana.alert.rule.rule_id), diff --git a/rules/cross-platform/multiple_alerts_risky_host_esql.toml b/rules/cross-platform/multiple_alerts_risky_host_esql.toml index 4d06c5f37..1f1583c32 100644 --- a/rules/cross-platform/multiple_alerts_risky_host_esql.toml +++ b/rules/cross-platform/multiple_alerts_risky_host_esql.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2025/11/19" maturity = "production" -updated_date = "2025/11/19" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -30,8 +30,10 @@ from .alerts-security.* metadata _id kibana.alert.rule.name IS NOT NULL and host.id is not null and event.dataset is not null and kibana.alert.rule.type != "threat_match" and - not kibana.alert.rule.name in ("Agent Spoofing - Mismatched Agent ID") and - not kibana.alert.rule.name like "Deprecated - *" + // Top noisy influencing rules + not kibana.alert.rule.name in ("Agent Spoofing - Mismatched Agent ID", "Compression DLL Loaded by Unusual Process", "Process Termination followed by Deletion", "Suspicious PrintSpooler Service Executable File Creation", "Potential PrintNightmare File Modification") and + not kibana.alert.rule.name like "Deprecated - *" and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // extract unique counts and values by host.id | stats Esql.alerts_count = COUNT(*), diff --git a/rules/cross-platform/multiple_alerts_same_tactic_by_host.toml b/rules/cross-platform/multiple_alerts_same_tactic_by_host.toml index c26cc2bd2..98c35fce5 100644 --- a/rules/cross-platform/multiple_alerts_same_tactic_by_host.toml +++ b/rules/cross-platform/multiple_alerts_same_tactic_by_host.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/12" maturity = "production" -updated_date = "2026/01/12" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -37,7 +37,8 @@ from .alerts-security.* metadata _id kibana.alert.rule.threat.tactic.name in ("Credential Access", "Defense Evasion", "Execution", "Command and Control") and // excluding some noisy rules - not kibana.alert.rule.name in ("Agent Spoofing - Mismatched Agent ID", "Process Termination followed by Deletion") + not kibana.alert.rule.name in ("Agent Spoofing - Mismatched Agent ID", "Process Termination followed by Deletion") and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) // extract unique counts and values by host.id and tactic name | stats Esql.alerts_count = COUNT(*), diff --git a/rules/cross-platform/multiple_external_edr_alerts_by_host.toml b/rules/cross-platform/multiple_external_edr_alerts_by_host.toml index 5e6c25fbf..de6113d53 100644 --- a/rules/cross-platform/multiple_external_edr_alerts_by_host.toml +++ b/rules/cross-platform/multiple_external_edr_alerts_by_host.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/09" maturity = "production" -updated_date = "2026/01/09" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -25,7 +25,8 @@ query = ''' from .alerts-security.* | WHERE event.dataset in ("crowdstrike.alert", "crowdstrike.falcon", "sentinel_one.alert", "sentinel_one.threat", "m365_defender.alert") and host.id is not null and kibana.alert.risk_score > 21 and - not (event.module == "crowdstrike" and (kibana.alert.rule.name like "* at *" or kibana.alert.rule.name like "* on *" or kibana.alert.rule.name == "EICARTestFileWrittenWin")) + not (event.module == "crowdstrike" and (kibana.alert.rule.name like "* at *" or kibana.alert.rule.name like "* on *" or kibana.alert.rule.name == "EICARTestFileWrittenWin")) and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | stats Esql.alerts_count = COUNT(*), Esql.rule_risk_score_distinct_count = COUNT_DISTINCT(kibana.alert.risk_score), Esql.unique_rules_count = COUNT_DISTINCT(kibana.alert.rule.name), diff --git a/rules/cross-platform/multiple_machine_learning_jobs_by_entity.toml b/rules/cross-platform/multiple_machine_learning_jobs_by_entity.toml index ca7ceda48..7d3aa4b8c 100644 --- a/rules/cross-platform/multiple_machine_learning_jobs_by_entity.toml +++ b/rules/cross-platform/multiple_machine_learning_jobs_by_entity.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/02/02" maturity = "production" -updated_date = "2026/02/02" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -24,7 +24,8 @@ type = "esql" query = ''' from .alerts-security.* -| where kibana.alert.rule.type == "machine_learning" +| where kibana.alert.rule.type == "machine_learning" and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | stats Esql.count_distinct_job_id = COUNT_DISTINCT(job_id), Esql.job_id_values = VALUES(job_id), Esql.rule_name_values = VALUES(kibana.alert.rule.name), diff --git a/rules/cross-platform/newly_observed_elastic_detection_rule.toml b/rules/cross-platform/newly_observed_elastic_detection_rule.toml index aa2420aed..09875a9d3 100644 --- a/rules/cross-platform/newly_observed_elastic_detection_rule.toml +++ b/rules/cross-platform/newly_observed_elastic_detection_rule.toml @@ -1,7 +1,7 @@ [metadata] creation_date = "2026/01/07" maturity = "production" -updated_date = "2026/01/16" +updated_date = "2026/02/16" [rule] author = ["Elastic"] @@ -28,7 +28,8 @@ FROM .alerts-security.* not kibana.alert.rule.type in ("threat_match", "machine_learning", "new_terms") and not kibana.alert.rule.name like "Deprecated - *" and kibana.alert.rule.name != "My First Rule" and // covered by 7306ce7d-5c90-4f42-aa6c-12b0dc2fe3b8 - event.dataset != "endpoint.alerts" + event.dataset != "endpoint.alerts" and + not KQL("""kibana.alert.rule.tags : "Rule Type: Higher-Order Rule" """) | STATS Esql.alerts_count = count(*), Esql.first_time_seen = MIN(@timestamp), Esql.last_time_seen = MAX(@timestamp), @@ -43,7 +44,8 @@ FROM .alerts-security.* Esql.agent_id_values = VALUES(agent.id), Esql.host_id_values = VALUES(host.id), Esql.event_module_values = VALUES(event.module), - Esql.source_ip_values = VALUES(source.ip), + Esql.source_ip_values = VALUES(source.ip), + Esql.rule_name_values = VALUES(kibana.alert.rule.name), Esql.agents_distinct_count = COUNT_DISTINCT(agent.id) by kibana.alert.rule.name // fist time seen in the last 5 days - defined in the rule schedule Additional look-back time | eval Esql.recent = DATE_DIFF("minute", Esql.first_time_seen, now())