diff --git a/.tests/mealie-bf/config.yaml b/.tests/mealie-bf/config.yaml new file mode 100644 index 00000000000..515430e447d --- /dev/null +++ b/.tests/mealie-bf/config.yaml @@ -0,0 +1,13 @@ +parsers: +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +- ./parsers/s01-parse/Jgigantino31/mealie-logs.yaml +scenarios: +- ./scenarios/Jgigantino31/mealie-bf.yaml +postoverflows: +- "" +log_file: mealie-bf.log +log_type: mealie +labels: {} +ignore_parsers: true +override_statics: [] diff --git a/.tests/mealie-bf/mealie-bf.log b/.tests/mealie-bf/mealie-bf.log new file mode 100644 index 00000000000..e355ad3478b --- /dev/null +++ b/.tests/mealie-bf/mealie-bf.log @@ -0,0 +1,24 @@ +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +[ERROR|auth|L83] 2025-07-16T19:43:16: Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T20:12:38 - Incorrect username or password from 127.0.0.1 diff --git a/.tests/mealie-bf/parser.assert b/.tests/mealie-bf/parser.assert new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/.tests/mealie-bf/parser.assert @@ -0,0 +1 @@ + diff --git a/.tests/mealie-bf/scenario.assert b/.tests/mealie-bf/scenario.assert new file mode 100644 index 00000000000..c008637b6f3 --- /dev/null +++ b/.tests/mealie-bf/scenario.assert @@ -0,0 +1,75 @@ +len(results) == 1 +"127.0.0.1" in results[0].Overflow.GetSources() +results[0].Overflow.Sources["127.0.0.1"].IP == "127.0.0.1" +results[0].Overflow.Sources["127.0.0.1"].Range == "" +results[0].Overflow.Sources["127.0.0.1"].GetScope() == "Ip" +results[0].Overflow.Sources["127.0.0.1"].GetValue() == "127.0.0.1" +basename(results[0].Overflow.Alert.Events[0].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[0].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[0].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[0].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[0].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[0].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[1].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[1].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[1].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[1].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[1].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[1].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[2].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[2].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[2].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[2].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[2].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[2].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[3].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[3].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[3].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[3].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[3].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[3].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[4].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[4].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[4].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[4].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[4].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[4].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[5].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[5].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[5].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[5].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[5].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[5].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[6].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[6].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[6].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[6].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[6].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[6].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[7].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[7].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[7].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[7].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[7].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[7].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[8].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[8].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[8].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[8].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[8].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[8].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[9].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[9].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[9].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[9].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[9].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[9].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +basename(results[0].Overflow.Alert.Events[10].GetMeta("datasource_path")) == "mealie-bf.log" +results[0].Overflow.Alert.Events[10].GetMeta("datasource_type") == "file" +results[0].Overflow.Alert.Events[10].GetMeta("log_type") == "mealie_failed_auth" +results[0].Overflow.Alert.Events[10].GetMeta("service") == "mealie" +results[0].Overflow.Alert.Events[10].GetMeta("source_ip") == "127.0.0.1" +results[0].Overflow.Alert.Events[10].GetMeta("timestamp") == "2025-07-16T20:12:38Z" +results[0].Overflow.Alert.GetScenario() == "Jgigantino31/mealie-bf" +results[0].Overflow.Alert.Remediation == true +results[0].Overflow.Alert.GetEventsCount() == 11 diff --git a/.tests/mealie-logs/config.yaml b/.tests/mealie-logs/config.yaml new file mode 100644 index 00000000000..bb48f02c64b --- /dev/null +++ b/.tests/mealie-logs/config.yaml @@ -0,0 +1,13 @@ +parsers: +- crowdsecurity/syslog-logs +- crowdsecurity/dateparse-enrich +- ./parsers/s01-parse/Jgigantino31/mealie-logs.yaml +scenarios: +- "" +postoverflows: +- "" +log_file: mealie-logs.log +log_type: mealie +labels: {} +ignore_parsers: false +override_statics: [] diff --git a/.tests/mealie-logs/mealie-logs.log b/.tests/mealie-logs/mealie-logs.log new file mode 100644 index 00000000000..42dc61571bb --- /dev/null +++ b/.tests/mealie-logs/mealie-logs.log @@ -0,0 +1,10 @@ +ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1 +ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1 +INFO 2025-07-16T19:42:45 - [127.0.0.1:32894] 401 Unauthorized "POST /api/auth/token HTTP/1.1" +INFO 2025-07-16T19:42:45 - [127.0.0.1:53864] 200 OK "GET /api/app/about HTTP/1.1" +INFO 2025-07-16T19:43:15 - [127.0.0.1:42322] 200 OK "GET /api/app/about HTTP/1.1" +WARNING 2025-07-16T19:43:16 - Found user but their auth method is not 'Mealie'. Unable to continue with credentials login +ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1 +WARNING 2025-07-16T19:43:16 - Found user but their auth method is not 'Mealie'. Unable to continue with credentials login +ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1 +INFO 2025-07-16T19:43:16 - [127.0.0.1:32894] 401 Unauthorized "POST /api/auth/token HTTP/1.1" diff --git a/.tests/mealie-logs/parser.assert b/.tests/mealie-logs/parser.assert new file mode 100644 index 00000000000..c8cf2dc747b --- /dev/null +++ b/.tests/mealie-logs/parser.assert @@ -0,0 +1,178 @@ +len(results) == 4 +len(results["s00-raw"]["crowdsecurity/non-syslog"]) == 10 +results["s00-raw"]["crowdsecurity/non-syslog"][0].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["message"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][0].Evt.Meta["datasource_path"]) == "mealie-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"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][1].Evt.Meta["datasource_path"]) == "mealie-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"] == "INFO 2025-07-16T19:42:45 - [127.0.0.1:32894] 401 Unauthorized \"POST /api/auth/token HTTP/1.1\"" +results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][2].Evt.Meta["datasource_path"]) == "mealie-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"] == "INFO 2025-07-16T19:42:45 - [127.0.0.1:53864] 200 OK \"GET /api/app/about HTTP/1.1\"" +results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][3].Evt.Meta["datasource_path"]) == "mealie-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"] == "INFO 2025-07-16T19:43:15 - [127.0.0.1:42322] 200 OK \"GET /api/app/about HTTP/1.1\"" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][4].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][5].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][5].Evt.Parsed["message"] == "WARNING 2025-07-16T19:43:16 - Found user but their auth method is not 'Mealie'. Unable to continue with credentials login" +results["s00-raw"]["crowdsecurity/non-syslog"][5].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][5].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][5].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][5].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][6].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][6].Evt.Parsed["message"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s00-raw"]["crowdsecurity/non-syslog"][6].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][6].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][6].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][6].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][7].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][7].Evt.Parsed["message"] == "WARNING 2025-07-16T19:43:16 - Found user but their auth method is not 'Mealie'. Unable to continue with credentials login" +results["s00-raw"]["crowdsecurity/non-syslog"][7].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][7].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][7].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][7].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][8].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][8].Evt.Parsed["message"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s00-raw"]["crowdsecurity/non-syslog"][8].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][8].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][8].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][8].Evt.Whitelisted == false +results["s00-raw"]["crowdsecurity/non-syslog"][9].Success == true +results["s00-raw"]["crowdsecurity/non-syslog"][9].Evt.Parsed["message"] == "INFO 2025-07-16T19:43:16 - [127.0.0.1:32894] 401 Unauthorized \"POST /api/auth/token HTTP/1.1\"" +results["s00-raw"]["crowdsecurity/non-syslog"][9].Evt.Parsed["program"] == "mealie" +basename(results["s00-raw"]["crowdsecurity/non-syslog"][9].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s00-raw"]["crowdsecurity/non-syslog"][9].Evt.Meta["datasource_type"] == "file" +results["s00-raw"]["crowdsecurity/non-syslog"][9].Evt.Whitelisted == false +len(results["s00-raw"]["crowdsecurity/syslog-logs"]) == 10 +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 +results["s00-raw"]["crowdsecurity/syslog-logs"][5].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][6].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][7].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][8].Success == false +results["s00-raw"]["crowdsecurity/syslog-logs"][9].Success == false +len(results["s01-parse"]["Jgigantino31/mealie-logs"]) == 10 +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Success == true +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Parsed["message"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Parsed["program"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Parsed["timestamp"] == "2025-07-16T19:42:45" +basename(results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Meta["log_type"] == "mealie_failed_auth" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Meta["service"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Meta["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][0].Evt.Whitelisted == false +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Success == true +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Parsed["message"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Parsed["program"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Parsed["timestamp"] == "2025-07-16T19:42:45" +basename(results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Meta["log_type"] == "mealie_failed_auth" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Meta["service"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Meta["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][1].Evt.Whitelisted == false +results["s01-parse"]["Jgigantino31/mealie-logs"][2].Success == false +results["s01-parse"]["Jgigantino31/mealie-logs"][3].Success == false +results["s01-parse"]["Jgigantino31/mealie-logs"][4].Success == false +results["s01-parse"]["Jgigantino31/mealie-logs"][5].Success == false +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Success == true +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Parsed["message"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Parsed["program"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Parsed["timestamp"] == "2025-07-16T19:43:16" +basename(results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Meta["log_type"] == "mealie_failed_auth" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Meta["service"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Meta["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][6].Evt.Whitelisted == false +results["s01-parse"]["Jgigantino31/mealie-logs"][7].Success == false +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Success == true +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Parsed["message"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Parsed["program"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Parsed["timestamp"] == "2025-07-16T19:43:16" +basename(results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Meta["datasource_type"] == "file" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Meta["log_type"] == "mealie_failed_auth" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Meta["service"] == "mealie" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Meta["source_ip"] == "127.0.0.1" +results["s01-parse"]["Jgigantino31/mealie-logs"][8].Evt.Whitelisted == false +results["s01-parse"]["Jgigantino31/mealie-logs"][9].Success == false +len(results["s02-enrich"]["crowdsecurity/dateparse-enrich"]) == 4 +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["message"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["program"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Parsed["timestamp"] == "2025-07-16T19:42:45" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["datasource_path"]) == "mealie-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"] == "mealie_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["service"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Meta["timestamp"] == "2025-07-16T19:42:45Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][0].Evt.Enriched["MarshaledTime"] == "2025-07-16T19:42:45Z" +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"] == "ERROR 2025-07-16T19:42:45 - Incorrect username or password from 127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["program"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Parsed["timestamp"] == "2025-07-16T19:42:45" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["datasource_path"]) == "mealie-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"] == "mealie_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["service"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Meta["timestamp"] == "2025-07-16T19:42:45Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][1].Evt.Enriched["MarshaledTime"] == "2025-07-16T19:42:45Z" +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"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["program"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Parsed["timestamp"] == "2025-07-16T19:43:16" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["datasource_path"]) == "mealie-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"] == "mealie_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["service"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Meta["timestamp"] == "2025-07-16T19:43:16Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Enriched["MarshaledTime"] == "2025-07-16T19:43:16Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][2].Evt.Whitelisted == false +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Success == true +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Parsed["message"] == "ERROR 2025-07-16T19:43:16 - Incorrect username or password from 127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Parsed["program"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Parsed["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Parsed["timestamp"] == "2025-07-16T19:43:16" +basename(results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["datasource_path"]) == "mealie-logs.log" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["datasource_type"] == "file" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["log_type"] == "mealie_failed_auth" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["service"] == "mealie" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["source_ip"] == "127.0.0.1" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Meta["timestamp"] == "2025-07-16T19:43:16Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Enriched["MarshaledTime"] == "2025-07-16T19:43:16Z" +results["s02-enrich"]["crowdsecurity/dateparse-enrich"][3].Evt.Whitelisted == false +len(results["success"][""]) == 0 diff --git a/.tests/mealie-logs/scenario.assert b/.tests/mealie-logs/scenario.assert new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/.tests/mealie-logs/scenario.assert @@ -0,0 +1 @@ + diff --git a/collections/Jgigantino31/mealie.md b/collections/Jgigantino31/mealie.md new file mode 100644 index 00000000000..483157ed86c --- /dev/null +++ b/collections/Jgigantino31/mealie.md @@ -0,0 +1,27 @@ +A collection to defend [Mealie](https://mealie.io/) instance against common attacks : + - Mealie parser + - Mealie bruteforce detection + +## Acquisition template + +Example acquisition for this collection : + +If using LOG_FILE environment variable: +```yaml +--- +filenames: + - /var/log/mealie.log +labels: + type: mealie +``` + +For Docker directly +```yaml +--- +source: docker +container_name: + - mealie +#container_id: +# - 843ee92d231b +labels: + type: mealie diff --git a/collections/Jgigantino31/mealie.yaml b/collections/Jgigantino31/mealie.yaml new file mode 100644 index 00000000000..05ac9ded279 --- /dev/null +++ b/collections/Jgigantino31/mealie.yaml @@ -0,0 +1,10 @@ +parsers: + - Jgigantino31/mealie-logs +scenarios: + - Jgigantino31/mealie-bf +description: "Mealie Support : parser and brute-force detection" +author: Jgigantino31 +tags: + - linux + - brute-force + - mealie diff --git a/parsers/s01-parse/Jgigantino31/mealie-logs.md b/parsers/s01-parse/Jgigantino31/mealie-logs.md new file mode 100644 index 00000000000..4b95fd41055 --- /dev/null +++ b/parsers/s01-parse/Jgigantino31/mealie-logs.md @@ -0,0 +1,19 @@ +Parser for [Mealie](https://mealie.io/) Logs. + +```yaml +--- +filenames: + - /var/log/mealie.log +labels: + type: mealie +``` + +```yaml +--- +source: docker +container_name: + - mealie +#container_id: +# - 843ee92d231b +labels: + type: mealie diff --git a/parsers/s01-parse/Jgigantino31/mealie-logs.yaml b/parsers/s01-parse/Jgigantino31/mealie-logs.yaml new file mode 100644 index 00000000000..9ef2811fc8d --- /dev/null +++ b/parsers/s01-parse/Jgigantino31/mealie-logs.yaml @@ -0,0 +1,28 @@ +onsuccess: next_stage +#debug: false +name: Jgigantino31/mealie-logs +description: "Parse mealie logs" +filter: "evt.Parsed.program == 'mealie'" +pattern_syntax: + MEALIE_CUSTOMDATE: "%{YEAR}-%{MONTHNUM}-%{MONTHDAY}T%{HOUR}:%{MINUTE}:%{SECOND}" +nodes: + - grok: + pattern: 'ERROR %{MEALIE_CUSTOMDATE:timestamp} - Incorrect username or password from %{IP:source_ip}' # For logs collected directly from docker + apply_on: message + statics: + - meta: log_type + value: mealie_failed_auth + - grok: + pattern: '[ERROR|auth|L83] %{MEALIE_CUSTOMDATE:timestamp}: Incorrect username or password from %{IP:source_ip}' # For logs collected from log file + apply_on: message + statics: + - meta: log_type + value: mealie_failed_auth + +statics: + - meta: service + value: mealie + - meta: source_ip + expression: "evt.Parsed.source_ip" + - target: evt.StrTime + expression: evt.Parsed.timestamp diff --git a/scenarios/Jgigantino31/mealie-bf.md b/scenarios/Jgigantino31/mealie-bf.md new file mode 100644 index 00000000000..d70f584e2cb --- /dev/null +++ b/scenarios/Jgigantino31/mealie-bf.md @@ -0,0 +1,5 @@ +Detect failed mealie authentications: + + - leakspeed of 10s, capacity of 10 + +**Note:** Mealie prints each failed authentication to the log twice causing each failed log in to count as two failed attempts! This means effective leakspeed is 20s and effective capacity is 5. diff --git a/scenarios/Jgigantino31/mealie-bf.yaml b/scenarios/Jgigantino31/mealie-bf.yaml new file mode 100644 index 00000000000..8bd4adfc602 --- /dev/null +++ b/scenarios/Jgigantino31/mealie-bf.yaml @@ -0,0 +1,19 @@ +# mealie BF scan +name: Jgigantino31/mealie-bf +description: "Detect mealie bruteforce" +filter: "evt.Meta.log_type == 'mealie_failed_auth'" +#debug: true +type: leaky +groupby: evt.Meta.source_ip +leakspeed: 10s +capacity: 10 +blackhole: 1m +labels: + service: mealie + behavior: "http:bruteforce" + spoofable: 0 + confidence: 3 + classification: + - attack.T1110 + label: "Mealie Bruteforce" + remediation: true