diff --git a/.tests/opnsense-sshd/scenario.assert b/.tests/opnsense-sshd/scenario.assert index 655138b078c..033017302fd 100644 --- a/.tests/opnsense-sshd/scenario.assert +++ b/.tests/opnsense-sshd/scenario.assert @@ -4,7 +4,7 @@ results[0].Overflow.Sources["1.2.3.4"].IP == "1.2.3.4" results[0].Overflow.Sources["1.2.3.4"].Range == "" results[0].Overflow.Sources["1.2.3.4"].GetScope() == "Ip" results[0].Overflow.Sources["1.2.3.4"].GetValue() == "1.2.3.4" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[0].GetMeta("machine") == "OPNsense.localdomain" @@ -12,7 +12,7 @@ results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "1.2.3.4" results[0].Overflow.Alert.Events[0].GetMeta("target_user") == "tutu" results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2022-01-19T14:23:55Z" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[1].GetMeta("machine") == "OPNsense.localdomain" @@ -20,7 +20,7 @@ results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "1.2.3.4" results[0].Overflow.Alert.Events[1].GetMeta("target_user") == "tutu" results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2022-01-19T14:23:56Z" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[2].GetMeta("machine") == "OPNsense.localdomain" @@ -28,7 +28,7 @@ results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "1.2.3.4" results[0].Overflow.Alert.Events[2].GetMeta("target_user") == "tutu" results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2022-01-19T14:23:56Z" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[3].GetMeta("machine") == "OPNsense.localdomain" @@ -36,7 +36,7 @@ results[0].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "1.2.3.4" results[0].Overflow.Alert.Events[3].GetMeta("target_user") == "tutu" results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2022-01-19T14:23:57Z" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[4].GetMeta("machine") == "OPNsense.localdomain" @@ -44,7 +44,7 @@ results[0].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "1.2.3.4" results[0].Overflow.Alert.Events[4].GetMeta("target_user") == "tutu" results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2022-01-19T14:23:57Z" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "opnsense-sshd.log" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "opnsense-sshd.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[5].GetMeta("machine") == "OPNsense.localdomain" diff --git a/.tests/ssh-bf/scenario.assert b/.tests/ssh-bf/scenario.assert index a633d367fd4..ae58dc7535c 100644 --- a/.tests/ssh-bf/scenario.assert +++ b/.tests/ssh-bf/scenario.assert @@ -4,42 +4,54 @@ results[0].Overflow.Sources["35.188.49.176"].IP == "35.188.49.176" results[0].Overflow.Sources["35.188.49.176"].Range == "" results[0].Overflow.Sources["35.188.49.176"].GetScope() == "Ip" results[0].Overflow.Sources["35.188.49.176"].GetValue() == "35.188.49.176" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "ssh-bf.log" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[0].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[0].GetMeta("target_user") == "pascal" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "ssh-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-02-12T14:10:21Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[1].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[1].GetMeta("target_user") == "pascal1" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "ssh-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-02-12T14:10:21Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[2].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[2].GetMeta("target_user") == "pascal2" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "ssh-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-02-12T14:10:22Z" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[3].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[3].GetMeta("target_user") == "pascal3" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "ssh-bf.log" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-02-12T14:10:22Z" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[4].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[4].GetMeta("target_user") == "pascal4" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "ssh-bf.log" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-02-12T14:10:23Z" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "ssh-bf.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[5].GetMeta("machine") == "sd-126005" results[0].Overflow.Alert.Events[5].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "35.188.49.176" results[0].Overflow.Alert.Events[5].GetMeta("target_user") == "pascal5" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2026-02-12T14:10:24Z" results[0].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-bf_user-enum" results[0].Overflow.Alert.Remediation == true results[0].Overflow.Alert.GetEventsCount() == 6 @@ -48,43 +60,54 @@ results[1].Overflow.Sources["35.188.49.176"].IP == "35.188.49.176" results[1].Overflow.Sources["35.188.49.176"].Range == "" results[1].Overflow.Sources["35.188.49.176"].GetScope() == "Ip" results[1].Overflow.Sources["35.188.49.176"].GetValue() == "35.188.49.176" -results[1].Overflow.Alert.Events[0].GetMeta("datasource_path") == "ssh-bf.log" +basename(results[1].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[0].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[0].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[0].GetMeta("target_user") == "pascal" -results[1].Overflow.Alert.Events[1].GetMeta("datasource_path") == "ssh-bf.log" +results[1].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-02-12T14:10:21Z" +basename(results[1].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[1].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[1].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[1].GetMeta("target_user") == "pascal1" -results[1].Overflow.Alert.Events[2].GetMeta("datasource_path") == "ssh-bf.log" +results[1].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-02-12T14:10:21Z" +basename(results[1].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[2].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[2].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[2].GetMeta("target_user") == "pascal2" -results[1].Overflow.Alert.Events[3].GetMeta("datasource_path") == "ssh-bf.log" +results[1].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-02-12T14:10:22Z" +basename(results[1].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[3].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[3].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[3].GetMeta("target_user") == "pascal3" -results[1].Overflow.Alert.Events[4].GetMeta("datasource_path") == "ssh-bf.log" +results[1].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-02-12T14:10:22Z" +basename(results[1].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[4].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[4].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[4].GetMeta("target_user") == "pascal4" -results[1].Overflow.Alert.Events[5].GetMeta("datasource_path") == "ssh-bf.log" +results[1].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-02-12T14:10:23Z" +basename(results[1].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "ssh-bf.log" results[1].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[1].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[5].GetMeta("machine") == "sd-126005" results[1].Overflow.Alert.Events[5].GetMeta("service") == "ssh" results[1].Overflow.Alert.Events[5].GetMeta("source_ip") == "35.188.49.176" results[1].Overflow.Alert.Events[5].GetMeta("target_user") == "pascal5" +results[1].Overflow.Alert.Events[5].GetMeta("timestamp") == "2026-02-12T14:10:24Z" results[1].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-bf" results[1].Overflow.Alert.Remediation == true results[1].Overflow.Alert.GetEventsCount() == 6 - diff --git a/.tests/ssh-slow-bf/scenario.assert b/.tests/ssh-slow-bf/scenario.assert index 9fe0f2a4cdc..ba215e11fb7 100644 --- a/.tests/ssh-slow-bf/scenario.assert +++ b/.tests/ssh-slow-bf/scenario.assert @@ -1,74 +1,97 @@ +len(results) == 1 "103.100.210.198" in results[0].Overflow.GetSources() results[0].Overflow.Sources["103.100.210.198"].IP == "103.100.210.198" results[0].Overflow.Sources["103.100.210.198"].Range == "" results[0].Overflow.Sources["103.100.210.198"].GetScope() == "Ip" results[0].Overflow.Sources["103.100.210.198"].GetValue() == "103.100.210.198" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "ssh-slow-bf.log" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[0].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[0].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-09-30T12:16:00Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[1].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[1].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-09-30T12:16:33Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[2].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[2].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-09-30T12:17:00Z" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[3].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[3].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-09-30T12:17:33Z" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[4].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[4].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-09-30T12:18:00Z" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[5].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[5].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[5].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[6].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2026-09-30T12:18:33Z" +basename(results[0].Overflow.Alert.Events[6].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[6].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[6].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[6].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[6].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[6].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[6].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[7].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[6].GetMeta("timestamp") == "2026-09-30T12:19:00Z" +basename(results[0].Overflow.Alert.Events[7].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[7].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[7].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[7].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[7].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[7].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[7].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[8].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[7].GetMeta("timestamp") == "2026-09-30T12:19:33Z" +basename(results[0].Overflow.Alert.Events[8].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[8].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[8].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[8].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[8].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[8].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[8].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[9].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[8].GetMeta("timestamp") == "2026-09-30T12:20:00Z" +basename(results[0].Overflow.Alert.Events[9].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[9].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[9].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[9].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[9].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[9].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[9].GetMeta("target_user") == "hadoop" -results[0].Overflow.Alert.Events[10].GetMeta("datasource_path") == "ssh-slow-bf.log" +results[0].Overflow.Alert.Events[9].GetMeta("timestamp") == "2026-09-30T12:20:33Z" +basename(results[0].Overflow.Alert.Events[10].GetMeta("datasource_path")) == "ssh-slow-bf.log" results[0].Overflow.Alert.Events[10].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[10].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[10].GetMeta("machine") == "ip-172-31-43-28" results[0].Overflow.Alert.Events[10].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[10].GetMeta("source_ip") == "103.100.210.198" results[0].Overflow.Alert.Events[10].GetMeta("target_user") == "hadoop" +results[0].Overflow.Alert.Events[10].GetMeta("timestamp") == "2026-09-30T12:21:00Z" results[0].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-slow-bf" results[0].Overflow.Alert.Remediation == true results[0].Overflow.Alert.GetEventsCount() == 20 diff --git a/.tests/ssh-time-based-bf/config.yaml b/.tests/ssh-time-based-bf/config.yaml new file mode 100644 index 00000000000..85a6ea33b11 --- /dev/null +++ b/.tests/ssh-time-based-bf/config.yaml @@ -0,0 +1,16 @@ +parsers: +- crowdsecurity/syslog-logs +- crowdsecurity/sshd-logs +- crowdsecurity/sshd-success-logs +- crowdsecurity/dateparse-enrich +scenarios: +- ./scenarios/crowdsecurity/ssh-time-based-bf.yaml +# we put these on purpose : we want only to trigger the time-based-bf +- crowdsecurity/ssh-bf +- crowdsecurity/ssh-slow-bf +postoverflows: +- "" +log_file: ssh-time-based-bf.log +log_type: syslog +ignore_parsers: true + diff --git a/.tests/ssh-time-based-bf/scenario.assert b/.tests/ssh-time-based-bf/scenario.assert new file mode 100644 index 00000000000..b07bce53ebb --- /dev/null +++ b/.tests/ssh-time-based-bf/scenario.assert @@ -0,0 +1,65 @@ +len(results) == 2 +"10.0.0.101" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["10.0.0.101"].IP == "10.0.0.101" +results[0].Overflow.Sources["10.0.0.101"].Range == "" +results[0].Overflow.Sources["10.0.0.101"].GetScope() == "Ip" +results[0].Overflow.Sources["10.0.0.101"].GetValue() == "10.0.0.101" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[0].GetMeta("machine") == "server" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "10.0.0.101" +results[0].Overflow.Alert.Events[0].GetMeta("target_user") == "root" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-09-30T11:00:00Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[1].GetMeta("machine") == "server" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "10.0.0.101" +results[0].Overflow.Alert.Events[1].GetMeta("target_user") == "mysql" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-09-30T11:20:00Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[2].GetMeta("machine") == "server" +results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" +results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "10.0.0.101" +results[0].Overflow.Alert.Events[2].GetMeta("target_user") == "oracle" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-09-30T11:40:00Z" +results[0].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-time-based-bf_user-enum" +results[0].Overflow.Alert.Remediation == false +results[0].Overflow.Alert.GetEventsCount() == 3 +"10.0.0.101" in results[1].Overflow.GetSources() +results[1].Overflow.Sources["10.0.0.101"].IP == "10.0.0.101" +results[1].Overflow.Sources["10.0.0.101"].Range == "" +results[1].Overflow.Sources["10.0.0.101"].GetScope() == "Ip" +results[1].Overflow.Sources["10.0.0.101"].GetValue() == "10.0.0.101" +basename(results[1].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[1].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[0].GetMeta("machine") == "server" +results[1].Overflow.Alert.Events[0].GetMeta("service") == "ssh" +results[1].Overflow.Alert.Events[0].GetMeta("source_ip") == "10.0.0.101" +results[1].Overflow.Alert.Events[0].GetMeta("target_user") == "root" +results[1].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-09-30T11:00:00Z" +basename(results[1].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[1].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[1].GetMeta("machine") == "server" +results[1].Overflow.Alert.Events[1].GetMeta("service") == "ssh" +results[1].Overflow.Alert.Events[1].GetMeta("source_ip") == "10.0.0.101" +results[1].Overflow.Alert.Events[1].GetMeta("target_user") == "mysql" +results[1].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-09-30T11:20:00Z" +basename(results[1].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "ssh-time-based-bf.log" +results[1].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[1].Overflow.Alert.Events[2].GetMeta("machine") == "server" +results[1].Overflow.Alert.Events[2].GetMeta("service") == "ssh" +results[1].Overflow.Alert.Events[2].GetMeta("source_ip") == "10.0.0.101" +results[1].Overflow.Alert.Events[2].GetMeta("target_user") == "oracle" +results[1].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-09-30T11:40:00Z" +results[1].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-time-based-bf" +results[1].Overflow.Alert.Remediation == false +results[1].Overflow.Alert.GetEventsCount() == 3 diff --git a/.tests/ssh-time-based-bf/ssh-time-based-bf.log b/.tests/ssh-time-based-bf/ssh-time-based-bf.log new file mode 100644 index 00000000000..d705380659d --- /dev/null +++ b/.tests/ssh-time-based-bf/ssh-time-based-bf.log @@ -0,0 +1,10 @@ +Sep 30 10:00:00 server sshd[12345]: Invalid user admin from 10.0.0.100 port 56762 +Sep 30 10:06:00 server sshd[12346]: Invalid user test from 10.0.0.100 port 56763 +Sep 30 10:12:00 server sshd[12347]: Invalid user guest from 10.0.0.100 port 56764 +Sep 30 11:00:00 server sshd[12348]: Invalid user root from 10.0.0.101 port 56765 +Sep 30 11:20:00 server sshd[12349]: Invalid user mysql from 10.0.0.101 port 56766 +Sep 30 11:40:00 server sshd[12350]: Invalid user oracle from 10.0.0.101 port 56767 +Sep 30 12:00:00 server sshd[12351]: Invalid user postgres from 10.0.0.102 port 56768 +Sep 30 12:10:00 server sshd[12352]: Invalid user jenkins from 10.0.0.102 port 56769 +Sep 30 12:15:00 server sshd[12353]: Accepted password for jenkins from 10.0.0.102 port 56770 ssh2 +Sep 30 12:20:00 server sshd[12354]: Invalid user admin from 10.0.0.102 port 56771 diff --git a/.tests/sshd-invalid-bf/scenario.assert b/.tests/sshd-invalid-bf/scenario.assert index f873d79c6dd..e9d8b7622bd 100644 --- a/.tests/sshd-invalid-bf/scenario.assert +++ b/.tests/sshd-invalid-bf/scenario.assert @@ -4,55 +4,54 @@ results[0].Overflow.Sources["179.43.183.98"].IP == "179.43.183.98" results[0].Overflow.Sources["179.43.183.98"].Range == "" results[0].Overflow.Sources["179.43.183.98"].GetScope() == "Ip" results[0].Overflow.Sources["179.43.183.98"].GetValue() == "179.43.183.98" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "sshd-invalid-bf.log" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[0].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[0].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[0].GetMeta("timestamp")[4:] == "-01-24T15:32:31Z" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "sshd-invalid-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-01-24T15:32:31Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[1].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[1].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[1].GetMeta("timestamp")[4:] == "-01-24T15:32:32Z" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "sshd-invalid-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-01-24T15:32:32Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[2].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[2].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[2].GetMeta("timestamp")[4:] == "-01-24T15:32:33Z" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "sshd-invalid-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-01-24T15:32:33Z" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[3].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[3].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[3].GetMeta("timestamp")[4:] == "-01-24T15:32:34Z" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "sshd-invalid-bf.log" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-01-24T15:32:34Z" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[4].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[4].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[4].GetMeta("timestamp")[4:] == "-01-24T15:32:35Z" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "sshd-invalid-bf.log" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-01-24T15:32:35Z" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "sshd-invalid-bf.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" results[0].Overflow.Alert.Events[5].GetMeta("machine") == "server" results[0].Overflow.Alert.Events[5].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "179.43.183.98" results[0].Overflow.Alert.Events[5].GetMeta("target_user") == "root" -results[0].Overflow.Alert.Events[5].GetMeta("timestamp")[4:] == "-01-24T15:32:36Z" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2026-01-24T15:32:36Z" results[0].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-bf" results[0].Overflow.Alert.Remediation == true results[0].Overflow.Alert.GetEventsCount() == 6 - diff --git a/.tests/sshd_banner_exchange/scenario.assert b/.tests/sshd_banner_exchange/scenario.assert index 8aca60edd5c..0d0efae1a5e 100644 --- a/.tests/sshd_banner_exchange/scenario.assert +++ b/.tests/sshd_banner_exchange/scenario.assert @@ -4,36 +4,54 @@ results[0].Overflow.Sources["59.91.122.57"].IP == "59.91.122.57" results[0].Overflow.Sources["59.91.122.57"].Range == "" results[0].Overflow.Sources["59.91.122.57"].GetScope() == "Ip" results[0].Overflow.Sources["59.91.122.57"].GetValue() == "59.91.122.57" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "sshd_banner_exchange.log" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[0].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[0].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "59.91.122.57" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "sshd_banner_exchange.log" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2026-12-01T18:59:33Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[1].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[1].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "59.91.122.57" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "sshd_banner_exchange.log" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2026-12-01T18:59:33Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[2].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[2].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[2].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "59.91.122.57" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "sshd_banner_exchange.log" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2026-12-01T18:59:33Z" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[3].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[3].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[3].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "59.91.122.57" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "sshd_banner_exchange.log" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2026-12-01T18:59:33Z" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[4].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[4].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[4].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "59.91.122.57" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "sshd_banner_exchange.log" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2026-12-01T18:59:33Z" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "sshd_banner_exchange.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[5].GetMeta("extra_log_type") == "ssh_bad_banner" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ssh_failed-auth" +results[0].Overflow.Alert.Events[5].GetMeta("machine") == "hostname" results[0].Overflow.Alert.Events[5].GetMeta("service") == "ssh" results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "59.91.122.57" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2026-12-01T18:59:33Z" results[0].Overflow.Alert.GetScenario() == "crowdsecurity/ssh-bf" results[0].Overflow.Alert.Remediation == true results[0].Overflow.Alert.GetEventsCount() == 6 diff --git a/collections/crowdsecurity/sshd.yaml b/collections/crowdsecurity/sshd.yaml index 5eda2732d14..ad9b001f3cc 100644 --- a/collections/crowdsecurity/sshd.yaml +++ b/collections/crowdsecurity/sshd.yaml @@ -1,8 +1,10 @@ parsers: - crowdsecurity/sshd-logs + - crowdsecurity/sshd-success-logs scenarios: - crowdsecurity/ssh-bf - crowdsecurity/ssh-slow-bf + - crowdsecurity/ssh-time-based-bf - crowdsecurity/ssh-cve-2024-6387 - crowdsecurity/ssh-refused-conn - crowdsecurity/ssh-generic-test diff --git a/scenarios/crowdsecurity/ssh-time-based-bf.md b/scenarios/crowdsecurity/ssh-time-based-bf.md new file mode 100644 index 00000000000..f16a85860eb --- /dev/null +++ b/scenarios/crowdsecurity/ssh-time-based-bf.md @@ -0,0 +1,23 @@ +Detect time-based ssh bruteforce attempts that evade traditional rate limiting with false positive reduction: + + - Uses conditional type with capacity -1 (unlimited) + - Triggers when at least 3 failed authentication attempts occur + - Median interval between failed attempts exceeds 10 minutes + - **False positive reduction**: Uses `cancel_on` to cancel bucket if user successfully authenticates + - Prevents "forgot password" scenarios from triggering alerts + - Standard variant: Cancels on ANY successful login from same IP + - User-enum variant: Only cancels for same IP + same username combination + - Attackers trying multiple usernames won't be excused by one success (in user-enum variant) + - Leakspeed of 2h naturally caps maximum interval (~40-60 minutes for 3 events) + - Remediation disabled (labels set to `remediation: false`) + - Uses `MedianInterval()` helper to detect consistent timing patterns (more robust against outliers) + - Requires `crowdsecurity/sshd-success-logs` parser for cancel_on functionality + +**Two variants:** +1. **ssh-time-based-bf**: Standard bruteforce detection (3 failed logins from same IP) +2. **ssh-time-based-bf_user-enum**: User enumeration detection (3 distinct usernames from same IP) + +This scenario complements the standard ssh-bf (capacity 5, leakspeed 10s) and ssh-slow-bf (capacity 10, leakspeed 60s) scenarios with no overlap: +- ssh-bf catches 5 failures within ~50 seconds (rate-based) +- ssh-slow-bf catches 10 failures within ~10 minutes (rate-based) +- ssh-time-based-bf catches 3 failures with median interval >10 minutes (time-pattern-based, naturally capped by 2h leakspeed) diff --git a/scenarios/crowdsecurity/ssh-time-based-bf.yaml b/scenarios/crowdsecurity/ssh-time-based-bf.yaml new file mode 100644 index 00000000000..c1c798b6296 --- /dev/null +++ b/scenarios/crowdsecurity/ssh-time-based-bf.yaml @@ -0,0 +1,51 @@ +# ssh time-based bruteforce with false positive reduction +type: conditional +name: crowdsecurity/ssh-time-based-bf +description: "Detect time-based ssh bruteforce attempts that evade rate limiting (with false positive reduction)" +filter: "evt.Meta.service == 'ssh' && evt.Meta.log_type in ['ssh_failed-auth', 'auth_success']" +groupby: evt.Meta.source_ip +capacity: -1 +cancel_on: "evt.Meta.log_type == 'auth_success'" +condition: | + let failedAuths = filter(queue.Queue, {#.Meta.log_type == 'ssh_failed-auth'}); + len(failedAuths) >= 3 && + MedianInterval(map(failedAuths[-3:], {#.Time})) > duration("10m") +leakspeed: 2h +blackhole: 5m +reprocess: true +labels: + service: ssh + behavior: "ssh:bruteforce" + spoofable: 0 + confidence: 3 + classification: + - attack.T1110 + label: "SSH Time-Based Bruteforce" + remediation: false +--- +# ssh user-enum time-based with false positive reduction +type: conditional +name: crowdsecurity/ssh-time-based-bf_user-enum +description: "Detect time-based ssh user enum bruteforce attempts (with false positive reduction)" +filter: "evt.Meta.service == 'ssh' && evt.Meta.log_type in ['ssh_failed-auth', 'auth_success']" +groupby: evt.Meta.source_ip +distinct: evt.Meta.target_user +capacity: -1 +cancel_on: "evt.Meta.log_type == 'auth_success'" +condition: | + let failedAuths = filter(queue.Queue, {#.Meta.log_type == 'ssh_failed-auth'}); + len(failedAuths) >= 3 && + MedianInterval(map(failedAuths[-3:], {#.Time})) > duration("10m") +leakspeed: 2h +blackhole: 5m +reprocess: true +labels: + service: ssh + behavior: "ssh:bruteforce" + spoofable: 0 + confidence: 3 + classification: + - attack.T1589 + - attack.T1110 + label: "SSH Time-Based User Enumeration" + remediation: false