# Original Author: Justin Henderson # SANS Instructor and author of SANS SEC555: SIEM and Tactical Analytics # Updated by: Doug Burks # Last Update: 2/10/2018 # filter { if "bro" in [tags] { # Bro logs have a high quality timestamp, so let's copy that to @timestamp. # Before we do, let's copy the existing logstash @timestamp to timestamp. mutate { add_field => { "logstash_timestamp" => "%{@timestamp}" } } mutate { convert => { "logstash_timestamp" => "string" } } mutate { convert => { "timestamp" => "string" } } # New Bro JSON logs use ISO8601 timestamps. # Old Bro TSV logs use UNIX timestamps. date { match => [ "timestamp", "ISO8601", "UNIX" ] } mutate { rename => { "logstash_timestamp" => "timestamp" } } if [duration] == "-" { mutate { replace => [ "duration", "0" ] } } if [original_bytes] == "-" { mutate { replace => [ "original_bytes", "0" ] } } # If MissedBytes is unspecified set it to zero so it is an integer if [missed_bytes] == "-" { mutate { replace => [ "missed_bytes", "0" ] } } # If OriginalIPBytes is unspecified set it to zero so it is an integer if [original_ip_bytes] == "-" { mutate { replace => [ "original_ip_bytes", "0" ] } } # If RespondBytes is unspecified set it to zero so it is an integer if [respond_bytes] == "-" { mutate { replace => [ "respond_bytes", "0" ] } } # If RespondIPBytes is unspecified set it to zero so it is an integer if [respond_ip_bytes] == "-" { mutate { replace => [ "respond_ip_bytes", "0" ] } } if [request_body_length] == "-" { mutate { replace => [ "request_body_length", "0" ] } } if [response_body_length] == "-" { mutate { replace => [ "response_body_length", "0" ] } } if [source_port] == "-" { mutate { remove_field => ["source_port"] } } if [destination_port] == "-" { mutate { remove_field => ["destination_port"] } } if [virtual_host] == "-" { mutate { remove_field => ["virtual_host"] } } if [x_originating_ip] == "-" { mutate { remove_field => ["x_originating_ip"] } } if [basic_constraints_path_length] == "-" { mutate { remove_field => ["basic_constraints_path_length"] } } if [data_channel_source_ip] == "-" { mutate { remove_field => ["data_channel_source_ip"] } } if [data_channel_destination_ip] == "-" { mutate { remove_field => ["data_channel_destination_ip"] } } if [desktop_width] == "-" { mutate { remove_field => ["desktop_width"] } } if [desktop_height] == "-" { mutate { remove_field => ["desktop_height"] } } if [height] == "-" { mutate { remove_field => ["height"] } } # I renamed conn_uids to uid so that it is easy to pivot to all things tied to a connection mutate { rename => [ "connection_uids", "uid" ] } # If total_bytes is set to "-" change it to 0 so it is an integer if [total_bytes] == "-" { mutate { replace => [ "total_bytes", "0" ] } } # If seen_bytes is set to "-" change it to 0 so it is an integer if [seen_bytes] == "-" { mutate { replace => [ "seen_bytes", "0" ] } } # If missing_bytes is set to "-" change it to 0 so it is an integer if [missing_bytes] == "-" { mutate { replace => [ "missing_bytes", "0" ] } } # If overflow_bytes is set to "-" change it to 0 so it is an integer if [overflow_bytes] == "-" { mutate { replace => [ "overflow_bytes", "0" ] } } if [dcc_file_size] == "-" { mutate { replace => [ "dcc_file_size", "0" ] } } if [authentication_attempts] == "-" { mutate { replace => [ "authentication_attempts", "0" ] } } if [file_size] == "-" { mutate { replace => [ "file_size", "0" ] } } if [original_ip_bytes] == "-" { mutate { replace => [ "original_ip_bytes", "0" ] } } # I recommend changing the field types below to integer or floats so searches can do greater than or less than # and also so math functions can be ran against them mutate { convert => [ "bound_port", "integer" ] convert => [ "data_channel_destination_port", "integer" ] convert => [ "destination_port", "integer" ] convert => [ "depth", "integer" ] #convert => [ "duration", "float" ] convert => [ "info_code", "integer" ] convert => [ "missed_bytes", "integer" ] convert => [ "missing_bytes", "integer" ] convert => [ "n", "integer" ] convert => [ "original_bytes", "integer" ] convert => [ "original_packets", "integer" ] convert => [ "original_ip_bytes", "integer" ] convert => [ "overflow_bytes", "integer" ] convert => [ "p", "integer" ] convert => [ "query_class", "integer" ] convert => [ "query_type", "integer" ] convert => [ "rcode", "integer" ] convert => [ "request_body_length", "integer" ] convert => [ "request_port", "integer" ] convert => [ "respond_bytes", "integer" ] convert => [ "respond_packets", "integer" ] convert => [ "respond_ip_bytes", "integer" ] convert => [ "response_body_length", "integer" ] convert => [ "seen_bytes", "integer" ] convert => [ "source_port", "integer" ] convert => [ "status_code", "integer" ] #convert => [ "suppress_for", "float" ] convert => [ "total_bytes", "integer" ] convert => [ "trans_depth", "integer" ] convert => [ "transaction_id", "integer" ] # convert the following boolean to text for now convert => [ "local_respond", "string" ] convert => [ "tc", "string" ] convert => [ "is_orig", "string" ] convert => [ "local_orig", "string" ] lowercase => [ "query" ] #remove_field => [ "timestamp" ] } # Combine OriginalBytes and RespondBytes and save the value to total_bytes if [original_bytes] { if [respond_bytes] { ruby { code => "event.set('total_bytes', event.get('original_bytes') + event.get('respond_bytes'))" } } } mutate { #add_tag => [ "conf_file_6000"] } } }