diff --git a/CHANGELOG.md b/CHANGELOG.md index c6f20ac5b..661a42373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,3 @@ -# UTMStack 10.8.6 Release Notes +# UTMStack 10.9.0 Release Notes -- Expanded the exclusion dictionary for malicious IP connection logs to reduce false positives. -- Added support for older Linux versions (RedHat 7, RedHat 8, Ubuntu 20.04). \ No newline at end of file +- Added New Suricata Integration. \ No newline at end of file diff --git a/agent/config/const.go b/agent/config/const.go index 550e41197..de0a06abf 100644 --- a/agent/config/const.go +++ b/agent/config/const.go @@ -85,6 +85,7 @@ var ( DataTypeAix DataType = "ibm_aix" DataTypePfsense DataType = "firewall_pfsense" DataTypeFortiweb DataType = "firewall_fortiweb" + DataTypeSuricata DataType = "suricata" ProtoPorts = map[DataType]ProtoPort{ DataTypeSyslog: {UDP: "7014", TCP: "7014"}, @@ -102,6 +103,7 @@ var ( DataTypeAix: {UDP: "7016", TCP: "7016"}, DataTypePfsense: {UDP: "7017", TCP: "7017"}, DataTypeFortiweb: {UDP: "7018", TCP: "7018"}, + DataTypeSuricata: {UDP: "7019", TCP: "7019"}, DataTypeNetflow: {UDP: "2055", TCP: ""}, } @@ -116,7 +118,7 @@ func ValidateModuleType(typ string) string { switch DataType(typ) { case DataTypeSyslog, DataTypeVmware, DataTypeEset, DataTypeKaspersky, DataTypeFortinet, DataTypePaloalto, DataTypeMikrotik, DataTypeSophosXG, DataTypeSonicwall, DataTypeSentinelOne, DataTypeCiscoGeneric, - DataTypeDeceptivebytes, DataTypeAix, DataTypePfsense, DataTypeFortiweb: + DataTypeDeceptivebytes, DataTypeAix, DataTypePfsense, DataTypeFortiweb, DataTypeSuricata: return "syslog" case DataTypeNetflow: return "netflow" diff --git a/backend/src/main/java/com/park/utmstack/domain/application_modules/enums/ModuleName.java b/backend/src/main/java/com/park/utmstack/domain/application_modules/enums/ModuleName.java index 14f3266e8..de4779274 100644 --- a/backend/src/main/java/com/park/utmstack/domain/application_modules/enums/ModuleName.java +++ b/backend/src/main/java/com/park/utmstack/domain/application_modules/enums/ModuleName.java @@ -62,5 +62,6 @@ public enum ModuleName { SALESFORCE, BITDEFENDER, SOC_AI, - PFSENSE + PFSENSE, + SURICATA, } diff --git a/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/ModuleFactory.java b/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/ModuleFactory.java index c6d9e2399..41e58fd17 100644 --- a/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/ModuleFactory.java +++ b/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/ModuleFactory.java @@ -67,6 +67,7 @@ public class ModuleFactory { private final ModulePfsense modulePfsense; private final ModuleFortiWeb moduleFortiWeb; private final ModuleAix moduleAix; + private final ModuleSuricata moduleSuricata; public ModuleFactory(ModuleFileIntegrity moduleFileIntegrity, @@ -129,7 +130,8 @@ public ModuleFactory(ModuleFileIntegrity moduleFileIntegrity, ModuleSocAi moduleSocAi, ModulePfsense modulePfsense, ModuleFortiWeb moduleFortiWeb, - ModuleAix moduleAix) { + ModuleAix moduleAix, + ModuleSuricata moduleSuricata) { this.moduleFileIntegrity = moduleFileIntegrity; this.moduleO365 = moduleO365; this.moduleAzure = moduleAzure; @@ -191,6 +193,7 @@ public ModuleFactory(ModuleFileIntegrity moduleFileIntegrity, this.modulePfsense = modulePfsense; this.moduleFortiWeb = moduleFortiWeb; this.moduleAix = moduleAix; + this.moduleSuricata = moduleSuricata; } public IModule getInstance(ModuleName nameShort) { @@ -316,6 +319,8 @@ public IModule getInstance(ModuleName nameShort) { return moduleFortiWeb; if (nameShort.equals(ModuleName.AIX)) return moduleAix; + if (nameShort.equals(ModuleName.SURICATA)) + return moduleSuricata; throw new RuntimeException("Unrecognized module " + nameShort.name()); } } diff --git a/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/impl/ModuleSuricata.java b/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/impl/ModuleSuricata.java new file mode 100644 index 000000000..8878eea50 --- /dev/null +++ b/backend/src/main/java/com/park/utmstack/domain/application_modules/factory/impl/ModuleSuricata.java @@ -0,0 +1,43 @@ +package com.park.utmstack.domain.application_modules.factory.impl; + +import com.park.utmstack.domain.application_modules.UtmModule; +import com.park.utmstack.domain.application_modules.enums.ModuleName; +import com.park.utmstack.domain.application_modules.factory.IModule; +import com.park.utmstack.domain.application_modules.types.ModuleConfigurationKey; +import com.park.utmstack.domain.application_modules.types.ModuleRequirement; +import com.park.utmstack.service.application_modules.UtmModuleService; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; + +@Component +public class ModuleSuricata implements IModule { + private static final String CLASSNAME = "ModuleSuricata"; + + private final UtmModuleService moduleService; + + public ModuleSuricata(UtmModuleService moduleService) { + this.moduleService = moduleService; + } + + @Override + public UtmModule getDetails(Long serverId) throws Exception { + final String ctx = CLASSNAME + ".getDetails"; + try { + return moduleService.findByServerIdAndModuleName(serverId, ModuleName.SURICATA); + } catch (Exception e) { + throw new Exception(ctx + ": " + e.getMessage()); + } + } + + @Override + public List checkRequirements(Long serverId) throws Exception { + return Collections.emptyList(); + } + + @Override + public List getConfigurationKeys(Long groupId) throws Exception { + return Collections.emptyList(); + } +} diff --git a/backend/src/main/resources/config/liquibase/changelog/20250814001_adding_suricata.xml b/backend/src/main/resources/config/liquibase/changelog/20250814001_adding_suricata.xml new file mode 100644 index 000000000..46a147b1b --- /dev/null +++ b/backend/src/main/resources/config/liquibase/changelog/20250814001_adding_suricata.xml @@ -0,0 +1,617 @@ + + + + + + + + + + + + + do + $$ + begin + perform public.execute_register_integration_function(); + end; + $$ + language plpgsql; + + + "message" + terminator => "" + } + + #Looking for datasource generated by an agent and parse original message + if [message]=~/\[utm_stack_agent_ds=(.+)\]-(.+)/ { + grok { + match => { + "message" => [ "\[utm_stack_agent_ds=%{DATA:dataSource}\]-%{GREEDYDATA:original_log_message}" ] + } + } + } + if [original_log_message] { + mutate { + update => { "message" => "%{[original_log_message]}" } + } + } + + if ![dataType] { + # Parse Suricata logs from syslog + if [message] =~ /suricata\[\d+\]:.*event_type/ { + grok { + match => { + "message" => "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{HOSTNAME:syslog_host} %{PROG:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:suricata_json}" + } + tag_on_failure => ["_grokparsefailure_suricata"] + } + + if [suricata_json] { + json { + source => "suricata_json" + } + mutate { + remove_field => ["suricata_json", "syslog_pri", "syslog_timestamp", "syslog_program", "syslog_pid"] + } + } + + + # Process all Suricata event types (from both syslog and file) + if [event_type] and ([event_type] == "anomaly" or [event_type] == "tls" or [event_type] == "flow" + or [event_type] == "alert" or [event_type] == "dns" or [event_type] == "ssh" + or [event_type] == "http" or [event_type] == "ftp" or [event_type] == "ftp_data" + or [event_type] == "tftp" or [event_type] == "smb" or [event_type] == "initial_request" + or [event_type] == "initial_response" or [event_type] == "connect_request" or [event_type] == "connect_response" + or [event_type] == "tls_handshake" or [rdp] or [event_type] == "rfb" or [event_type] == "mqtt" + or [event_type] == "http2" or [event_type] == "pgsql" or [event_type] == "ike" + or [event_type] == "ikev1" or [event_type] == "ikev2" + or [event_type] == "modbus" or [event_type] == "quic" or [event_type] == "snmp" + or [event_type] == "fileinfo" or [event_type] == "sip" or [event_type] == "dhcp") { + mutate { + rename => ["dest_ip", "[logx][suricata][dest_ip]"] + rename => ["dest_port", "[logx][suricata][dest_port]"] + rename => ["flow_id", "[logx][suricata][flow_id]"] + rename => ["host", "[logx][suricata][host]"] + rename => ["in_iface", "[logx][suricata][in_iface]"] + rename => ["proto", "[logx][suricata][proto]"] + rename => ["src_ip", "[logx][suricata][src_ip]"] + rename => ["src_port", "[logx][suricata][src_port]"] + rename => ["tx_id", "[logx][suricata][tx_id]"] + } + } + + # Set dataSource from syslog_host or host + if (![dataSource]){ + if [syslog_host] { + mutate { + add_field => { "dataSource" => "%{syslog_host}" } + } + } else if [host] { + mutate { + add_field => { "dataSource" => "%{host}" } + } + } + } + + # Clean up syslog_host field after using it + if [syslog_host] { + mutate { + remove_field => ["syslog_host"] + } + } + + # Add dataType and clean up fields + mutate { + add_field => { + "dataType" => "suricata" + } + remove_field => [ "timestamp", "type", "path"] + rename => ["event_type", "[logx][suricata][event_type]"] + } + if [tls] { + mutate { + rename => ["tls", "[logx][suricata][tls]"] + } + } + if [ssh] { + mutate { + rename => ["ssh", "[logx][suricata][ssh]"] + } + } + if [stats] { + mutate { + rename => ["stats", "[logx][suricata][stats]"] + } + } + if [flow] { + mutate { + rename => ["flow", "[logx][suricata][flow]"] + } + } + if [tcp] { + mutate { + rename => ["tcp", "[logx][suricata][tcp]"] + } + } + if [dns] { + mutate { + rename => ["dns", "[logx][suricata][dns]"] + } + } + if [app_proto] { + mutate { + rename => ["app_proto", "[logx][suricata][app_proto]"] + } + } + if [anomaly] { + mutate { + rename => ["anomaly", "[logx][suricata][anomaly]"] + } + } + if [alert] { + mutate { + rename => ["alert", "[logx][suricata][alert]"] + } + if [logx][suricata][alert][severity] { + if [logx][suricata][alert][severity] >= 3 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "Low" + "[logx][suricata][severity]" => 1 + } + } + } + if [logx][suricata][alert][severity] == 2 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "Medium" + "[logx][suricata][severity]" => 2 + } + } + } + if [logx][suricata][alert][severity] == 1 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "High" + "[logx][suricata][severity]" => 3 + } + } + } + mutate { + remove_field => [ "[logx][suricata][alert][severity]" ] + } + } + } + #....................................................................... + # Add new event_types to logx structure, detected in real logs, present in suricata 7.0.0 + + mutate { + rename => ["http", "[logx][suricata][http]"] + rename => ["ftp", "[logx][suricata][ftp]"] + rename => ["ftp_data", "[logx][suricata][ftp_data]"] + rename => ["tftp", "[logx][suricata][tftp]"] + rename => ["smb", "[logx][suricata][smb]"] + + # RDP event_type + rename => ["rdp", "[logx][suricata][rdp]"] + # End RDP event_type + + rename => ["rfb", "[logx][suricata][rfb]"] + rename => ["mqtt", "[logx][suricata][mqtt]"] + rename => ["http2", "[logx][suricata][http2]"] + rename => ["pgsql", "[logx][suricata][pgsql]"] + rename => ["ike", "[logx][suricata][ike]"] + rename => ["ikev1", "[logx][suricata][ike]"] + rename => ["ikev2", "[logx][suricata][ike]"] + rename => ["modbus", "[logx][suricata][modbus]"] + rename => ["quic", "[logx][suricata][quic]"] + + # New fields from real logs, not present in suricata docs + rename => ["snmp", "[logx][suricata][snmp]"] + rename => ["fileinfo", "[logx][suricata][fileinfo]"] + rename => ["sip", "[logx][suricata][sip]"] + rename => ["dhcp", "[logx][suricata][dhcp]"] + + # This field isnt an event_type but appear in alert real logs + rename => ["files", "[logx][suricata][alert][files]"] + } + + #....................................................................... + # Add fields to logx structure, detected outside th event_type, present in suricata 7.0.0 + if [logx][suricata][event_type] == "mqtt" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][mqtt][pcap_cnt]"] + } + } else if [logx][suricata][event_type] == "pgsql" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][pgsql][pcap_cnt]"] + } + } else if [logx][suricata][event_type] == "fileinfo" { + if [logx][suricata][http] { + mutate { + rename => ["fileinfo", "[logx][suricata][http][fileinfo]"] + } + } else if [logx][suricata][http2] { + mutate { + rename => ["fileinfo", "[logx][suricata][http2][fileinfo]"] + } + } else { + mutate { + rename => ["fileinfo", "[logx][suricata][fileinfo]"] + } + } + } else if [logx][suricata][event_type] == "anomaly" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][anomaly][pcap_cnt]"] + rename => ["packet", "[logx][suricata][anomaly][packet]"] + rename => ["packet_info", "[logx][suricata][anomaly][packet_info]"] + } + } else if [logx][suricata][event_type] == "flow" { + mutate { + rename => ["icmp_type", "[logx][suricata][flow][icmp_type]"] + rename => ["icmp_code", "[logx][suricata][flow][icmp_code]"] + rename => ["response_icmp_code", "[logx][suricata][flow][response_icmp_code]"] + rename => ["response_icmp_type", "[logx][suricata][flow][response_icmp_type]"] + } + } + + #....................................................................... + # Implementing logx.utm.action field used for established connections + if [logx][suricata][event_type] == "tls" { + if ![logx][suricata][tls][session_resumed] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "dns" { + if [logx][suricata][dns][type] and [logx][suricata][dns][type] == "answer" { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "flow" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][flow][bytes_toserver] and [logx][suricata][flow][bytes_toserver] > 0) and + ([logx][suricata][flow][bytes_toclient] and [logx][suricata][flow][bytes_toclient] > 0) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ssh" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + [logx][suricata][ssh][server] and [logx][suricata][ssh][client] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "alert" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][alert][action] == "allowed" and + ([logx][suricata][flow][bytes_toserver] and [logx][suricata][flow][bytes_toserver] > 0) and + ([logx][suricata][flow][bytes_toclient] and [logx][suricata][flow][bytes_toclient] > 0) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "http" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][http][status] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ftp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][ftp][completion_code] { + ruby { + code => " + event.get('[logx][suricata][ftp][completion_code]').each_with_index do |value,key| + if value =~ /(2\d\d)|(125)/ + event.set('[logx][utm][action]', 'Success') + end + end + " + } + } + } else if [logx][suricata][event_type] == "tftp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][tftp][packet] and [logx][suricata][tftp][packet] != "error") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "smb" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ( [logx][suricata][smb][command] and "NEGOTIATE" in [logx][suricata][smb][command] ) and + [logx][suricata][smb][status] and ( "SUCCESS" in [logx][suricata][smb][status] or + "GRANTED" in [logx][suricata][smb][status] or "CONNECTED" in [logx][suricata][smb][status]) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "rdp" + or ([logx][suricata][rdp][event_type] and ([logx][suricata][rdp][event_type] == "initial_response" + or [logx][suricata][rdp][event_type] == "initial_request" or [logx][suricata][rdp][event_type] == "connect_request" + or [logx][suricata][rdp][event_type] == "connect_response" or [logx][suricata][rdp][event_type] == "tls_handshake") ) { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][rdp][event_type] == "connect_response" or [logx][suricata][rdp][event_type] == "tls_handshake") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "rfb" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][rfb][authentication][security-result] and [logx][suricata][rfb][authentication][security-result] == "OK") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "mqtt" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][mqtt][connack][return_code] and + ([logx][suricata][mqtt][connack][return_code] == 0 or [logx][suricata][mqtt][connack][return_code] == "0x00")) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "http2" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][http2][response][headers] ) { + ruby { + code => " + event.get('[logx][suricata][http2][response][headers]').each_with_index do |value,key| + if (value['name'] == 'status' or value['name'] == ':status') + event.set('[logx][utm][action]', 'Success') + end + end + " + } + } + } else if [logx][suricata][event_type] == "pgsql" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][pgsql][request][simple_query] or [logx][suricata][pgsql][response][command_completed] or + ([logx][suricata][pgsql][response][ssl_accepted] and [logx][suricata][pgsql][response][ssl_accepted] == "true") or + ([logx][suricata][pgsql][response][accepted] and [logx][suricata][pgsql][response][accepted] == "true") or + [logx][suricata][pgsql][response][authentication_md5_password] ) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ike" or [logx][suricata][event_type] == "ikev1" or [logx][suricata][event_type] == "ikev2" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "modbus" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "sip" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "quic" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "fileinfo" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "snmp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "dhcp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][dhcp][assigned_ip] and [logx][suricata][dhcp][assigned_ip] != "0") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } + } + # Remove fields that are not needed + mutate { + remove_field => ["original_log_message", "suricata_json"] + } + } +}$$, 'suricata', null, true, 'SURICATA', false, '2.0.0'); + ]]> + + + + + + + + diff --git a/backend/src/main/resources/config/liquibase/master.xml b/backend/src/main/resources/config/liquibase/master.xml index ec2ce533d..72ec78fe6 100644 --- a/backend/src/main/resources/config/liquibase/master.xml +++ b/backend/src/main/resources/config/liquibase/master.xml @@ -107,5 +107,7 @@ + + diff --git a/filters/nids/nids-ids.conf b/filters/nids/nids-ids.conf deleted file mode 100644 index 5e4d55c8e..000000000 --- a/filters/nids/nids-ids.conf +++ /dev/null @@ -1,355 +0,0 @@ -filter { - -# NIDS filter version 1.3.2 -# Based on https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html (latest 7.0.0) (april 2022) -# and real events log provided -# Support json format - - if [path] and [path] == "/var/log/suricata/eve.json" { - if [message] { - json { source => "message" } - } - if [event_type] and ([event_type] == "anomaly" or [event_type] == "tls" or [event_type] == "flow" - or [event_type] == "alert" or [event_type] == "dns" or [event_type] == "ssh" - or [event_type] == "http" or [event_type] == "ftp" or [event_type] == "ftp_data" - or [event_type] == "tftp" or [event_type] == "smb" or [event_type] == "initial_request" - or [event_type] == "initial_response" or [event_type] == "connect_request" or [event_type] == "connect_response" - or [event_type] == "tls_handshake" or [rdp] or [event_type] == "rfb" or [event_type] == "mqtt" - or [event_type] == "http2" or [event_type] == "pgsql" or [event_type] == "ike" - or [event_type] == "ikev1" or [event_type] == "ikev2" - or [event_type] == "modbus" or [event_type] == "quic" or [event_type] == "snmp" - or [event_type] == "fileinfo" or [event_type] == "sip" or [event_type] == "dhcp") { - mutate { - rename => ["dest_ip", "[logx][nids][dest_ip]"] - rename => ["dest_port", "[logx][nids][dest_port]"] - rename => ["flow_id", "[logx][nids][flow_id]"] - rename => ["host", "[logx][nids][host]"] - rename => ["in_iface", "[logx][nids][in_iface]"] - rename => ["proto", "[logx][nids][proto]"] - rename => ["src_ip", "[logx][nids][src_ip]"] - rename => ["src_port", "[logx][nids][src_port]"] - rename => ["tx_id", "[logx][nids][tx_id]"] - } - } - mutate { - add_field => { - "dataType" => "nids" - } - add_field => { - "dataSource" => "nids" - } - remove_field => [ "timestamp", "type", "path"] - rename => ["event_type", "[logx][nids][event_type]"] - } - if [tls] { - mutate { - rename => ["tls", "[logx][nids][tls]"] - } - } - if [ssh] { - mutate { - rename => ["ssh", "[logx][nids][ssh]"] - } - } - if [stats] { - mutate { - rename => ["stats", "[logx][nids][stats]"] - } - } - if [flow] { - mutate { - rename => ["flow", "[logx][nids][flow]"] - } - } - if [tcp] { - mutate { - rename => ["tcp", "[logx][nids][tcp]"] - } - } - if [dns] { - mutate { - rename => ["dns", "[logx][nids][dns]"] - } - } - if [app_proto] { - mutate { - rename => ["app_proto", "[logx][nids][app_proto]"] - } - } - if [anomaly] { - mutate { - rename => ["anomaly", "[logx][nids][anomaly]"] - } - } - if [alert] { - mutate { - rename => ["alert", "[logx][nids][alert]"] - } - if [logx][nids][alert][severity] { - if [logx][nids][alert][severity] >= 3 { - mutate { - add_field => { - "[logx][nids][severity_label]" => "Low" - "[logx][nids][severity]" => 1 - } - } - } - if [logx][nids][alert][severity] == 2 { - mutate { - add_field => { - "[logx][nids][severity_label]" => "Medium" - "[logx][nids][severity]" => 2 - } - } - } - if [logx][nids][alert][severity] == 1 { - mutate { - add_field => { - "[logx][nids][severity_label]" => "High" - "[logx][nids][severity]" => 3 - } - } - } - mutate { - remove_field => [ "[logx][nids][alert][severity]" ] - } - } - } -#....................................................................... -# Add new event_types to logx structure, detected in real logs, present in suricata 7.0.0 - - mutate { - rename => ["http", "[logx][nids][http]"] - rename => ["ftp", "[logx][nids][ftp]"] - rename => ["ftp_data", "[logx][nids][ftp_data]"] - rename => ["tftp", "[logx][nids][tftp]"] - rename => ["smb", "[logx][nids][smb]"] - - # RDP event_type - rename => ["rdp", "[logx][nids][rdp]"] - # End RDP event_type - - rename => ["rfb", "[logx][nids][rfb]"] - rename => ["mqtt", "[logx][nids][mqtt]"] - rename => ["http2", "[logx][nids][http2]"] - rename => ["pgsql", "[logx][nids][pgsql]"] - rename => ["ike", "[logx][nids][ike]"] - rename => ["ikev1", "[logx][nids][ike]"] - rename => ["ikev2", "[logx][nids][ike]"] - rename => ["modbus", "[logx][nids][modbus]"] - rename => ["quic", "[logx][nids][quic]"] - - # New fields from real logs, not present in suricata docs - rename => ["snmp", "[logx][nids][snmp]"] - rename => ["fileinfo", "[logx][nids][fileinfo]"] - rename => ["sip", "[logx][nids][sip]"] - rename => ["dhcp", "[logx][nids][dhcp]"] - - # This field isnt an event_type but appear in alert real logs - rename => ["files", "[logx][nids][alert][files]"] - } - -#....................................................................... -# Add fields to logx structure, detected outside th event_type, present in suricata 7.0.0 - if [logx][nids][event_type] == "mqtt" { - mutate { - rename => ["pcap_cnt", "[logx][nids][mqtt][pcap_cnt]"] - } - } else if [logx][nids][event_type] == "pgsql" { - mutate { - rename => ["pcap_cnt", "[logx][nids][pgsql][pcap_cnt]"] - } - } else if [logx][nids][event_type] == "fileinfo" { - if [logx][nids][http] { - mutate { - rename => ["fileinfo", "[logx][nids][http][fileinfo]"] - } - } else if [logx][nids][http2] { - mutate { - rename => ["fileinfo", "[logx][nids][http2][fileinfo]"] - } - } else { - mutate { - rename => ["fileinfo", "[logx][nids][fileinfo]"] - } - } - } else if [logx][nids][event_type] == "anomaly" { - mutate { - rename => ["pcap_cnt", "[logx][nids][anomaly][pcap_cnt]"] - rename => ["packet", "[logx][nids][anomaly][packet]"] - rename => ["packet_info", "[logx][nids][anomaly][packet_info]"] - } - } else if [logx][nids][event_type] == "flow" { - mutate { - rename => ["icmp_type", "[logx][nids][flow][icmp_type]"] - rename => ["icmp_code", "[logx][nids][flow][icmp_code]"] - rename => ["response_icmp_code", "[logx][nids][flow][response_icmp_code]"] - rename => ["response_icmp_type", "[logx][nids][flow][response_icmp_type]"] - } - } - -#....................................................................... -# Implementing logx.utm.action field used for established connections - if [logx][nids][event_type] == "tls" { - if ![logx][nids][tls][session_resumed] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "dns" { - if [logx][nids][dns][type] and [logx][nids][dns][type] == "answer" { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "flow" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][flow][bytes_toserver] and [logx][nids][flow][bytes_toserver] > 0) and - ([logx][nids][flow][bytes_toclient] and [logx][nids][flow][bytes_toclient] > 0) { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "ssh" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - [logx][nids][ssh][server] and [logx][nids][ssh][client] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "alert" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and [logx][nids][alert][action] == "allowed" and - ([logx][nids][flow][bytes_toserver] and [logx][nids][flow][bytes_toserver] > 0) and - ([logx][nids][flow][bytes_toclient] and [logx][nids][flow][bytes_toclient] > 0) { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "http" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and [logx][nids][http][status] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "ftp" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and [logx][nids][ftp][completion_code] { - ruby { - code => " - event.get('[logx][nids][ftp][completion_code]').each_with_index do |value,key| - if value =~ /(2\d\d)|(125)/ - event.set('[logx][utm][action]', 'Success') - end - end - " - } - } - } else if [logx][nids][event_type] == "tftp" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][tftp][packet] and [logx][nids][tftp][packet] != "error") { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "smb" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ( [logx][nids][smb][command] and "NEGOTIATE" in [logx][nids][smb][command] ) and - [logx][nids][smb][status] and ( "SUCCESS" in [logx][nids][smb][status] or - "GRANTED" in [logx][nids][smb][status] or "CONNECTED" in [logx][nids][smb][status]) { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "rdp" - or ([logx][nids][rdp][event_type] and ([logx][nids][rdp][event_type] == "initial_response" - or [logx][nids][rdp][event_type] == "initial_request" or [logx][nids][rdp][event_type] == "connect_request" - or [logx][nids][rdp][event_type] == "connect_response" or [logx][nids][rdp][event_type] == "tls_handshake") ) { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][rdp][event_type] == "connect_response" or [logx][nids][rdp][event_type] == "tls_handshake") { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "rfb" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][rfb][authentication][security-result] and [logx][nids][rfb][authentication][security-result] == "OK") { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "mqtt" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][mqtt][connack][return_code] and - ([logx][nids][mqtt][connack][return_code] == 0 or [logx][nids][mqtt][connack][return_code] == "0x00")) { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "http2" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][http2][response][headers] ) { - ruby { - code => " - event.get('[logx][nids][http2][response][headers]').each_with_index do |value,key| - if (value['name'] == 'status' or value['name'] == ':status') - event.set('[logx][utm][action]', 'Success') - end - end - " - } - } - } else if [logx][nids][event_type] == "pgsql" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][pgsql][request][simple_query] or [logx][nids][pgsql][response][command_completed] or - ([logx][nids][pgsql][response][ssl_accepted] and [logx][nids][pgsql][response][ssl_accepted] == "true") or - ([logx][nids][pgsql][response][accepted] and [logx][nids][pgsql][response][accepted] == "true") or - [logx][nids][pgsql][response][authentication_md5_password] ) { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "ike" or [logx][nids][event_type] == "ikev1" or [logx][nids][event_type] == "ikev2" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "modbus" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "sip" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "quic" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "fileinfo" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "snmp" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } else if [logx][nids][event_type] == "dhcp" { - if [logx][nids][src_ip] and [logx][nids][dest_ip] and - ([logx][nids][dhcp][assigned_ip] and [logx][nids][dhcp][assigned_ip] != "0") { - mutate { - add_field => { "[logx][utm][action]" => "Success" } - } - } - } - } -} diff --git a/filters/suricata/suricata.conf b/filters/suricata/suricata.conf new file mode 100644 index 000000000..12f6c8f4e --- /dev/null +++ b/filters/suricata/suricata.conf @@ -0,0 +1,414 @@ +filter { + +# Suricata filter version 1.0.4 +# Based on https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html (latest 8.0.0) (august 2025) +# and real events log provided +# Support json format + split { + field => "message" + terminator => "" + } + + #Looking for datasource generated by an agent and parse original message + if [message]=~/\[utm_stack_agent_ds=(.+)\]-(.+)/ { + grok { + match => { + "message" => [ "\[utm_stack_agent_ds=%{DATA:dataSource}\]-%{GREEDYDATA:original_log_message}" ] + } + } + } + if [original_log_message] { + mutate { + update => { "message" => "%{[original_log_message]}" } + } + } + + if ![dataType] { + # Parse Suricata logs from syslog + if [message] =~ /suricata\[\d+\]:.*event_type/ { + grok { + match => { + "message" => "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{HOSTNAME:syslog_host} %{PROG:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:suricata_json}" + } + tag_on_failure => ["_grokparsefailure_suricata"] + } + + if [suricata_json] { + json { + source => "suricata_json" + } + mutate { + remove_field => ["suricata_json", "syslog_pri", "syslog_timestamp", "syslog_program", "syslog_pid"] + } + } + + + # Process all Suricata event types (from both syslog and file) + if [event_type] and ([event_type] == "anomaly" or [event_type] == "tls" or [event_type] == "flow" + or [event_type] == "alert" or [event_type] == "dns" or [event_type] == "ssh" + or [event_type] == "http" or [event_type] == "ftp" or [event_type] == "ftp_data" + or [event_type] == "tftp" or [event_type] == "smb" or [event_type] == "initial_request" + or [event_type] == "initial_response" or [event_type] == "connect_request" or [event_type] == "connect_response" + or [event_type] == "tls_handshake" or [rdp] or [event_type] == "rfb" or [event_type] == "mqtt" + or [event_type] == "http2" or [event_type] == "pgsql" or [event_type] == "ike" + or [event_type] == "ikev1" or [event_type] == "ikev2" + or [event_type] == "modbus" or [event_type] == "quic" or [event_type] == "snmp" + or [event_type] == "fileinfo" or [event_type] == "sip" or [event_type] == "dhcp") { + mutate { + rename => ["dest_ip", "[logx][suricata][dest_ip]"] + rename => ["dest_port", "[logx][suricata][dest_port]"] + rename => ["flow_id", "[logx][suricata][flow_id]"] + rename => ["host", "[logx][suricata][host]"] + rename => ["in_iface", "[logx][suricata][in_iface]"] + rename => ["proto", "[logx][suricata][proto]"] + rename => ["src_ip", "[logx][suricata][src_ip]"] + rename => ["src_port", "[logx][suricata][src_port]"] + rename => ["tx_id", "[logx][suricata][tx_id]"] + } + } + + # Set dataSource from syslog_host or host + if (![dataSource]){ + if [syslog_host] { + mutate { + add_field => { "dataSource" => "%{syslog_host}" } + } + } else if [host] { + mutate { + add_field => { "dataSource" => "%{host}" } + } + } + } + + # Clean up syslog_host field after using it + if [syslog_host] { + mutate { + remove_field => ["syslog_host"] + } + } + + # Add dataType and clean up fields + mutate { + add_field => { + "dataType" => "suricata" + } + remove_field => [ "timestamp", "type", "path"] + rename => ["event_type", "[logx][suricata][event_type]"] + } + if [tls] { + mutate { + rename => ["tls", "[logx][suricata][tls]"] + } + } + if [ssh] { + mutate { + rename => ["ssh", "[logx][suricata][ssh]"] + } + } + if [stats] { + mutate { + rename => ["stats", "[logx][suricata][stats]"] + } + } + if [flow] { + mutate { + rename => ["flow", "[logx][suricata][flow]"] + } + } + if [tcp] { + mutate { + rename => ["tcp", "[logx][suricata][tcp]"] + } + } + if [dns] { + mutate { + rename => ["dns", "[logx][suricata][dns]"] + } + } + if [app_proto] { + mutate { + rename => ["app_proto", "[logx][suricata][app_proto]"] + } + } + if [anomaly] { + mutate { + rename => ["anomaly", "[logx][suricata][anomaly]"] + } + } + if [alert] { + mutate { + rename => ["alert", "[logx][suricata][alert]"] + } + if [logx][suricata][alert][severity] { + if [logx][suricata][alert][severity] >= 3 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "Low" + "[logx][suricata][severity]" => 1 + } + } + } + if [logx][suricata][alert][severity] == 2 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "Medium" + "[logx][suricata][severity]" => 2 + } + } + } + if [logx][suricata][alert][severity] == 1 { + mutate { + add_field => { + "[logx][suricata][severity_label]" => "High" + "[logx][suricata][severity]" => 3 + } + } + } + mutate { + remove_field => [ "[logx][suricata][alert][severity]" ] + } + } + } + #....................................................................... + # Add new event_types to logx structure, detected in real logs, present in suricata 7.0.0 + + mutate { + rename => ["http", "[logx][suricata][http]"] + rename => ["ftp", "[logx][suricata][ftp]"] + rename => ["ftp_data", "[logx][suricata][ftp_data]"] + rename => ["tftp", "[logx][suricata][tftp]"] + rename => ["smb", "[logx][suricata][smb]"] + + # RDP event_type + rename => ["rdp", "[logx][suricata][rdp]"] + # End RDP event_type + + rename => ["rfb", "[logx][suricata][rfb]"] + rename => ["mqtt", "[logx][suricata][mqtt]"] + rename => ["http2", "[logx][suricata][http2]"] + rename => ["pgsql", "[logx][suricata][pgsql]"] + rename => ["ike", "[logx][suricata][ike]"] + rename => ["ikev1", "[logx][suricata][ike]"] + rename => ["ikev2", "[logx][suricata][ike]"] + rename => ["modbus", "[logx][suricata][modbus]"] + rename => ["quic", "[logx][suricata][quic]"] + + # New fields from real logs, not present in suricata docs + rename => ["snmp", "[logx][suricata][snmp]"] + rename => ["fileinfo", "[logx][suricata][fileinfo]"] + rename => ["sip", "[logx][suricata][sip]"] + rename => ["dhcp", "[logx][suricata][dhcp]"] + + # This field isnt an event_type but appear in alert real logs + rename => ["files", "[logx][suricata][alert][files]"] + } + + #....................................................................... + # Add fields to logx structure, detected outside th event_type, present in suricata 7.0.0 + if [logx][suricata][event_type] == "mqtt" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][mqtt][pcap_cnt]"] + } + } else if [logx][suricata][event_type] == "pgsql" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][pgsql][pcap_cnt]"] + } + } else if [logx][suricata][event_type] == "fileinfo" { + if [logx][suricata][http] { + mutate { + rename => ["fileinfo", "[logx][suricata][http][fileinfo]"] + } + } else if [logx][suricata][http2] { + mutate { + rename => ["fileinfo", "[logx][suricata][http2][fileinfo]"] + } + } else { + mutate { + rename => ["fileinfo", "[logx][suricata][fileinfo]"] + } + } + } else if [logx][suricata][event_type] == "anomaly" { + mutate { + rename => ["pcap_cnt", "[logx][suricata][anomaly][pcap_cnt]"] + rename => ["packet", "[logx][suricata][anomaly][packet]"] + rename => ["packet_info", "[logx][suricata][anomaly][packet_info]"] + } + } else if [logx][suricata][event_type] == "flow" { + mutate { + rename => ["icmp_type", "[logx][suricata][flow][icmp_type]"] + rename => ["icmp_code", "[logx][suricata][flow][icmp_code]"] + rename => ["response_icmp_code", "[logx][suricata][flow][response_icmp_code]"] + rename => ["response_icmp_type", "[logx][suricata][flow][response_icmp_type]"] + } + } + + #....................................................................... + # Implementing logx.utm.action field used for established connections + if [logx][suricata][event_type] == "tls" { + if ![logx][suricata][tls][session_resumed] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "dns" { + if [logx][suricata][dns][type] and [logx][suricata][dns][type] == "answer" { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "flow" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][flow][bytes_toserver] and [logx][suricata][flow][bytes_toserver] > 0) and + ([logx][suricata][flow][bytes_toclient] and [logx][suricata][flow][bytes_toclient] > 0) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ssh" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + [logx][suricata][ssh][server] and [logx][suricata][ssh][client] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "alert" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][alert][action] == "allowed" and + ([logx][suricata][flow][bytes_toserver] and [logx][suricata][flow][bytes_toserver] > 0) and + ([logx][suricata][flow][bytes_toclient] and [logx][suricata][flow][bytes_toclient] > 0) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "http" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][http][status] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ftp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][ftp][completion_code] { + ruby { + code => " + event.get('[logx][suricata][ftp][completion_code]').each_with_index do |value,key| + if value =~ /(2\d\d)|(125)/ + event.set('[logx][utm][action]', 'Success') + end + end + " + } + } + } else if [logx][suricata][event_type] == "tftp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][tftp][packet] and [logx][suricata][tftp][packet] != "error") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "smb" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ( [logx][suricata][smb][command] and "NEGOTIATE" in [logx][suricata][smb][command] ) and + [logx][suricata][smb][status] and ( "SUCCESS" in [logx][suricata][smb][status] or + "GRANTED" in [logx][suricata][smb][status] or "CONNECTED" in [logx][suricata][smb][status]) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "rdp" + or ([logx][suricata][rdp][event_type] and ([logx][suricata][rdp][event_type] == "initial_response" + or [logx][suricata][rdp][event_type] == "initial_request" or [logx][suricata][rdp][event_type] == "connect_request" + or [logx][suricata][rdp][event_type] == "connect_response" or [logx][suricata][rdp][event_type] == "tls_handshake") ) { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][rdp][event_type] == "connect_response" or [logx][suricata][rdp][event_type] == "tls_handshake") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "rfb" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][rfb][authentication][security-result] and [logx][suricata][rfb][authentication][security-result] == "OK") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "mqtt" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][mqtt][connack][return_code] and + ([logx][suricata][mqtt][connack][return_code] == 0 or [logx][suricata][mqtt][connack][return_code] == "0x00")) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "http2" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][http2][response][headers] ) { + ruby { + code => " + event.get('[logx][suricata][http2][response][headers]').each_with_index do |value,key| + if (value['name'] == 'status' or value['name'] == ':status') + event.set('[logx][utm][action]', 'Success') + end + end + " + } + } + } else if [logx][suricata][event_type] == "pgsql" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][pgsql][request][simple_query] or [logx][suricata][pgsql][response][command_completed] or + ([logx][suricata][pgsql][response][ssl_accepted] and [logx][suricata][pgsql][response][ssl_accepted] == "true") or + ([logx][suricata][pgsql][response][accepted] and [logx][suricata][pgsql][response][accepted] == "true") or + [logx][suricata][pgsql][response][authentication_md5_password] ) { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "ike" or [logx][suricata][event_type] == "ikev1" or [logx][suricata][event_type] == "ikev2" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "modbus" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "sip" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "quic" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "fileinfo" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "snmp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } else if [logx][suricata][event_type] == "dhcp" { + if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and + ([logx][suricata][dhcp][assigned_ip] and [logx][suricata][dhcp][assigned_ip] != "0") { + mutate { + add_field => { "[logx][utm][action]" => "Success" } + } + } + } + } + # Remove fields that are not needed + mutate { + remove_field => ["original_log_message", "suricata_json"] + } + } +} diff --git a/frontend/src/app/app-module/guides/guide-syslog/guide-syslog.component.ts b/frontend/src/app/app-module/guides/guide-syslog/guide-syslog.component.ts index 896a0e12c..5a00ae6d8 100644 --- a/frontend/src/app/app-module/guides/guide-syslog/guide-syslog.component.ts +++ b/frontend/src/app/app-module/guides/guide-syslog/guide-syslog.component.ts @@ -72,6 +72,9 @@ export class GuideSyslogComponent implements OnInit { {module: UtmModulesEnum.AIX, port: '7016 TCP'}, {module: UtmModulesEnum.AIX, port: '7016 UDP'}, + + {module: UtmModulesEnum.SURICATA, port: '7019 TCP'}, + {module: UtmModulesEnum.SURICATA, port: '7019 UDP'}, ]; steps: Step[] = SYSLOGSTEPS; diff --git a/frontend/src/app/app-module/guides/shared/components/log-collector.component.ts b/frontend/src/app/app-module/guides/shared/components/log-collector.component.ts index 2294c1a47..3a6777a8b 100644 --- a/frontend/src/app/app-module/guides/shared/components/log-collector.component.ts +++ b/frontend/src/app/app-module/guides/shared/components/log-collector.component.ts @@ -170,6 +170,9 @@ export class LogCollectorComponent { case UtmModulesEnum.NETFLOW: return 'netflow'; + case UtmModulesEnum.SURICATA: + return 'suricata'; + case UtmModulesEnum.FIRE_POWER: case UtmModulesEnum.CISCO: case UtmModulesEnum.CISCO_SWITCH: diff --git a/frontend/src/app/app-module/module-integration/module-integration.component.html b/frontend/src/app/app-module/module-integration/module-integration.component.html index 8843ac63d..2ea24ef66 100644 --- a/frontend/src/app/app-module/module-integration/module-integration.component.html +++ b/frontend/src/app/app-module/module-integration/module-integration.component.html @@ -179,6 +179,11 @@ [guideName]="module.prettyName" [integrationId]="module.id"> + + diff --git a/frontend/src/app/app-module/shared/enum/utm-module.enum.ts b/frontend/src/app/app-module/shared/enum/utm-module.enum.ts index 8cfd4c664..a9e067e42 100644 --- a/frontend/src/app/app-module/shared/enum/utm-module.enum.ts +++ b/frontend/src/app/app-module/shared/enum/utm-module.enum.ts @@ -66,5 +66,6 @@ export enum UtmModulesEnum { SALESFORCE = 'SALESFORCE', BITDEFENDER = 'BITDEFENDER', AS_400 = 'AS_400', - SOC_AI = 'SOC_AI' + SOC_AI = 'SOC_AI', + SURICATA = 'SURICATA', } diff --git a/frontend/src/assets/img/guides/logos/suricata.png b/frontend/src/assets/img/guides/logos/suricata.png new file mode 100644 index 000000000..c20f9dd25 Binary files /dev/null and b/frontend/src/assets/img/guides/logos/suricata.png differ diff --git a/log-auth-proxy/config/constants.go b/log-auth-proxy/config/constants.go index 9cfde63c8..e254b8987 100644 --- a/log-auth-proxy/config/constants.go +++ b/log-auth-proxy/config/constants.go @@ -72,6 +72,7 @@ const ( AS400 = "as_400" FirewallPfsense = "firewall_pfsense" FirewallFortiweb = "firewall_fortiweb" + Suricata = "suricata" ) type ServiceStatus string diff --git a/version.yml b/version.yml index 5dd9cf489..fdbb687c1 100644 --- a/version.yml +++ b/version.yml @@ -1 +1 @@ -version: 10.8.6 \ No newline at end of file +version: 10.9.0 \ No newline at end of file