diff --git a/.tests/vsftpd-bf/scenario.assert b/.tests/vsftpd-bf/scenario.assert index 66c4c81f33c..e00bf55f7cd 100644 --- a/.tests/vsftpd-bf/scenario.assert +++ b/.tests/vsftpd-bf/scenario.assert @@ -1,46 +1,57 @@ len(results) == 1 -"93.24.101.89" in results[0].Overflow.GetSources() -results[0].Overflow.Sources["93.24.101.89"].IP == "93.24.101.89" -results[0].Overflow.Sources["93.24.101.89"].Range == "" -results[0].Overflow.Sources["93.24.101.89"].GetScope() == "Ip" -results[0].Overflow.Sources["93.24.101.89"].GetValue() == "93.24.101.89" -results[0].Overflow.Alert.Events[0].GetMeta("datasource_path") == "vsftpd-bf.log" +"192.168.1.100" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["192.168.1.100"].IP == "192.168.1.100" +results[0].Overflow.Sources["192.168.1.100"].Range == "" +results[0].Overflow.Sources["192.168.1.100"].GetScope() == "Ip" +results[0].Overflow.Sources["192.168.1.100"].GetValue() == "192.168.1.100" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[0].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2020-06-08T12:08:53Z" results[0].Overflow.Alert.Events[0].GetMeta("user") == "user" -results[0].Overflow.Alert.Events[1].GetMeta("datasource_path") == "vsftpd-bf.log" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[1].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2020-06-08T12:08:53Z" results[0].Overflow.Alert.Events[1].GetMeta("user") == "user" -results[0].Overflow.Alert.Events[2].GetMeta("datasource_path") == "vsftpd-bf.log" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[2].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[2].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2020-06-08T12:08:54Z" results[0].Overflow.Alert.Events[2].GetMeta("user") == "user" -results[0].Overflow.Alert.Events[3].GetMeta("datasource_path") == "vsftpd-bf.log" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[3].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[3].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2020-06-08T12:08:54Z" results[0].Overflow.Alert.Events[3].GetMeta("user") == "user" -results[0].Overflow.Alert.Events[4].GetMeta("datasource_path") == "vsftpd-bf.log" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[4].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[4].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2020-06-08T12:08:55Z" results[0].Overflow.Alert.Events[4].GetMeta("user") == "user" -results[0].Overflow.Alert.Events[5].GetMeta("datasource_path") == "vsftpd-bf.log" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "vsftpd-bf.log" results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ftp_failed_auth" results[0].Overflow.Alert.Events[5].GetMeta("program") == "vsftpd" -results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "93.24.101.89" +results[0].Overflow.Alert.Events[5].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2020-06-08T12:08:55Z" results[0].Overflow.Alert.Events[5].GetMeta("user") == "user" results[0].Overflow.Alert.GetScenario() == "crowdsecurity/vsftpd-bf" results[0].Overflow.Alert.Remediation == true results[0].Overflow.Alert.GetEventsCount() == 6 - diff --git a/.tests/vsftpd-bf/vsftpd-bf.log b/.tests/vsftpd-bf/vsftpd-bf.log index 438936dd977..8c54e7e646a 100644 --- a/.tests/vsftpd-bf/vsftpd-bf.log +++ b/.tests/vsftpd-bf/vsftpd-bf.log @@ -1,6 +1,6 @@ -Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" -Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" -Mon Jun 8 12:08:54 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" -Mon Jun 8 12:08:54 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" -Mon Jun 8 12:08:55 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" -Mon Jun 8 12:08:55 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:93.24.101.89" +Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:08:54 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:08:54 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:08:55 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:08:55 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" diff --git a/.tests/vsftpd-impossible-travel/config.yaml b/.tests/vsftpd-impossible-travel/config.yaml new file mode 100644 index 00000000000..d68258721c3 --- /dev/null +++ b/.tests/vsftpd-impossible-travel/config.yaml @@ -0,0 +1,11 @@ +parsers: +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +- crowdsecurity/geoip-enrich +- ./parsers/s01-parse/crowdsecurity/vsftpd-success-logs.yaml +scenarios: +- "./scenarios/crowdsecurity/impossible-travel.yaml" +log_file: vsftpd-success-logs.log +log_type: vsftpd +ignore_parsers: true + diff --git a/.tests/vsftpd-impossible-travel/scenario.assert b/.tests/vsftpd-impossible-travel/scenario.assert new file mode 100644 index 00000000000..e232a19fc68 --- /dev/null +++ b/.tests/vsftpd-impossible-travel/scenario.assert @@ -0,0 +1,36 @@ +len(results) == 1 +"1.2.3.4" in results[0].Overflow.GetSources() +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" +"9.8.8.8" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["9.8.8.8"].IP == "9.8.8.8" +results[0].Overflow.Sources["9.8.8.8"].Range == "" +results[0].Overflow.Sources["9.8.8.8"].GetScope() == "Ip" +results[0].Overflow.Sources["9.8.8.8"].GetValue() == "9.8.8.8" +results[0].Overflow.Alert.Events[0].GetMeta("ASNNumber") == "0" +results[0].Overflow.Alert.Events[0].GetMeta("IsInEU") == "false" +results[0].Overflow.Alert.Events[0].GetMeta("IsoCode") == "AU" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "vsftpd-success-logs.log" +results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "auth_success" +results[0].Overflow.Alert.Events[0].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "1.2.3.4" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2020-06-08T12:00:00Z" +results[0].Overflow.Alert.Events[0].GetMeta("user") == "vagrant" +results[0].Overflow.Alert.Events[1].GetMeta("ASNNumber") == "0" +results[0].Overflow.Alert.Events[1].GetMeta("IsInEU") == "false" +results[0].Overflow.Alert.Events[1].GetMeta("IsoCode") == "US" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "vsftpd-success-logs.log" +results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "auth_success" +results[0].Overflow.Alert.Events[1].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "9.8.8.8" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2020-06-08T12:01:00Z" +results[0].Overflow.Alert.Events[1].GetMeta("user") == "vagrant" +results[0].Overflow.Alert.GetScenario() == "crowdsecurity/impossible-travel" +results[0].Overflow.Alert.Remediation == false +results[0].Overflow.Alert.GetEventsCount() == 2 diff --git a/.tests/vsftpd-impossible-travel/vsftpd-success-logs.log b/.tests/vsftpd-impossible-travel/vsftpd-success-logs.log new file mode 100644 index 00000000000..745724124c6 --- /dev/null +++ b/.tests/vsftpd-impossible-travel/vsftpd-success-logs.log @@ -0,0 +1,3 @@ +Mon Jun 8 12:00:00 2020 [pid 27307] [vagrant] OK LOGIN: Client "::ffff:1.2.3.4" +Mon Jun 8 12:01:00 2020 [pid 27308] [vagrant] OK LOGIN: Client "::ffff:9.8.8.8" + diff --git a/.tests/vsftpd-logs/parser.assert b/.tests/vsftpd-logs/parser.assert index 613b3e44e00..b0ae03d4dc8 100644 --- a/.tests/vsftpd-logs/parser.assert +++ b/.tests/vsftpd-logs/parser.assert @@ -1,3 +1,41 @@ +len(results) == 4 +len(results["s00-raw"]["crowdsecurity/non-syslog"]) == 5 +results["s00-raw"]["crowdsecurity/non-syslog"][0].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["message"] == "Mon Jun 8 12:08:44 2020 [pid 27245] CONNECT: Client \"::ffff:93.24.101.89\"" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][1].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["message"] == "Mon Jun 8 12:12:43 2020 [pid 27307] [ubuntu] OK LOGIN: Client \"::ffff:93.24.101.89\"" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][2].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["message"] == "Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client \"::ffff:93.24.101.89\"" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][3].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Parsed["message"] == "Mon Jun 9 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client \"::ffff:93.24.101.90\"" +results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][4].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Parsed["message"] == "Mon Apr 12 15:19:22 2021 [pid 15685] [www-data] FTP response: Client \"1.2.3.4\", \"530 Permission denied.\"" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Whitelisted == false +len(results["s00-raw"]["crowdsecurity/syslog-logs"]) == 5 +results["s00-raw"]["crowdsecurity/syslog-logs"][0].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][1].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][2].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][3].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][4].Success == false len(results["s01-parse"]["vsftpd-logs"]) == 5 results["s01-parse"]["vsftpd-logs"][0].Success == false results["s01-parse"]["vsftpd-logs"][1].Success == false @@ -7,34 +45,89 @@ results["s01-parse"]["vsftpd-logs"][2].Evt.Parsed["program"] == "vsftpd" results["s01-parse"]["vsftpd-logs"][2].Evt.Parsed["source_ip"] == "93.24.101.89" results["s01-parse"]["vsftpd-logs"][2].Evt.Parsed["timestamp"] == "Mon Jun 8 12:08:53 2020" results["s01-parse"]["vsftpd-logs"][2].Evt.Parsed["user"] == "user" +basename(results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["datasource_type"] == "file" results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["log_type"] == "ftp_failed_auth" results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["service"] == "ftp" results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["source_ip"] == "93.24.101.89" results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["user"] == "user" -results["s01-parse"]["vsftpd-logs"][2].Evt.Meta["datasource_path"] == "vsftpd-logs.log" +results["s01-parse"]["vsftpd-logs"][2].Evt.Whitelisted == false results["s01-parse"]["vsftpd-logs"][3].Success == true results["s01-parse"]["vsftpd-logs"][3].Evt.Parsed["message"] == "Mon Jun 9 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client \"::ffff:93.24.101.90\"" results["s01-parse"]["vsftpd-logs"][3].Evt.Parsed["program"] == "vsftpd" results["s01-parse"]["vsftpd-logs"][3].Evt.Parsed["source_ip"] == "93.24.101.90" results["s01-parse"]["vsftpd-logs"][3].Evt.Parsed["timestamp"] == "Mon Jun 9 12:08:53 2020" results["s01-parse"]["vsftpd-logs"][3].Evt.Parsed["user"] == "user" +basename(results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["datasource_type"] == "file" results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["log_type"] == "ftp_failed_auth" results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["service"] == "ftp" results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["source_ip"] == "93.24.101.90" results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["user"] == "user" -results["s01-parse"]["vsftpd-logs"][3].Evt.Meta["datasource_path"] == "vsftpd-logs.log" +results["s01-parse"]["vsftpd-logs"][3].Evt.Whitelisted == false results["s01-parse"]["vsftpd-logs"][4].Success == true results["s01-parse"]["vsftpd-logs"][4].Evt.Parsed["message"] == "Mon Apr 12 15:19:22 2021 [pid 15685] [www-data] FTP response: Client \"1.2.3.4\", \"530 Permission denied.\"" results["s01-parse"]["vsftpd-logs"][4].Evt.Parsed["program"] == "vsftpd" results["s01-parse"]["vsftpd-logs"][4].Evt.Parsed["source_ip"] == "1.2.3.4" results["s01-parse"]["vsftpd-logs"][4].Evt.Parsed["timestamp"] == "Mon Apr 12 15:19:22 2021" results["s01-parse"]["vsftpd-logs"][4].Evt.Parsed["user"] == "www-data" -results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["datasource_path"] == "vsftpd-logs.log" +basename(results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["datasource_type"] == "file" results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["log_type"] == "ftp_failed_auth" results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["service"] == "ftp" results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["source_ip"] == "1.2.3.4" results["s01-parse"]["vsftpd-logs"][4].Evt.Meta["user"] == "www-data" - +results["s01-parse"]["vsftpd-logs"][4].Evt.Whitelisted == false +len(results["s02-enrich"]["crowdsecurity/dateparse-enrich"]) == 3 +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["message"] == "Mon Jun 8 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client \"::ffff:93.24.101.89\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["source_ip"] == "93.24.101.89" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["timestamp"] == "Mon Jun 8 12:08:53 2020" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["user"] == "user" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["log_type"] == "ftp_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["source_ip"] == "93.24.101.89" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["timestamp"] == "2020-06-08T12:08:53Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["user"] == "user" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Enriched["MarshaledTime"] == "2020-06-08T12:08:53Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Whitelisted == false +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["message"] == "Mon Jun 9 12:08:53 2020 [pid 27244] [user] FAIL LOGIN: Client \"::ffff:93.24.101.90\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["source_ip"] == "93.24.101.90" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["timestamp"] == "Mon Jun 9 12:08:53 2020" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["user"] == "user" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["log_type"] == "ftp_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["source_ip"] == "93.24.101.90" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["timestamp"] == "2020-06-09T12:08:53Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["user"] == "user" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Enriched["MarshaledTime"] == "2020-06-09T12:08:53Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Whitelisted == false +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["message"] == "Mon Apr 12 15:19:22 2021 [pid 15685] [www-data] FTP response: Client \"1.2.3.4\", \"530 Permission denied.\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["source_ip"] == "1.2.3.4" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["timestamp"] == "Mon Apr 12 15:19:22 2021" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["user"] == "www-data" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["datasource_path"]) == "vsftpd-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["log_type"] == "ftp_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["source_ip"] == "1.2.3.4" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["timestamp"] == "2021-04-12T15:19:22Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["user"] == "www-data" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Enriched["MarshaledTime"] == "2021-04-12T15:19:22Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Whitelisted == false +len(results["success"][""]) == 0 diff --git a/.tests/vsftpd-slow-bf/config.yaml b/.tests/vsftpd-slow-bf/config.yaml new file mode 100644 index 00000000000..de76d1bbca7 --- /dev/null +++ b/.tests/vsftpd-slow-bf/config.yaml @@ -0,0 +1,12 @@ +parsers: +- crowdsecurity/vsftpd-logs +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +scenarios: +- ./scenarios/crowdsecurity/vsftpd-slow-bf.yaml +postoverflows: +- "" +log_file: vsftpd-slow-bf.log +log_type: vsftpd +ignore_parsers: true + diff --git a/.tests/vsftpd-slow-bf/scenario.assert b/.tests/vsftpd-slow-bf/scenario.assert new file mode 100644 index 00000000000..9b05dc59d40 --- /dev/null +++ b/.tests/vsftpd-slow-bf/scenario.assert @@ -0,0 +1,97 @@ +len(results) == 1 +"192.168.1.100" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["192.168.1.100"].IP == "192.168.1.100" +results[0].Overflow.Sources["192.168.1.100"].Range == "" +results[0].Overflow.Sources["192.168.1.100"].GetScope() == "Ip" +results[0].Overflow.Sources["192.168.1.100"].GetValue() == "192.168.1.100" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[0].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2020-06-08T12:00:45Z" +results[0].Overflow.Alert.Events[0].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[1].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2020-06-08T12:01:00Z" +results[0].Overflow.Alert.Events[1].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[2].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[2].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2020-06-08T12:01:15Z" +results[0].Overflow.Alert.Events[2].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[3].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[3].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2020-06-08T12:01:30Z" +results[0].Overflow.Alert.Events[3].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[4].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[4].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2020-06-08T12:01:45Z" +results[0].Overflow.Alert.Events[4].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[5].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[5].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2020-06-08T12:02:00Z" +results[0].Overflow.Alert.Events[5].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[6].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[6].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[6].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[6].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[6].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[6].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[6].GetMeta("timestamp") == "2020-06-08T12:02:15Z" +results[0].Overflow.Alert.Events[6].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[7].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[7].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[7].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[7].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[7].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[7].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[7].GetMeta("timestamp") == "2020-06-08T12:02:30Z" +results[0].Overflow.Alert.Events[7].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[8].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[8].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[8].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[8].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[8].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[8].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[8].GetMeta("timestamp") == "2020-06-08T12:02:45Z" +results[0].Overflow.Alert.Events[8].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[9].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[9].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[9].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[9].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[9].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[9].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[9].GetMeta("timestamp") == "2020-06-08T12:03:00Z" +results[0].Overflow.Alert.Events[9].GetMeta("user") == "user" +basename(results[0].Overflow.Alert.Events[10].GetMeta("datasource_path")) == "vsftpd-slow-bf.log" +results[0].Overflow.Alert.Events[10].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[10].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[10].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[10].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[10].GetMeta("source_ip") == "192.168.1.100" +results[0].Overflow.Alert.Events[10].GetMeta("timestamp") == "2020-06-08T12:03:15Z" +results[0].Overflow.Alert.Events[10].GetMeta("user") == "user" +results[0].Overflow.Alert.GetScenario() == "crowdsecurity/vsftpd-slow-bf" +results[0].Overflow.Alert.Remediation == true +results[0].Overflow.Alert.GetEventsCount() == 14 diff --git a/.tests/vsftpd-slow-bf/vsftpd-slow-bf.log b/.tests/vsftpd-slow-bf/vsftpd-slow-bf.log new file mode 100644 index 00000000000..6897dd5e8b0 --- /dev/null +++ b/.tests/vsftpd-slow-bf/vsftpd-slow-bf.log @@ -0,0 +1,17 @@ +Mon Jun 8 12:00:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:00:15 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:00:30 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:00:45 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:01:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:01:15 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:01:30 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:01:45 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:02:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:02:15 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:02:30 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:02:45 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:03:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:03:15 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:03:30 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:03:45 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" + diff --git a/.tests/vsftpd-success-logs/config.yaml b/.tests/vsftpd-success-logs/config.yaml new file mode 100644 index 00000000000..b453d9df77d --- /dev/null +++ b/.tests/vsftpd-success-logs/config.yaml @@ -0,0 +1,9 @@ +parsers: +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +- ./parsers/s01-parse/crowdsecurity/vsftpd-success-logs.yaml +scenarios: +- "" +log_file: vsftpd-success-logs.log +log_type: vsftpd + diff --git a/.tests/vsftpd-success-logs/parser.assert b/.tests/vsftpd-success-logs/parser.assert new file mode 100644 index 00000000000..b248e9bdcbf --- /dev/null +++ b/.tests/vsftpd-success-logs/parser.assert @@ -0,0 +1,117 @@ +len(results) == 4 +len(results["s00-raw"]["crowdsecurity/non-syslog"]) == 3 +results["s00-raw"]["crowdsecurity/non-syslog"][0].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["message"] == "Mon Jun 8 12:00:00 2020 [pid 27307] [vagrant] OK LOGIN: Client \"::ffff:192.168.1.100\"" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][1].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["message"] == "Mon Jun 8 12:01:00 2020 [pid 27308] [admin] OK LOGIN: Client \"::ffff:192.168.1.200\"" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][2].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["message"] == "Mon Jun 8 12:02:00 2020 [pid 27309] [testuser] OK LOGIN: Client \"::ffff:192.168.1.150\"" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["program"] == "vsftpd" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Whitelisted == false +len(results["s00-raw"]["crowdsecurity/syslog-logs"]) == 3 +results["s00-raw"]["crowdsecurity/syslog-logs"][0].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][1].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][2].Success == false +len(results["s01-parse"]["crowdsecurity/vsftpd-success-logs"]) == 3 +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Success == true +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Parsed["message"] == "Mon Jun 8 12:00:00 2020 [pid 27307] [vagrant] OK LOGIN: Client \"::ffff:192.168.1.100\"" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Parsed["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Parsed["source_ip"] == "192.168.1.100" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Parsed["timestamp"] == "Mon Jun 8 12:00:00 2020" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Parsed["user"] == "vagrant" +basename(results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["log_type"] == "auth_success" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["service"] == "ftp" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["source_ip"] == "192.168.1.100" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Meta["user"] == "vagrant" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][0].Evt.Whitelisted == false +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Success == true +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Parsed["message"] == "Mon Jun 8 12:01:00 2020 [pid 27308] [admin] OK LOGIN: Client \"::ffff:192.168.1.200\"" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Parsed["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Parsed["source_ip"] == "192.168.1.200" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Parsed["timestamp"] == "Mon Jun 8 12:01:00 2020" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Parsed["user"] == "admin" +basename(results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["log_type"] == "auth_success" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["service"] == "ftp" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["source_ip"] == "192.168.1.200" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Meta["user"] == "admin" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][1].Evt.Whitelisted == false +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Success == true +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Parsed["message"] == "Mon Jun 8 12:02:00 2020 [pid 27309] [testuser] OK LOGIN: Client \"::ffff:192.168.1.150\"" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Parsed["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Parsed["source_ip"] == "192.168.1.150" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Parsed["timestamp"] == "Mon Jun 8 12:02:00 2020" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Parsed["user"] == "testuser" +basename(results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["log_type"] == "auth_success" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["program"] == "vsftpd" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["service"] == "ftp" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["source_ip"] == "192.168.1.150" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Meta["user"] == "testuser" +results["s01-parse"]["crowdsecurity/vsftpd-success-logs"][2].Evt.Whitelisted == false +len(results["s02-enrich"]["crowdsecurity/dateparse-enrich"]) == 3 +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["message"] == "Mon Jun 8 12:00:00 2020 [pid 27307] [vagrant] OK LOGIN: Client \"::ffff:192.168.1.100\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["source_ip"] == "192.168.1.100" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["timestamp"] == "Mon Jun 8 12:00:00 2020" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["user"] == "vagrant" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["log_type"] == "auth_success" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["source_ip"] == "192.168.1.100" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["timestamp"] == "2020-06-08T12:00:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["user"] == "vagrant" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Enriched["MarshaledTime"] == "2020-06-08T12:00:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Whitelisted == false +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["message"] == "Mon Jun 8 12:01:00 2020 [pid 27308] [admin] OK LOGIN: Client \"::ffff:192.168.1.200\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["source_ip"] == "192.168.1.200" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["timestamp"] == "Mon Jun 8 12:01:00 2020" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["user"] == "admin" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["log_type"] == "auth_success" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["source_ip"] == "192.168.1.200" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["timestamp"] == "2020-06-08T12:01:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["user"] == "admin" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Enriched["MarshaledTime"] == "2020-06-08T12:01:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Whitelisted == false +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["message"] == "Mon Jun 8 12:02:00 2020 [pid 27309] [testuser] OK LOGIN: Client \"::ffff:192.168.1.150\"" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["source_ip"] == "192.168.1.150" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["timestamp"] == "Mon Jun 8 12:02:00 2020" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["user"] == "testuser" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["datasource_path"]) == "vsftpd-success-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["log_type"] == "auth_success" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["program"] == "vsftpd" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["service"] == "ftp" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["source_ip"] == "192.168.1.150" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["timestamp"] == "2020-06-08T12:02:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["user"] == "testuser" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Enriched["MarshaledTime"] == "2020-06-08T12:02:00Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Whitelisted == false +len(results["success"][""]) == 0 diff --git a/.tests/vsftpd-success-logs/scenario.assert b/.tests/vsftpd-success-logs/scenario.assert new file mode 100644 index 00000000000..e69de29bb2d diff --git a/.tests/vsftpd-success-logs/vsftpd-success-logs.log b/.tests/vsftpd-success-logs/vsftpd-success-logs.log new file mode 100644 index 00000000000..3d01f174483 --- /dev/null +++ b/.tests/vsftpd-success-logs/vsftpd-success-logs.log @@ -0,0 +1,4 @@ +Mon Jun 8 12:00:00 2020 [pid 27307] [vagrant] OK LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:01:00 2020 [pid 27308] [admin] OK LOGIN: Client "::ffff:192.168.1.200" +Mon Jun 8 12:02:00 2020 [pid 27309] [testuser] OK LOGIN: Client "::ffff:192.168.1.150" + diff --git a/.tests/vsftpd-time-based-bf/config.yaml b/.tests/vsftpd-time-based-bf/config.yaml new file mode 100644 index 00000000000..c48a471ed3c --- /dev/null +++ b/.tests/vsftpd-time-based-bf/config.yaml @@ -0,0 +1,12 @@ +parsers: +- crowdsecurity/vsftpd-logs +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +scenarios: +- ./scenarios/crowdsecurity/vsftpd-time-based-bf.yaml +postoverflows: +- "" +log_file: vsftpd-time-based-bf.log +log_type: vsftpd +ignore_parsers: true + diff --git a/.tests/vsftpd-time-based-bf/scenario.assert b/.tests/vsftpd-time-based-bf/scenario.assert new file mode 100644 index 00000000000..a65212d494d --- /dev/null +++ b/.tests/vsftpd-time-based-bf/scenario.assert @@ -0,0 +1,65 @@ +len(results) == 2 +"192.168.1.200" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["192.168.1.200"].IP == "192.168.1.200" +results[0].Overflow.Sources["192.168.1.200"].Range == "" +results[0].Overflow.Sources["192.168.1.200"].GetScope() == "Ip" +results[0].Overflow.Sources["192.168.1.200"].GetValue() == "192.168.1.200" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[0].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "192.168.1.200" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2020-06-08T13:00:00Z" +results[0].Overflow.Alert.Events[0].GetMeta("user") == "admin" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[1].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "192.168.1.200" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2020-06-08T13:04:00Z" +results[0].Overflow.Alert.Events[1].GetMeta("user") == "admin" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "ftp_failed_auth" +results[0].Overflow.Alert.Events[2].GetMeta("program") == "vsftpd" +results[0].Overflow.Alert.Events[2].GetMeta("service") == "ftp" +results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "192.168.1.200" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2020-06-08T13:08:00Z" +results[0].Overflow.Alert.Events[2].GetMeta("user") == "admin" +results[0].Overflow.Alert.GetScenario() == "crowdsecurity/vsftpd-time-based-bf" +results[0].Overflow.Alert.Remediation == true +results[0].Overflow.Alert.GetEventsCount() == 3 +"192.168.1.100" in results[1].Overflow.GetSources() +results[1].Overflow.Sources["192.168.1.100"].IP == "192.168.1.100" +results[1].Overflow.Sources["192.168.1.100"].Range == "" +results[1].Overflow.Sources["192.168.1.100"].GetScope() == "Ip" +results[1].Overflow.Sources["192.168.1.100"].GetValue() == "192.168.1.100" +basename(results[1].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[1].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[0].GetMeta("log_type") == "ftp_failed_auth" +results[1].Overflow.Alert.Events[0].GetMeta("program") == "vsftpd" +results[1].Overflow.Alert.Events[0].GetMeta("service") == "ftp" +results[1].Overflow.Alert.Events[0].GetMeta("source_ip") == "192.168.1.100" +results[1].Overflow.Alert.Events[0].GetMeta("timestamp") == "2020-06-08T12:00:00Z" +results[1].Overflow.Alert.Events[0].GetMeta("user") == "user" +basename(results[1].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[1].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[1].GetMeta("log_type") == "ftp_failed_auth" +results[1].Overflow.Alert.Events[1].GetMeta("program") == "vsftpd" +results[1].Overflow.Alert.Events[1].GetMeta("service") == "ftp" +results[1].Overflow.Alert.Events[1].GetMeta("source_ip") == "192.168.1.100" +results[1].Overflow.Alert.Events[1].GetMeta("timestamp") == "2020-06-08T12:03:30Z" +results[1].Overflow.Alert.Events[1].GetMeta("user") == "user" +basename(results[1].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "vsftpd-time-based-bf.log" +results[1].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[1].Overflow.Alert.Events[2].GetMeta("log_type") == "ftp_failed_auth" +results[1].Overflow.Alert.Events[2].GetMeta("program") == "vsftpd" +results[1].Overflow.Alert.Events[2].GetMeta("service") == "ftp" +results[1].Overflow.Alert.Events[2].GetMeta("source_ip") == "192.168.1.100" +results[1].Overflow.Alert.Events[2].GetMeta("timestamp") == "2020-06-08T12:07:00Z" +results[1].Overflow.Alert.Events[2].GetMeta("user") == "user" +results[1].Overflow.Alert.GetScenario() == "crowdsecurity/vsftpd-time-based-bf" +results[1].Overflow.Alert.Remediation == true +results[1].Overflow.Alert.GetEventsCount() == 3 diff --git a/.tests/vsftpd-time-based-bf/vsftpd-time-based-bf.log b/.tests/vsftpd-time-based-bf/vsftpd-time-based-bf.log new file mode 100644 index 00000000000..a178a946de3 --- /dev/null +++ b/.tests/vsftpd-time-based-bf/vsftpd-time-based-bf.log @@ -0,0 +1,7 @@ +Mon Jun 8 12:00:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:03:30 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 12:07:00 2020 [pid 27244] [user] FAIL LOGIN: Client "::ffff:192.168.1.100" +Mon Jun 8 13:00:00 2020 [pid 27245] [admin] FAIL LOGIN: Client "::ffff:192.168.1.200" +Mon Jun 8 13:04:00 2020 [pid 27245] [admin] FAIL LOGIN: Client "::ffff:192.168.1.200" +Mon Jun 8 13:08:00 2020 [pid 27245] [admin] FAIL LOGIN: Client "::ffff:192.168.1.200" + diff --git a/collections/crowdsecurity/vsftpd-impossible-travel.md b/collections/crowdsecurity/vsftpd-impossible-travel.md new file mode 100644 index 00000000000..5039fb4213c --- /dev/null +++ b/collections/crowdsecurity/vsftpd-impossible-travel.md @@ -0,0 +1,35 @@ +## VSFTPD Impossible Travel collection + +This collection detects impossible travel scenarios for FTP authentications - when a user successfully authenticates from geographically distant locations within a timeframe that makes physical travel impossible. + +**Components:** + - VSFTPD successful authentication parser + - Impossible travel detection (by IP) + - Impossible travel detection (by user) + +**Use Cases:** + - Detect compromised credentials being used from multiple locations + - Identify potential account takeover attempts + - Monitor for insider threats and credential sharing + +**Requirements:** + - GeoIP enrichment must be enabled + - VSFTPD logging must capture successful authentications with "OK LOGIN" + - VSFTPD must be configured with appropriate logging level + +## Acquisition template + +Example acquisition for this collection: + +```yaml +filenames: + - /var/log/vsftpd/*.log +labels: + type: vsftpd +``` + +**Notes:** + - If you are using `syslog`, set type to `syslog` instead + - Depending on your distribution/OS, paths to log files might change + - Only relevant if you are manually installing collection + diff --git a/collections/crowdsecurity/vsftpd-impossible-travel.yaml b/collections/crowdsecurity/vsftpd-impossible-travel.yaml new file mode 100644 index 00000000000..edbc8dc2f44 --- /dev/null +++ b/collections/crowdsecurity/vsftpd-impossible-travel.yaml @@ -0,0 +1,13 @@ +parsers: + - crowdsecurity/vsftpd-success-logs +scenarios: + - crowdsecurity/impossible-travel + - crowdsecurity/impossible-travel-user +description: "vsftpd success: parser and impossible travel detection" +author: crowdsecurity +tags: + - linux + - ftp + - inside-threat + - impossible-travel + diff --git a/collections/crowdsecurity/vsftpd.md b/collections/crowdsecurity/vsftpd.md index 97540db3edc..545a4073d01 100644 --- a/collections/crowdsecurity/vsftpd.md +++ b/collections/crowdsecurity/vsftpd.md @@ -1,8 +1,11 @@ ## VsFTPD collection -A collection to defend VSFTPD against common attacks : -- VSFTPD parser: `crowdsecurity/vsftpd-logs` -- bruteforce scenario : `crowdsecurity/vsftpd-bf` +A collection to defend VSFTPD against common attacks: + - vsftpd failed authentication parser + - vsftpd successful authentication parser + - detect bruteforce (fast attacks: 5 failures in ~50s) + - detect slow bruteforce (slower attacks: 10 failures in ~10min) + - detect time-based bruteforce (time-spaced attacks: 3 failures with >2min median interval, includes false positive reduction) ## Acquisition template diff --git a/collections/crowdsecurity/vsftpd.yaml b/collections/crowdsecurity/vsftpd.yaml index 8f0500799a4..12b2ad86c8c 100644 --- a/collections/crowdsecurity/vsftpd.yaml +++ b/collections/crowdsecurity/vsftpd.yaml @@ -1,8 +1,11 @@ parsers: - crowdsecurity/vsftpd-logs + - crowdsecurity/vsftpd-success-logs scenarios: - crowdsecurity/vsftpd-bf -description: "VSFTPD support : logs and brute-force scenarios" + - crowdsecurity/vsftpd-slow-bf + - crowdsecurity/vsftpd-time-based-bf +description: "VSFTPD support : parsers and brute-force scenarios" author: crowdsecurity tags: - linux diff --git a/parsers/s01-parse/crowdsecurity/vsftpd-logs.yaml b/parsers/s01-parse/crowdsecurity/vsftpd-logs.yaml index 993ab16afbd..ae1125068a7 100644 --- a/parsers/s01-parse/crowdsecurity/vsftpd-logs.yaml +++ b/parsers/s01-parse/crowdsecurity/vsftpd-logs.yaml @@ -21,6 +21,8 @@ statics: value: vsftpd - meta: log_type value: ftp_failed_auth + - meta: service + value: ftp - meta: source_ip expression: "evt.Parsed.source_ip" - meta: user diff --git a/parsers/s01-parse/crowdsecurity/vsftpd-success-logs.yaml b/parsers/s01-parse/crowdsecurity/vsftpd-success-logs.yaml new file mode 100644 index 00000000000..dd1e722a699 --- /dev/null +++ b/parsers/s01-parse/crowdsecurity/vsftpd-success-logs.yaml @@ -0,0 +1,27 @@ +onsuccess: next_stage +name: crowdsecurity/vsftpd-success-logs +description: "Parse VSFTPD successful authentications" +filter: "evt.Parsed.program == 'vsftpd'" +pattern_syntax: + CUSTOM_HTTPDERROR_DATE: '%{DAY} %{MONTH} (?:\s?)%{MONTHDAY} %{TIME} %{YEAR}' + FTP_AUTH_SUCCESS: '%{CUSTOM_HTTPDERROR_DATE:timestamp} \[pid %{NUMBER}\] \[%{GREEDYDATA:user}\] OK LOGIN: Client "(::ffff:)?%{IP:source_ip}"' +nodes: + - grok: + pattern: "%{FTP_AUTH_SUCCESS}" + apply_on: message +statics: + - meta: program + value: vsftpd + - meta: log_type + value: auth_success + - meta: service + value: ftp + - meta: source_ip + expression: "evt.Parsed.source_ip" + - meta: user + expression: "evt.Parsed.user" + - target: evt.StrTime + expression: evt.Parsed.timestamp + - target: evt.StrTimeFormat + value: "Mon Jan _2 15:04:05 2006" + diff --git a/scenarios/crowdsecurity/vsftpd-slow-bf.md b/scenarios/crowdsecurity/vsftpd-slow-bf.md new file mode 100644 index 00000000000..31ef4eb43cb --- /dev/null +++ b/scenarios/crowdsecurity/vsftpd-slow-bf.md @@ -0,0 +1,8 @@ +Detect slow FTP bruteforce attempts: + + - leakspeed of 60s, capacity of 10 + +This scenario complements the standard vsftpd-bf scenario (capacity 5, leakspeed 10s) by catching slower attacks. The standard scenario catches 5 failures within ~50 seconds, while this catches 10 failures over ~10 minutes. + +FTP is a common target for credential attacks, and attackers may slow their attempts to avoid detection. + diff --git a/scenarios/crowdsecurity/vsftpd-slow-bf.yaml b/scenarios/crowdsecurity/vsftpd-slow-bf.yaml new file mode 100644 index 00000000000..bade95faa77 --- /dev/null +++ b/scenarios/crowdsecurity/vsftpd-slow-bf.yaml @@ -0,0 +1,19 @@ +type: leaky +name: crowdsecurity/vsftpd-slow-bf +description: "Detect slow FTP bruteforce (vsftpd)" +filter: "evt.Meta.log_type == 'ftp_failed_auth'" +leakspeed: "60s" +capacity: 10 +groupby: evt.Meta.source_ip +blackhole: 1m +reprocess: true +labels: + service: vsftpd + remediation: true + confidence: 3 + spoofable: 0 + classification: + - attack.T1110 + behavior: "ftp:bruteforce" + label: "VSFTPD Slow Bruteforce" + diff --git a/scenarios/crowdsecurity/vsftpd-time-based-bf.md b/scenarios/crowdsecurity/vsftpd-time-based-bf.md new file mode 100644 index 00000000000..60022d2494d --- /dev/null +++ b/scenarios/crowdsecurity/vsftpd-time-based-bf.md @@ -0,0 +1,18 @@ +Detect time-based FTP 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 attempts exceeds 2 minutes + - Leakspeed of 2h naturally caps maximum interval (~40-60 minutes for 3 events) + - Uses `MedianInterval()` helper to detect consistent timing patterns (more robust against outliers) + - Includes `cancel_on` to cancel detection if successful authentication occurs (reduces false positives) + +This scenario complements the standard vsftpd-bf scenario (capacity 5, leakspeed 10s) and vsftpd-slow-bf scenario (capacity 10, leakspeed 60s) by catching attackers who deliberately use time-based attacks to avoid detection. The standard scenario catches 5 failures within ~50 seconds, the slow-bf catches 10 failures within ~10 minutes, while this catches 3 failures with median interval >2 minutes (naturally capped by 2h leakspeed). + +Coverage analysis: +- vsftpd-bf: 0-10s intervals (fast attacks) +- vsftpd-slow-bf: 10-60s intervals (slow attacks) +- vsftpd-time-based-bf: >120s intervals (time-spaced attacks) + +FTP is a common target for credential attacks, and sophisticated adversaries often use slow bruteforce techniques to evade detection. + diff --git a/scenarios/crowdsecurity/vsftpd-time-based-bf.yaml b/scenarios/crowdsecurity/vsftpd-time-based-bf.yaml new file mode 100644 index 00000000000..648860422a1 --- /dev/null +++ b/scenarios/crowdsecurity/vsftpd-time-based-bf.yaml @@ -0,0 +1,25 @@ +# vsftpd time-based bruteforce with false positive reduction +type: conditional +name: crowdsecurity/vsftpd-time-based-bf +description: "Detect time-based FTP bruteforce attempts that evade rate limiting (with false positive reduction)" +filter: "evt.Meta.service == 'ftp' && evt.Meta.log_type in ['ftp_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 == 'ftp_failed_auth'}); + len(failedAuths) >= 3 && + MedianInterval(map(failedAuths[-3:], {#.Time})) > duration("2m") +leakspeed: 2h +blackhole: 5m +reprocess: true +labels: + service: vsftpd + behavior: "ftp:bruteforce" + spoofable: 0 + confidence: 3 + classification: + - attack.T1110 + label: "VSFTPD Time-Based Bruteforce" + remediation: true +