|
21 | 21 | VALUES ('Suricata', |
22 | 22 | 'Suricata is an open-source based intrusion detection system (IDS) and intrusion prevention system (IPS).', |
23 | 23 | FALSE, |
24 | | - 'suricata.svg', |
| 24 | + 'suricata.png', |
25 | 25 | 'SURICATA', |
26 | 26 | srv_id, |
27 | 27 | 'Device', |
28 | 28 | FALSE, |
29 | 29 | TRUE, |
30 | 30 | TRUE) |
31 | 31 | ON CONFLICT (module_name, server_id) DO UPDATE SET pretty_name = 'Suricata', |
32 | | - module_icon = 'suricata.svg', |
| 32 | + module_icon = 'suricata.png', |
33 | 33 | module_name = 'SURICATA', |
34 | 34 | module_category = 'Device', |
35 | 35 | module_description = 'Suricata is an open-source based intrusion detection system (IDS) and intrusion prevention system (IPS).', |
|
164 | 164 | <sql dbms="postgresql" splitStatements="true" stripComments="true"> |
165 | 165 | <![CDATA[ |
166 | 166 | INSERT INTO utm_logstash_filter (id, logstash_filter, filter_name, filter_group_id, system_owner, module_name, is_active, filter_version) |
167 | | - VALUES (1528, 'filter { |
| 167 | + VALUES (1528, $$filter { |
168 | 168 |
|
169 | | -# Suricata filter version 1.0.0 |
| 169 | +# Suricata filter version 1.0.4 |
170 | 170 | # Based on https://suricata.readthedocs.io/en/latest/output/eve/eve-json-format.html (latest 8.0.0) (august 2025) |
171 | 171 | # and real events log provided |
172 | 172 | # Support json format |
|
190 | 190 | } |
191 | 191 |
|
192 | 192 | if ![dataType] { |
193 | | - if [path] and [path] == "/var/log/suricata/eve.json" { |
194 | | - if [message] { |
195 | | - json { source => "message" } |
| 193 | + # Parse Suricata logs from syslog |
| 194 | + if [message] =~ /suricata\[\d+\]:.*event_type/ { |
| 195 | + grok { |
| 196 | + match => { |
| 197 | + "message" => "<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{HOSTNAME:syslog_host} %{PROG:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:suricata_json}" |
196 | 198 | } |
197 | | - if [event_type] and ([event_type] == "anomaly" or [event_type] == "tls" or [event_type] == "flow" |
| 199 | + tag_on_failure => ["_grokparsefailure_suricata"] |
| 200 | + } |
| 201 | +
|
| 202 | + if [suricata_json] { |
| 203 | + json { |
| 204 | + source => "suricata_json" |
| 205 | + } |
| 206 | + mutate { |
| 207 | + remove_field => ["suricata_json", "syslog_pri", "syslog_timestamp", "syslog_program", "syslog_pid"] |
| 208 | + } |
| 209 | + } |
| 210 | +
|
| 211 | +
|
| 212 | + # Process all Suricata event types (from both syslog and file) |
| 213 | + if [event_type] and ([event_type] == "anomaly" or [event_type] == "tls" or [event_type] == "flow" |
198 | 214 | or [event_type] == "alert" or [event_type] == "dns" or [event_type] == "ssh" |
199 | 215 | or [event_type] == "http" or [event_type] == "ftp" or [event_type] == "ftp_data" |
200 | 216 | or [event_type] == "tftp" or [event_type] == "smb" or [event_type] == "initial_request" |
|
215 | 231 | rename => ["src_port", "[logx][suricata][src_port]"] |
216 | 232 | rename => ["tx_id", "[logx][suricata][tx_id]"] |
217 | 233 | } |
| 234 | + } |
| 235 | +
|
| 236 | + # Set dataSource from syslog_host or host |
| 237 | + if (![dataSource]){ |
| 238 | + if [syslog_host] { |
| 239 | + mutate { |
| 240 | + add_field => { "dataSource" => "%{syslog_host}" } |
218 | 241 | } |
219 | | - if (![dataSource]){ |
220 | | - mutate { |
221 | | - add_field => { "dataSource" => "%{host}" } |
222 | | - } |
| 242 | + } else if [host] { |
| 243 | + mutate { |
| 244 | + add_field => { "dataSource" => "%{host}" } |
223 | 245 | } |
| 246 | + } |
| 247 | + } |
224 | 248 |
|
225 | | - mutate { |
226 | | - add_field => { |
227 | | - "dataType" => "suricata" |
228 | | - } |
229 | | - remove_field => [ "timestamp", "type", "path"] |
230 | | - rename => ["event_type", "[logx][suricata][event_type]"] |
| 249 | + # Clean up syslog_host field after using it |
| 250 | + if [syslog_host] { |
| 251 | + mutate { |
| 252 | + remove_field => ["syslog_host"] |
| 253 | + } |
| 254 | + } |
| 255 | +
|
| 256 | + # Add dataType and clean up fields |
| 257 | + mutate { |
| 258 | + add_field => { |
| 259 | + "dataType" => "suricata" |
231 | 260 | } |
| 261 | + remove_field => [ "timestamp", "type", "path"] |
| 262 | + rename => ["event_type", "[logx][suricata][event_type]"] |
| 263 | + } |
232 | 264 | if [tls] { |
233 | 265 | mutate { |
234 | 266 | rename => ["tls", "[logx][suricata][tls]"] |
|
423 | 455 | if [logx][suricata][src_ip] and [logx][suricata][dest_ip] and [logx][suricata][ftp][completion_code] { |
424 | 456 | ruby { |
425 | 457 | code => " |
426 | | - event.get(''[logx][suricata][ftp][completion_code]'').each_with_index do |value,key| |
| 458 | + event.get('[logx][suricata][ftp][completion_code]').each_with_index do |value,key| |
427 | 459 | if value =~ /(2\d\d)|(125)/ |
428 | | - event.set(''[logx][utm][action]'', ''Success'') |
| 460 | + event.set('[logx][utm][action]', 'Success') |
429 | 461 | end |
430 | 462 | end |
431 | 463 | " |
|
477 | 509 | ([logx][suricata][http2][response][headers] ) { |
478 | 510 | ruby { |
479 | 511 | code => " |
480 | | - event.get(''[logx][suricata][http2][response][headers]'').each_with_index do |value,key| |
481 | | - if (value[''name''] == ''status'' or value[''name''] == '':status'') |
482 | | - event.set(''[logx][utm][action]'', ''Success'') |
| 512 | + event.get('[logx][suricata][http2][response][headers]').each_with_index do |value,key| |
| 513 | + if (value['name'] == 'status' or value['name'] == ':status') |
| 514 | + event.set('[logx][utm][action]', 'Success') |
483 | 515 | end |
484 | 516 | end |
485 | 517 | " |
|
540 | 572 | } |
541 | 573 | } |
542 | 574 | } |
| 575 | + # Remove fields that are not needed |
| 576 | + mutate { |
| 577 | + remove_field => ["original_log_message", "suricata_json"] |
| 578 | + } |
543 | 579 | } |
544 | | -}', 'suricata', null, true, 'SURICATA', false, '2.0.0'); |
| 580 | +}$$, 'suricata', null, true, 'SURICATA', false, '2.0.0'); |
545 | 581 | ]]> |
546 | 582 | </sql> |
547 | 583 | <sql dbms="postgresql" splitStatements="true" stripComments="true"> |
|
0 commit comments