added Malcolm
This commit is contained in:
		| @@ -0,0 +1,6 @@ | ||||
| input { | ||||
|   pipeline { | ||||
|     address => "zeek-parse" | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										5050
									
								
								Vagrant/resources/malcolm/logstash/pipelines/zeek/11_zeek_logs.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5050
									
								
								Vagrant/resources/malcolm/logstash/pipelines/zeek/11_zeek_logs.conf
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,967 @@ | ||||
| filter { | ||||
|  | ||||
|   # Protocol/service version ########################################################################################## | ||||
|   # collect protocol version under the parent zeek.service_version array | ||||
|  | ||||
|   if ([zeek_gquic][version])                    { mutate { id => "mutate_merge_normalize_zeek_gquic_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_gquic][version]" } } } | ||||
|  | ||||
|   if ([zeek_http][version])                     { mutate { id => "mutate_merge_normalize_zeek_http_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_http][version]" } } } | ||||
|  | ||||
|   if ([zeek_ipsec]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_field_zeek_service_version_ipsec" | ||||
|       code => " | ||||
|         versions = Array.new | ||||
|         versions << [event.get('[zeek_ipsec][maj_ver]'), | ||||
|                      event.get('[zeek_ipsec][min_ver]')].compact.join('.') | ||||
|         event.set('[zeek][service_version]', versions)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ldap][version])                      { mutate { id => "mutate_merge_normalize_zeek_ldap_version" | ||||
|                                                             merge => { "[zeek][service_version]" => "[zeek_ldap][version]" } } } | ||||
|  | ||||
|   if ([zeek_ntp][version])                      { mutate { id => "mutate_merge_normalize_zeek_ntp_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_ntp][version]" } } } | ||||
|  | ||||
|   if ([zeek_profinet][block_version])           { mutate { id => "mutate_merge_normalize_zeek_profinet_block_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_profinet][block_version]" } } } | ||||
|  | ||||
|   if ([zeek_profinet_dce_rpc][version])         { mutate { id => "mutate_merge_normalize_zeek_profinet_dce_rpc_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_profinet_dce_rpc][version]" } } } | ||||
|  | ||||
|   if ([zeek_rfb]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_field_zeek_service_version_rfb" | ||||
|       code => ' | ||||
|         versions = Array.new | ||||
|         clientMajorVersion = event.get("[zeek_rfb][client_major_version]").sub!(/^0*/, "") | ||||
|         clientMinorVersion = event.get("[zeek_rfb][client_minor_version]").sub!(/^0*/, "") | ||||
|         serverMajorVersion = event.get("[zeek_rfb][server_major_version]").sub!(/^0*/, "") | ||||
|         serverMinorVersion = event.get("[zeek_rfb][server_minor_version]").sub!(/^0*/, "") | ||||
|         if clientMajorVersion then | ||||
|           versions << [clientMajorVersion, clientMinorVersion].join(".") | ||||
|         end | ||||
|         if serverMajorVersion then | ||||
|           versions << [serverMajorVersion, serverMinorVersion].join(".") | ||||
|         end | ||||
|         event.set("[zeek][service_version]", versions.uniq)' | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_rdp][client_build])                 { mutate { id => "mutate_merge_normalize_zeek_rdp_client_build" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_rdp][client_build]" } } } | ||||
|  | ||||
|   if ([zeek_smtp][version])                      { mutate { id => "mutate_merge_normalize_zeek_smtp_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_smtp][version]" } } } | ||||
|  | ||||
|   if ([zeek_smb_cmd][version])                  { mutate { id => "mutate_merge_normalize_zeek_smb_cmd_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_smb_cmd][version]" } } } | ||||
|  | ||||
|   if ([zeek_snmp][version])                     { mutate { id => "mutate_merge_normalize_zeek_snmp_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_snmp][version]" } } } | ||||
|  | ||||
|   if ([zeek_socks][version])                    { mutate { id => "mutate_merge_normalize_zeek_socks_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_socks][version]" } } } | ||||
|  | ||||
|   if ([zeek_ssh][version])                      { mutate { id => "mutate_merge_normalize_zeek_ssh_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_ssh][version]" } } } | ||||
|  | ||||
|   if ([zeek_ssl][ssl_version])                  { mutate { id => "mutate_merge_normalize_zeek_ssl_ssl_version" | ||||
|                                                            merge => { "[zeek][service_version]" => "[zeek_ssl][ssl_version]" } } } | ||||
|  | ||||
|   if ([zeek][service_version]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_service_version_uniq" | ||||
|       code => "event.set('[zeek][service_version]', event.get('[zeek][service_version]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # Action ############################################################################################################ | ||||
|   # collect all actions/operations/commands under the parent [zeek][action] array | ||||
|  | ||||
|   if ([zeek_bacnet][pdu_service])               { mutate { id => "mutate_merge_normalize_zeek_bacnet_pdu_service" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bacnet][pdu_service]" } } } | ||||
|  | ||||
|   if ([zeek_bacnet_discovery][pdu_service])     { mutate { id => "mutate_merge_normalize_zeek_bacnet_discovery_pdu_service" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bacnet_discovery][pdu_service]" } } } | ||||
|  | ||||
|   if ([zeek_bacnet_property][pdu_service])      { mutate { id => "mutate_merge_normalize_zeek_bacnet_property_pdu_service" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bacnet_property][pdu_service]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_ip_rdb]) { | ||||
|     ruby { | ||||
|       # action = zeek_bsap_ip_rdb.app_func_code:zeek_bsap_ip_rdb.func_code | ||||
|       id => "ruby_zeek_bsap_ip_rdb_generate_action" | ||||
|       code => " | ||||
|         actions = Array.new unless (actions = event.get('[zeek][action]')) | ||||
|         actions.append([event.get('[zeek_bsap_ip_rdb][app_func_code]'), | ||||
|                         event.get('[zeek_bsap_ip_rdb][func_code]')].compact.join(':')) | ||||
|         event.set('[zeek][action]', actions)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_bsap_serial_header][sfun])          { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_header_sfun" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_header][sfun]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_serial_header][dfun])          { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_header_dfun" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_header][dfun]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_serial_rdb][func_code])        { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_rdb_func_code" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_rdb][func_code]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_serial_rdb_ext][sfun])         { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_rdb_ext_sfun" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_rdb_ext][sfun]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_serial_rdb_ext][dfun])         { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_rdb_ext_dfun" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_rdb_ext][dfun]" } } } | ||||
|  | ||||
|   if ([zeek_bsap_serial_rdb_ext][extfun])       { mutate { id => "mutate_merge_normalize_zeek_bsap_serial_rdb_ext_extfun" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_bsap_serial_rdb_ext][extfun]" } } } | ||||
|  | ||||
|   if ([zeek_cip][cip_service])                  { mutate { id => "mutate_merge_normalize_zeek_cip_cip_service" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_cip][cip_service]" } } } | ||||
|  | ||||
|   if ([zeek_dce_rpc][operation])                { mutate { id => "mutate_merge_normalize_zeek_dce_rpc_operation" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_dce_rpc][operation]" } } } | ||||
|  | ||||
|   if ([zeek_dhcp][msg_types])                   { mutate { id => "mutate_merge_normalize_zeek_dhcp_msg_types" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_dhcp][msg_types]" } } } | ||||
|  | ||||
|   if ([zeek_dnp3][fc_request])                  { mutate { id => "mutate_merge_normalize_zeek_dnp3_fc_request" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_dnp3][fc_request]" } } } | ||||
|  | ||||
|   if ([zeek_dnp3_control]) { | ||||
|     ruby { | ||||
|       # action = function_code:operation_type:trip_control_code | ||||
|       id => "ruby_zeek_dnp3_control_generate_action" | ||||
|       code => " | ||||
|         actions = Array.new unless (actions = event.get('[zeek][action]')) | ||||
|         actions.append([event.get('[zeek_dnp3_control][function_code]'), | ||||
|                         event.get('[zeek_dnp3_control][operation_type]'), | ||||
|                         event.get('[zeek_dnp3_control][trip_control_code]')].compact.join(':')) | ||||
|         event.set('[zeek][action]', actions)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_dnp3_read_objects][function_code])  { mutate { id => "mutate_merge_normalize_zeek_dnp3_read_objects" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_dnp3_read_objects][function_code]" } } } | ||||
|  | ||||
|   if ([zeek_dns]) { | ||||
|     # action: query class and type | ||||
|     if ([zeek_dns][qclass_name]) and ([zeek_dns][qtype_name]) { | ||||
|       mutate { id => "mutate_add_field_metadata_dns_class_and_type" | ||||
|                add_field => { "[@metadata][dns_action]" => "%{[zeek_dns][qclass_name]} %{[zeek_dns][qtype_name]}" } } | ||||
|     } else if ([zeek_dns][qclass_name]) { | ||||
|       mutate { id => "mutate_add_field_metadata_dns_class" | ||||
|                add_field => { "[@metadata][dns_action]" => "%{[zeek_dns][qclass_name]}" } } | ||||
|     } else if ([zeek_dns][qtype_name]) { | ||||
|       mutate { id => "mutate_add_field_metadata_dns_type" | ||||
|                add_field => { "[@metadata][dns_action]" => "%{[zeek_dns][qtype_name]}" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_metadata_dns_query" | ||||
|                add_field => { "[@metadata][dns_action]" => "Query" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_dns_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][dns_action]" } } | ||||
|   } | ||||
|  | ||||
|   # TODO: convert zeek_ecat_foe_info.opcode and zeek_ecat_soe_info.opcode to operations | ||||
|   # zeek EtherCAT commands/operations | ||||
|   if ([zeek_ecat_aoe_info][command])            { mutate { id => "mutate_merge_normalize_zeek_ecat_aoe_info_command" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_aoe_info][command]" } } } | ||||
|   if ([zeek_ecat_foe_info][opcode])             { mutate { id => "mutate_merge_normalize_zeek_ecat_foe_info_opcode" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_foe_info][opcode]" } } } | ||||
|   if ([zeek_ecat_log_address][command])         { mutate { id => "mutate_merge_normalize_zeek_ecat_log_address" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_log_address][command]" } } } | ||||
|   if ([zeek_ecat_registers][command])           { mutate { id => "mutate_merge_normalize_zeek_ecat_registers_command" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_registers][command]" } } } | ||||
|   if ([zeek_ecat_soe_info][opcode])             { mutate { id => "mutate_merge_normalize_zeek_ecat_soe_info_opcode" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_soe_info][opcode]" } } } | ||||
|   if ([zeek_ecat_arp_info][arp_type])           { mutate { id => "mutate_merge_normalize_zeek_ecat_arp_info_arp_type" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ecat_arp_info][arp_type]" } } } | ||||
|  | ||||
|   if ([zeek_enip][enip_command])                { mutate { id => "mutate_merge_normalize_zeek_enip_enip_command" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_enip][enip_command]" } } } | ||||
|  | ||||
|   if ([zeek_ftp][command])                      { mutate { id => "mutate_merge_normalize_zeek_ftp_command" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ftp][command]" } } } | ||||
|  | ||||
|   if ([zeek_http]) { | ||||
|     if ([zeek_http][method])  { | ||||
|       mutate { id => "mutate_merge_normalize_zeek_http_method" | ||||
|                merge => { "[zeek][action]" => "[zeek_http][method]" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_http_request_action" | ||||
|                add_field => { "[@metadata][http_request_action]" => "Request" } } | ||||
|       mutate { id => "mutate_merge_field_zeek_http_request_action" | ||||
|                merge => { "[zeek][action]" => "[@metadata][http_request_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_irc][command])                      { mutate { id => "mutate_merge_normalize_zeek_irc_command" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_irc][command]" } } } | ||||
|  | ||||
|   if ([zeek_iso_cotp][pdu_type])                { mutate { id => "mutate_merge_normalize_zeek_iso_cotp_pdu_type" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_iso_cotp][pdu_type]" } } } | ||||
|  | ||||
|   if ([zeek_kerberos][request_type])            { mutate { id => "mutate_merge_normalize_zeek_kerberos_request_type" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_kerberos][request_type]" } } } | ||||
|  | ||||
|   if ([zeek_ldap][operation])                   { mutate { id => "mutate_merge_normalize_zeek_ldap_operation" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ldap][operation]" } } } | ||||
|  | ||||
|   if ([zeek_ldap_search]) { | ||||
|     if ([zeek_ldap_search][scope]) { | ||||
|       mutate { id => "mutate_add_field_zeek_ldap_search_scope_action" | ||||
|                add_field => { "[@metadata][zeek_ldap_search_action]" => "search %{[zeek_ldap_search][scope]}" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_ldap_search_action" | ||||
|                add_field => { "[@metadata][zeek_ldap_search_action]" => "search" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_field_zeek_ldap_search_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_ldap_search_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_modbus][func])                      { mutate { id => "mutate_merge_normalize_zeek_modbus_func" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_modbus][func]" } } } | ||||
|  | ||||
|   if ([zeek_modbus_mask_write_register][func])  { mutate { id => "mutate_merge_normalize_zeek_modbus_mask_write_register_func" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_modbus_mask_write_register][func]" } } } | ||||
|  | ||||
|   if ([zeek_modbus_read_write_multiple_registers][func])  { mutate { id => "mutate_merge_normalize_zeek_modbus_read_write_multiple_registers" | ||||
|                                                             merge => { "[zeek][action]" => "[zeek_modbus_read_write_multiple_registers][func]" } } } | ||||
|  | ||||
|   if ([zeek_mqtt_connect][connect_status]) { | ||||
|     # this log entry implicitly means "connect" | ||||
|     mutate { id => "mutate_add_field_zeek_mqtt_connect_action" | ||||
|              add_field => { "[@metadata][zeek_mqtt_connect_action]" => "Connect" } } | ||||
|     mutate { id => "mutate_merge_zeek_mqtt_connect_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_mqtt_connect_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_mqtt_publish]) { | ||||
|     if ([zeek_mqtt_publish][payload_dict][messageType]) { | ||||
|       # not sure if this is a standard or just the PCAPs I found :/ | ||||
|       mutate { id => "mutate_merge_normalize_zeek_mqtt_publish_payload_dict_messageType" | ||||
|       merge => { "[zeek][action]" => "[zeek_mqtt_publish][payload_dict][messageType]" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_mqtt_publish_action" | ||||
|                add_field => { "[@metadata][zeek_mqtt_publish_action]" => "Publish" } } | ||||
|       mutate { id => "mutate_merge_zeek_mqtt_publish_action" | ||||
|                merge => { "[zeek][action]" => "[@metadata][zeek_mqtt_publish_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_mqtt_subscribe][action])            { mutate { id => "mutate_merge_normalize_zeek_mqtt_subscribe_action" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_mqtt_subscribe][action]" } } } | ||||
|  | ||||
|   if ([zeek_mysql][cmd])                        { mutate { id => "mutate_merge_normalize_zeek_mysql_cmd" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_mysql][cmd]" } } } | ||||
|  | ||||
|   if ([zeek_ntlm][success]) { | ||||
|     # this log entry implicitly means a login attempt | ||||
|     mutate { id => "mutate_add_field_zeek_ntlm_action" | ||||
|              add_field => { "[@metadata][zeek_ntlm_action]" => "Authenticate" } } | ||||
|     mutate { id => "mutate_merge_zeek_ntlm_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_ntlm_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntp][mode_str])                     { mutate { id => "mutate_merge_normalize_zeek_ntp_mode_str" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_ntp][mode_str]" } } } | ||||
|  | ||||
|   if ([zeek_profinet][operation_type])          { mutate { id => "mutate_merge_normalize_zeek_profinet_operation_type" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_profinet][operation_type]" } } } | ||||
|  | ||||
|   if ([zeek_profinet_dce_rpc][operation])       { mutate { id => "mutate_merge_normalize_zeek_profinet_dce_rpc_operation" | ||||
|                                                            merge => { "[zeek][action]" => "[zeek_profinet_dce_rpc][operation]" } } } | ||||
|  | ||||
|   if ([zeek_rfb][auth]) and ([zeek_rfb][authentication_method]) { | ||||
|     # if authentication was attempted, assign an "authenticate" action | ||||
|     mutate { id => "mutate_add_field_zeek_rfb_auth_action" | ||||
|              add_field => { "[@metadata][zeek_rfb_auth_action]" => "Authenticate" } } | ||||
|     mutate { id => "mutate_merge_zeek_rfb_auth_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_rfb_auth_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_s7comm]) { | ||||
|     ruby { | ||||
|       # action = rosctr:mode:type:sub | ||||
|       id => "ruby_zeek_s7comm_generate_action" | ||||
|       code => " | ||||
|         actions = Array.new unless (actions = event.get('[zeek][action]')) | ||||
|         actions.append([event.get('[zeek_s7comm][rosctr]'), | ||||
|                         event.get('[zeek_s7comm][parameters][mode]'), | ||||
|                         event.get('[zeek_s7comm][parameters][type]'), | ||||
|                         event.get('[zeek_s7comm][parameters][sub]')].compact.join(':')) | ||||
|         event.set('[zeek][action]', actions)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_sip][method]) { mutate { id => "mutate_merge_normalize_zeek_sip_method" | ||||
|                                      merge => { "[zeek][action]" => "[zeek_sip][method]" } } } | ||||
|  | ||||
|   if ([zeek_smtp]) { | ||||
|     # action depends on varios smtp headers' presence | ||||
|     if ([zeek_smtp][last_reply]) { | ||||
|       if ([zeek_smtp][msg_id]) { | ||||
|         mutate { id => "mutate_add_field_zeek_smtp_action_deliver" | ||||
|                  add_field => { "[@metadata][zeek_smtp_action]" => "Deliver message" } } | ||||
|       } else if ([zeek_smtp][mailfrom]) { | ||||
|         mutate { id => "mutate_add_field_zeek_smtp_action_queue" | ||||
|                  add_field => { "[@metadata][zeek_smtp_action]" => "Queue message" } } | ||||
|       } else { | ||||
|         mutate { id => "mutate_add_field_zeek_smtp_action_connect_reply" | ||||
|                  add_field => { "[@metadata][zeek_smtp_action]" => "Connect" } } | ||||
|       } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_smtp_action_connect_no_reply" | ||||
|                add_field => { "[@metadata][zeek_smtp_action]" => "Connect" } } | ||||
|     } | ||||
|     if ([@metadata][zeek_smtp_action]) { | ||||
|       mutate { id => "mutate_merge_zeek_smtp_action" | ||||
|                merge => { "[zeek][action]" => "[@metadata][zeek_smtp_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_socks]) { | ||||
|     # socks action is "Authenticate" or "Connect" based on user/password or not | ||||
|     if ([zeek_socks][user]) or ([zeek_socks][password]) { | ||||
|       mutate { id => "mutate_add_field_zeek_socks_action_authenticate" | ||||
|                add_field => { "[@metadata][zeek_socks_action]" => "Authenticate" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_socks_action_connect" | ||||
|                add_field => { "[@metadata][zeek_socks_action]" => "Connect" } } | ||||
|     } | ||||
|     if ([@metadata][zeek_socks_action]) { | ||||
|       mutate { id => "mutate_merge_zeek_socks_action" | ||||
|                merge => { "[zeek][action]" => "[@metadata][zeek_socks_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_cmd]) { | ||||
|     ruby { | ||||
|       # action = command:sub_command | ||||
|       id => "ruby_zeek_smb_cmd_generate_action" | ||||
|       code => " | ||||
|         cmd = event.get('[zeek_smb_cmd][command]') | ||||
|         subCmd = event.get('[zeek_smb_cmd][sub_command]') | ||||
|         actions = Array.new unless (actions = event.get('[zeek][action]')) | ||||
|         actions.append((cmd =~ /^\s*transaction\d*\s*$/i) ? subCmd : [cmd, subCmd].compact.join(':')) | ||||
|         event.set('[zeek][action]', actions)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][action])   { mutate { id => "mutate_merge_normalize_zeek_smb_files_action" | ||||
|                                              merge => { "[zeek][action]" => "[zeek_smb_files][action]" } } } | ||||
|  | ||||
|   if ([zeek_smtp][method])         { mutate { id => "mutate_merge_normalize_zeek_smtp_method" | ||||
|                                              merge => { "[zeek][action]" => "[zeek_smtp][method]" } } } | ||||
|  | ||||
|   if ([zeek_snmp]) { | ||||
|     # action based on > 0 values for variou get/set PDUs | ||||
|     if ([zeek_snmp][get_bulk_requests]) and ([zeek_snmp][get_bulk_requests] != "0") { | ||||
|       mutate { id => "mutate_add_field_zeek_snmp_get_bulk_requests_action" | ||||
|                add_field => { "[@metadata][snmp_get_bulk_requests_action]" => "GetBulkRequest" } } | ||||
|       mutate { id => "mutate_merge_zeek_snmp_action_get_bulk_requests" | ||||
|                merge => { "[zeek][action]" => "[@metadata][snmp_get_bulk_requests_action]" } } | ||||
|     } | ||||
|     if ([zeek_snmp][get_requests]) and ([zeek_snmp][get_requests] != "0") { | ||||
|       mutate { id => "mutate_add_field_zeek_snmp_get_requests_action" | ||||
|                add_field => { "[@metadata][snmp_get_requests_action]" => "GetRequest" } } | ||||
|       mutate { id => "mutate_merge_zeek_snmp_action_get_requests" | ||||
|                merge => { "[zeek][action]" => "[@metadata][snmp_get_requests_action]" } } | ||||
|     } | ||||
|     if ([zeek_snmp][get_responses]) and ([zeek_snmp][get_responses] != "0") { | ||||
|       mutate { id => "mutate_add_field_zeek_snmp_get_responses_action" | ||||
|                add_field => { "[@metadata][snmp_get_responses_action]" => "GetResponse" } } | ||||
|       mutate { id => "mutate_merge_zeek_snmp_action_get_responses" | ||||
|                merge => { "[zeek][action]" => "[@metadata][snmp_get_responses_action]" } } | ||||
|     } | ||||
|     if ([zeek_snmp][set_requests]) and ([zeek_snmp][set_requests] != "0") { | ||||
|       mutate { id => "mutate_add_field_zeek_snmp_set_requests_action" | ||||
|                add_field => { "[@metadata][snmp_set_requests_action]" => "SetRequest" } } | ||||
|       mutate { id => "mutate_merge_zeek_snmp_action_set_requests" | ||||
|                merge => { "[zeek][action]" => "[@metadata][snmp_set_requests_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ssh]) { | ||||
|     # ssh action is "Authenticate" or "Connect" based on auth_attempts | ||||
|     if ([zeek_ssh][auth_attempts]) { | ||||
|       mutate { id => "mutate_add_field_zeek_ssh_action_authenticate" | ||||
|                add_field => { "[@metadata][zeek_ssh_action]" => "Authenticate" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_ssh_action_connect" | ||||
|                add_field => { "[@metadata][zeek_ssh_action]" => "Connect" } } | ||||
|     } | ||||
|     if ([@metadata][zeek_ssh_action]) { | ||||
|       mutate { id => "mutate_merge_zeek_ssh_action" | ||||
|                merge => { "[zeek][action]" => "[@metadata][zeek_ssh_action]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ssl]) { | ||||
|     # SSL action will be either "connect", "validate", "resume" | ||||
|     if ([zeek_ssl][resumed] == "T") { | ||||
|       mutate { id => "mutate_add_field_zeek_ssl_resume" | ||||
|                add_field => { "[@metadata][zeek_ssl_action]" => "Resume" } } | ||||
|     } else if ([zeek_ssl][established] != "T") and ([zeek_ssl][validation_status]) and ([zeek_ssl][validation_status] != "ok") { | ||||
|       mutate { id => "mutate_add_field_zeek_ssl_validate" | ||||
|                add_field => { "[@metadata][zeek_ssl_action]" => "Validate Certificate" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_ssl_connect" | ||||
|                add_field => { "[@metadata][zeek_ssl_action]" => "Connect" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_ssl_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_ssl_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_tds][command]) { mutate { id => "mutate_merge_normalize_zeek_tds_command" | ||||
|                              merge => { "[zeek][action]" => "[zeek_tds][command]" } } } | ||||
|  | ||||
|   if ([zeek_tds_rpc][procedure_name]) { | ||||
|     mutate { id => "mutate_add_field_zeek_tds_rpc_procedure_name_tmp" | ||||
|              add_field => { "[@metadata][zeek_tds_rpc_procedure_name_tmp]" => "%{[zeek_tds_rpc][procedure_name]}" } } | ||||
|  | ||||
|     # remove everything after the first $ | ||||
|     mutate { id => "mutate_gsub_field_zeek_tds_rpc_procedure_name_tmp" | ||||
|              gsub => [ "[@metadata][zeek_tds_rpc_procedure_name_tmp]", "\$.*", "" ] } | ||||
|  | ||||
|     mutate { id => "mutate_merge_normalize_zeek_tds_rpc_procedure_name" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_tds_rpc_procedure_name_tmp]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_tftp][wrq]) { | ||||
|     if ([zeek_tftp][wrq] == "T") { | ||||
|       mutate { id => "mutate_add_field_zeek_tftp_wrq" | ||||
|                add_field => { "[@metadata][zeek_tftp_action]" => "Write" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_tftp_connect" | ||||
|                add_field => { "[@metadata][zeek_tftp_action]" => "Read" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_tftp_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_tftp_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_tunnel][action])  { mutate { id => "mutate_merge_normalize_zeek_tunnel_action" | ||||
|                                          merge => { "[zeek][action]" => "[zeek_tunnel][action]" } } } | ||||
|  | ||||
|   # Result ############################################################################################################ | ||||
|   # collect all result/status/response/errors under the parent [zeek][result] array | ||||
|  | ||||
|   if ([zeek_bacnet]) { | ||||
|     if ([zeek_bacnet][result_code]) { | ||||
|       mutate { id => "mutate_merge_normalize_zeek_bacnet_result_code" | ||||
|       merge => { "[zeek][result]" => "[zeek_bacnet][result_code]" } } | ||||
|     } else if ([zeek_bacnet][pdu_service]) { | ||||
|       mutate { id => "mutate_add_field_zeek_bacnet_success" | ||||
|                add_field => { "[@metadata][zeek_bacnet_result]" => "Success" } } | ||||
|       mutate { id => "mutate_merge_field_zeek_bacnet_success" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_bacnet_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_cip][cip_status]) { mutate { id => "mutate_merge_normalize_zeek_cip_status_result" | ||||
|                                          merge => { "[zeek][result]" => "[zeek_cip][cip_status]" } } } | ||||
|  | ||||
|   if ([zeek_dhcp]) { | ||||
|     # dhcp server_message and client_message populate result, as do ACK and NAK message types | ||||
|     if ([zeek_dhcp][server_message])  { mutate { id => "mutate_merge_normalize_zeek_dhcp_server_message" | ||||
|                                                  merge => { "[zeek][result]" => "[zeek_dhcp][server_message]" } } } | ||||
|     if ([zeek_dhcp][client_message])  { mutate { id => "mutate_merge_normalize_zeek_dhcp_client_message" | ||||
|                                                  merge => { "[zeek][result]" => "[zeek_dhcp][client_message]" } } } | ||||
|     if ("ACK" in [zeek_dhcp][msg_types]) { | ||||
|       mutate { id => "mutate_add_field_zeek_dhcp_ack_result" | ||||
|                add_field => { "[@metadata][zeek_dhcp_result]" => "Success" } } | ||||
|     } else if ("NAK" in [zeek_dhcp][msg_types]) { | ||||
|       mutate { id => "mutate_add_field_zeek_dhcp_nak_result" | ||||
|                add_field => { "[@metadata][zeek_dhcp_result]" => "Failure" } } | ||||
|     } | ||||
|     if ([@metadata][zeek_dhcp_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_dhcp_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_dhcp_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # dnp3: fc_reply and iin_flags | ||||
|   if ([zeek_dnp3][fc_reply])  { mutate { id => "mutate_merge_zeek_dnp3_fc_reply" | ||||
|                                          merge => { "[zeek][result]" => "[zeek_dnp3][fc_reply]" } } } | ||||
|   if ([zeek_dnp3][iin_flags]) { mutate { id => "mutate_merge_zeek_dnp3_iin_flags" | ||||
|                                          merge => { "[zeek][result]" => "[zeek_dnp3][iin_flags]" } } } | ||||
|  | ||||
|   # dnp3_control.status_code | ||||
|   if ([zeek_dnp3_control][status_code]) { mutate { id => "mutate_merge_zeek_dnp3_control_status_code" | ||||
|                                                    merge => { "[zeek][result]" => "[zeek_dnp3_control][status_code]" } } } | ||||
|  | ||||
|   if ([zeek_dns]) { | ||||
|     # DNS result is populated by rcode_name (with NOERROR being translated to Success), and rejected | ||||
|     if ([zeek_dns][rcode_name]) { | ||||
|       if ([zeek_dns][rcode_name] == 'NOERROR') { | ||||
|         mutate { id => "mutate_add_field_zeek_dns_noerror" | ||||
|                  add_field => { "[@metadata][zeek_dns_result]" => "Success" } } | ||||
|         mutate { id => "mutate_merge_field_zeek_dns_noerror" | ||||
|                  merge => { "[zeek][result]" => "[@metadata][zeek_dns_result]" } } | ||||
|       } else { | ||||
|         mutate { id => "mutate_merge_normalize_zeek_dns_rcode_name" | ||||
|                  merge => { "[zeek][result]" => "[zeek_dns][rcode_name]" } } | ||||
|       } | ||||
|     } | ||||
|     if ([zeek_dns][rejected] == 'T') { | ||||
|       mutate { id => "mutate_add_field_zeek_dns_rejected" | ||||
|                add_field => { "[@metadata][zeek_dns_rejected_result]" => "Rejected" } } | ||||
|       mutate { id => "mutate_merge_field_zeek_dns_rejected" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_dns_rejected_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # TODO: convert zeek_ecat_foe_info.error_code and zeek_ecat_soe_info.error to strings? | ||||
|   # zeek_ecat_foe_info.error_code and zeek_ecat_soe_info.error | ||||
|   if ([zeek_ecat_foe_info][error_code])        { mutate { id => "mutate_merge_normalize_zeek_ecat_foe_info_error_code" | ||||
|                                                           merge => { "[zeek][result]" => "[zeek_ecat_foe_info][error_code]" } } } | ||||
|   if ([zeek_ecat_soe_info][error])             { mutate { id => "mutate_merge_normalize_zeek_ecat_soe_info_error" | ||||
|                                                           merge => { "[zeek][result]" => "[zeek_ecat_soe_info][error]" } } } | ||||
|  | ||||
|   # zeek_enip.enip_status | ||||
|   if ([zeek_enip][enip_status])         { mutate { id => "mutate_merge_normalize_zeek_enip_enip_status" | ||||
|                                                    merge => { "[zeek][result]" => "[zeek_enip][enip_status]" } } } | ||||
|  | ||||
|   if ([zeek_ftp][reply_code]) { | ||||
|     # normalized version of reply code (reply_msg is too unpredictable) | ||||
|     translate { | ||||
|       id => "translate_zeek_ftp_reply_code" | ||||
|       field => "[zeek_ftp][reply_code]" | ||||
|       destination => "[@metadata][zeek_ftp_mapped_result]" | ||||
|       dictionary_path => "/etc/ftp_result_codes.yaml" | ||||
|     } | ||||
|     if ([@metadata][zeek_ftp_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_ftp_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_ftp_mapped_result]" } } | ||||
|     } else if ([zeek_ftp][reply_msg]) { | ||||
|       mutate { id => "mutate_merge_zeek_ftp_reply_msg_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_ftp][reply_msg]" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_merge_zeek_ftp_reply_code_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_ftp][reply_code]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_http][status_code]) { | ||||
|     # normalized version of http reply code (status_msg is too unpredictable) | ||||
|     translate { | ||||
|       id => "translate_zeek_http_reply_code" | ||||
|       field => "[zeek_http][status_code]" | ||||
|       destination => "[@metadata][zeek_http_mapped_result]" | ||||
|       dictionary_path => "/etc/http_result_codes.yaml" | ||||
|     } | ||||
|     if ([@metadata][zeek_http_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_http_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_http_mapped_result]" } } | ||||
|     } else if ([zeek_http][status_msg]) { | ||||
|       mutate { id => "mutate_merge_zeek_http_status_msg_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_http][status_msg]" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_merge_zeek_http_status_code_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_http][status_code]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_kerberos]) { | ||||
|     # result populated from success and error_msg | ||||
|     if ([zeek_kerberos][success] == 'T') { | ||||
|       mutate { id => "mutate_add_field_zeek_zeek_kerberos_success" | ||||
|                add_field => { "[@metadata][zeek_kerberos_result]" => "Success" } } | ||||
|     } else if ([zeek_kerberos][error_msg]) { | ||||
|       mutate { id => "mutate_add_field_zeek_zeek_kerberos_error_msg" | ||||
|                add_field => { "[@metadata][zeek_kerberos_result]" => "%{[zeek_kerberos][error_msg]}" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_zeek_kerberos_failure" | ||||
|                add_field => { "[@metadata][zeek_kerberos_result]" => "Failure" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_kerberos_result" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_kerberos_result]" } } | ||||
|   } | ||||
|  | ||||
|   # (zeek_ldap|zeek_ldap_search).(result_code) | ||||
|   if ([zeek_ldap][result_code])            { mutate { id => "mutate_merge_normalize_zeek_ldap_result_code" | ||||
|                                                       merge => { "[zeek][result]" => "[zeek_ldap][result_code]" } } } | ||||
|   if ([zeek_ldap_search][result_code])     { mutate { id => "mutate_merge_normalize_zeek_ldap_search_result_code" | ||||
|                                                       merge => { "[zeek][result]" => "[zeek_ldap_search][result_code]" } } } | ||||
|  | ||||
|   if ([zeek_modbus]) { | ||||
|     # result comes from exception, but if exception is missing and we have a func, then assume success | ||||
|     if ([zeek_modbus][exception]) { | ||||
|       mutate { id => "mutate_merge_normalize_zeek_modbus_exception" | ||||
|       merge => { "[zeek][result]" => "[zeek_modbus][exception]" } } | ||||
|     } else if ([zeek_modbus][func]) { | ||||
|       mutate { id => "mutate_add_field_zeek_modbus_success" | ||||
|                add_field => { "[@metadata][zeek_modbus_result]" => "Success" } } | ||||
|       mutate { id => "mutate_merge_field_zeek_modbus_success" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_modbus_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # result for zeek_mqtt_connect: connect_status.'Connection Accepted' -> 'Success', else connect_status | ||||
|   if ([zeek_mqtt_connect][connect_status] == 'Connection Accepted') { | ||||
|     mutate { id => "mutate_add_field_zeek_mqtt_connect_success" | ||||
|              add_field => { "[@metadata][zeek_mqtt_connect_success]" => "Success" } } | ||||
|     mutate { id => "mutate_merge_field_zeek_mqtt_connect_success" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_mqtt_connect_success]" } } | ||||
|   } else if ([zeek_mqtt_connect][connect_status]) { | ||||
|     mutate { id => "mutate_merge_zeek_mqtt_connect_connect_status" | ||||
|              merge => { "[zeek][result]" => "[zeek_mqtt_connect][connect_status]" } } | ||||
|   } | ||||
|  | ||||
|   # result for zeek_mqtt_publish: status.'ok' -> 'Success', else status | ||||
|   if ([zeek_mqtt_publish][status] == 'ok') { | ||||
|     mutate { id => "mutate_add_field_zeek_mqtt_publish_success" | ||||
|              add_field => { "[@metadata][zeek_mqtt_publish_success]" => "Success" } } | ||||
|     mutate { id => "mutate_merge_field_zeek_mqtt_publish_success" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_mqtt_publish_success]" } } | ||||
|   } else if ([zeek_mqtt_publish][status]) { | ||||
|     mutate { id => "mutate_merge_zeek_mqtt_publish_publish_status" | ||||
|              merge => { "[zeek][result]" => "[zeek_mqtt_publish][status]" } } | ||||
|   } | ||||
|  | ||||
|   # zeek_mqtt_subscribe.ack.'T' -> 'Acknowledged' | ||||
|   if ([zeek_mqtt_subscribe][ack] == 'T') { | ||||
|     mutate { id => "mutate_add_field_zeek_mqtt_subscribe_ack" | ||||
|              add_field => { "[@metadata][zeek_mqtt_subscribe_acknowledged]" => "Acknowledged" } } | ||||
|     mutate { id => "mutate_merge_field_zeek_mqtt_subscribe_ack" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_mqtt_subscribe_acknowledged]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_mysql]) { | ||||
|     # mysql result comes from success and response | ||||
|     if ([zeek_mysql][success] == "T") { | ||||
|       mutate { id => "mutate_add_field_zeek_mysql_success" | ||||
|                add_field => { "[@metadata][zeek_mysql_result]" => "Success" } } | ||||
|     } else if ([zeek_mysql][response] =~ /^Access denied/) { | ||||
|       mutate { id => "mutate_add_field_zeek_mysql_access" | ||||
|                add_field => { "[@metadata][zeek_mysql_result]" => "Access denied" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_mysql_failure" | ||||
|                add_field => { "[@metadata][zeek_mysql_result]" => "Failure" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_mysql_result" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_mysql_result]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntlm]) { | ||||
|     # ntlm result comes from .success | ||||
|     if ([zeek_ntlm][success] == "T") { | ||||
|       mutate { id => "mutate_add_field_zeek_ntlm_success" | ||||
|                add_field => { "[@metadata][zeek_ntlm_result]" => "Success" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_ntlm_failure" | ||||
|                add_field => { "[@metadata][zeek_ntlm_result]" => "Failure" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_ntlm_result" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_ntlm_result]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_radius][result]) { | ||||
|     if ([zeek_radius][result] =~ /^(?i)succ/) { | ||||
|       mutate { id => "mutate_add_field_zeek_radius_success" | ||||
|                add_field => { "[@metadata][zeek_radius_result]" => "Success" } } | ||||
|     } else if ([zeek_radius][result] =~ /^(?i)fail/) { | ||||
|       mutate { id => "mutate_add_field_zeek_radius_failure" | ||||
|                add_field => { "[@metadata][zeek_radius_result]" => "Failure" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_zeek_radius_result_fallback" | ||||
|                add_field => { "[@metadata][zeek_radius_result]" => "%{[zeek_radius][result]}" } } | ||||
|     } | ||||
|     mutate { id => "mutate_merge_zeek_radius_result" | ||||
|              merge => { "[zeek][result]" => "[@metadata][zeek_radius_result]" } } | ||||
|     # if authentication was attempted, also assign an "authenticate" action | ||||
|     mutate { id => "mutate_add_field_zeek_radius_auth_action" | ||||
|              add_field => { "[@metadata][zeek_radius_auth_action]" => "Authenticate" } } | ||||
|     mutate { id => "mutate_merge_zeek_radius_auth_action" | ||||
|              merge => { "[zeek][action]" => "[@metadata][zeek_radius_auth_action]" } } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_rdp][result]) { mutate { id => "mutate_merge_normalize_zeek_rdp_result" | ||||
|                                             merge => { "[zeek][result]" => "[zeek_rdp][result]" } } } | ||||
|  | ||||
|   if ([zeek_s7comm][parameters][code]) { | ||||
|     # reference: https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-s7comm.c | ||||
|     translate { | ||||
|       id => "translate_zeek_s7comm_parameters_code" | ||||
|       field => "[zeek_s7comm][parameters][code]" | ||||
|       destination => "[@metadata][zeek_s7comm_mapped_result]" | ||||
|       dictionary_path => "/etc/s7comm_result_codes.yaml" | ||||
|       fallback => "%{[zeek_s7comm][parameters][code]}" | ||||
|     } | ||||
|     if ([@metadata][zeek_s7comm_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_s7comm_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_s7comm_mapped_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_sip][status_code]) { | ||||
|     # normalized version of sip reply code (status_msg may be unpredictable) | ||||
|     translate { | ||||
|       id => "translate_zeek_sip_reply_code" | ||||
|       field => "[zeek_sip][status_code]" | ||||
|       destination => "[@metadata][zeek_sip_mapped_result]" | ||||
|       dictionary_path => "/etc/sip_result_codes.yaml" | ||||
|     } | ||||
|     if ([@metadata][zeek_sip_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_sip_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_sip_mapped_result]" } } | ||||
|     } else if ([zeek_sip][status_msg]) { | ||||
|       mutate { id => "mutate_merge_zeek_sip_status_msg_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_sip][status_msg]" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_merge_zeek_sip_status_code_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_sip][status_code]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_cmd][status]) { | ||||
|     # zeek_smb_cmd.status (SUCCESS, NO_SUCH_FILE, ACCESS_DENIED, OBJECT_NAME_COLLISION, etc.) | ||||
|     translate { | ||||
|       id => "translate_zeek_smb_cmd_status" | ||||
|       field => "[zeek_smb_cmd][status]" | ||||
|       destination => "[@metadata][zeek_smb_cmd_mapped_result]" | ||||
|       dictionary => { | ||||
|         "SUCCESS" => "Success" | ||||
|         # TODO... normalize other codes? or maybe just case-normalize and remove underscores/dashes? | ||||
|         # e.g., "ACCESS_DENIED".split(/[_-]/).collect(&:capitalize).join(' ') | ||||
|       } | ||||
|       fallback => "%{[zeek_smb_cmd][status]}" | ||||
|     } | ||||
|     if ([@metadata][zeek_smb_cmd_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_smb_cmd_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_smb_cmd_mapped_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smtp]) { | ||||
|     if ([zeek_smtp][last_reply_code]) { | ||||
|       # normalized version of smtp reply code (last_reply may be unpredictable) | ||||
|       translate { | ||||
|         id => "translate_zeek_smtp_last_reply_code" | ||||
|         field => "[zeek_smtp][last_reply_code]" | ||||
|         destination => "[@metadata][zeek_smtp_mapped_result]" | ||||
|         dictionary_path => "/etc/smtp_result_codes.yaml" | ||||
|       } | ||||
|     } | ||||
|     if ([@metadata][zeek_smtp_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_smtp_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_smtp_mapped_result]" } } | ||||
|     } else if ([zeek_smtp][last_reply]) { | ||||
|       mutate { id => "mutate_merge_zeek_smtp_last_reply_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_smtp][last_reply]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_socks][server_status]) { | ||||
|     translate { | ||||
|       id => "translate_zeek_socks_server_status" | ||||
|       field => "[zeek_socks][server_status]" | ||||
|       destination => "[@metadata][zeek_socks_mapped_result]" | ||||
|       dictionary => { | ||||
|         "succeeded" => "Success" | ||||
|         # TODO... normalize other codes (figure out what they are) | ||||
|       } | ||||
|     } | ||||
|     if ([@metadata][zeek_socks_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_socks_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_socks_mapped_result]" } } | ||||
|     } else if ([zeek_socks][server_status]) { | ||||
|       mutate { id => "mutate_merge_zeek_socks_server_status_result" | ||||
|                merge => { "[zeek][result]" => "[zeek_socks][server_status]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ssh][auth_success]) { | ||||
|     translate { | ||||
|       id => "translate_zeek_ssh_auth_success" | ||||
|       field => "[zeek_ssh][auth_success]" | ||||
|       destination => "[@metadata][zeek_ssh_mapped_result]" | ||||
|       dictionary => { | ||||
|         "T" => "Success" | ||||
|         "F" => "Failure" | ||||
|       } | ||||
|     } | ||||
|     if ([@metadata][zeek_ssh_mapped_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_ssh_mapped_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_ssh_mapped_result]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ssl]) { | ||||
|     if ([zeek_ssl][established] == "T") { | ||||
|       mutate { id => "mutate_add_field_zeek_ssl_result_success" | ||||
|                add_field => { "[@metadata][zeek_ssl_mapped_success_result]" => "Success" } } | ||||
|     } else if (![zeek_ssl][last_alert]) { | ||||
|       mutate { id => "mutate_add_field_zeek_ssl_result_failure" | ||||
|                add_field => { "[@metadata][zeek_ssl_mapped_success_result]" => "Failure" } } | ||||
|     } | ||||
|     if ([@metadata][zeek_ssl_mapped_success_result]) { | ||||
|       mutate { id => "mutate_merge_zeek_ssl_mapped_success_result" | ||||
|                merge => { "[zeek][result]" => "[@metadata][zeek_ssl_mapped_success_result]" } } | ||||
|     } | ||||
|     if ([zeek_ssl][last_alert]) { | ||||
|       mutate { id => "mutate_merge_field_zeek_ssl_result_last_alert" | ||||
|                merge => { "[zeek][result]" => "[zeek_ssl][last_alert]" } } | ||||
|     } | ||||
|     if ([zeek_ssl][validation_status]) and ([zeek_ssl][validation_status] != 'ok') { | ||||
|       mutate { id => "mutate_merge_field_zeek_ssl_result_validation_status" | ||||
|                merge => { "[zeek][result]" => "[zeek_ssl][validation_status]" } } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_tftp]) { | ||||
|  | ||||
|     if (![zeek_tftp][error_code]) and (![zeek_tftp][error_msg]) { | ||||
|       # no error, set as "success" | ||||
|       mutate { id => "mutate_add_field_zeek_tftp_result_success" | ||||
|                add_field => { "[@metadata][zeek_tftp_result_success]" => "Success" } } | ||||
|       mutate { id => "mutate_merge_zeek_tftp_result_success" | ||||
|                 merge => { "[zeek][result]" => "[@metadata][zeek_tftp_result_success]" } } | ||||
|  | ||||
|     } else { | ||||
|       # normalized version of reply code | ||||
|       translate { | ||||
|         id => "translate_zeek_tftp_error_code" | ||||
|         field => "[zeek_tftp][error_code]" | ||||
|         destination => "[@metadata][zeek_tftp_mapped_result]" | ||||
|         dictionary_path => "/etc/tftp_result_codes.yaml" | ||||
|       } | ||||
|       if ([@metadata][zeek_tftp_mapped_result]) { | ||||
|         mutate { id => "mutate_merge_zeek_tftp_mapped_result" | ||||
|                  merge => { "[zeek][result]" => "[@metadata][zeek_tftp_mapped_result]" } } | ||||
|       } else if ([zeek_tftp][error_msg]) { | ||||
|         mutate { id => "mutate_merge_zeek_tftp_error_msg_result" | ||||
|                  merge => { "[zeek][result]" => "[zeek_tftp][error_msg]" } } | ||||
|       } else { | ||||
|         mutate { id => "mutate_merge_zeek_tftp_error_code_result" | ||||
|                  merge => { "[zeek][result]" => "[zeek_tftp][error_code]" } } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   ##################################################################################################################### | ||||
|   # remove any duplicates from action and result | ||||
|   if ([zeek][action]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_action_uniq" | ||||
|       code => "event.set('[zeek][action]', event.get('[zeek][action]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek][result]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_result_uniq" | ||||
|       code => "event.set('[zeek][result]', event.get('[zeek][result]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # FUIDs ############################################################################################################# | ||||
|   # collect all other FUIDs under parent [zeek][fuid] array (some were already done at the root level in | ||||
|   # the "rename" in 11_zeek_logs.conf) | ||||
|  | ||||
|   if ([zeek_files][parent_fuid])                { mutate { id => "mutate_merge_normalize_zeek_files_parent_fuid" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_files][parent_fuid]" } } } | ||||
|  | ||||
|   if ([zeek_http][orig_fuids])                  { mutate { id => "mutate_merge_normalize_zeek_http_orig_fuids" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_http][orig_fuids]" } } } | ||||
|  | ||||
|   if ([zeek_http][resp_fuids])                  { mutate { id => "mutate_merge_normalize_zeek_http_resp_fuids" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_http][resp_fuids]" } } } | ||||
|  | ||||
|   if ([zeek_kerberos][client_cert_fuid])        { mutate { id => "mutate_merge_normalize_zeek_kerberos_client_cert_fuid" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_kerberos][client_cert_fuid]" } } } | ||||
|  | ||||
|   if ([zeek_kerberos][server_cert_fuid])        { mutate { id => "mutate_merge_normalize_zeek_kerberos_server_cert_fuid" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_kerberos][server_cert_fuid]" } } } | ||||
|  | ||||
|   if ([zeek_ssl][cert_chain_fuids])             { mutate { id => "mutate_merge_normalize_zeek_ssl_cert_chain_fuids" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_ssl][cert_chain_fuids]" } } } | ||||
|  | ||||
|   if ([zeek_ssl][client_cert_chain_fuids])      { mutate { id => "mutate_merge_normalize_zeek_ssl_client_cert_chain_fuids" | ||||
|                                                            merge => { "[zeek][fuid]" => "[zeek_ssl][client_cert_chain_fuids]" } } } | ||||
|  | ||||
|   if ([zeek][fuid]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_fuid_uniq" | ||||
|       code => "event.set('[zeek][fuid]', event.get('[zeek][fuid]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # File/MIME types ################################################################################################### | ||||
|   # collect all file/MIME types under the parent [zeek][filetype] array | ||||
|  | ||||
|   if ([zeek_files][mime_type])                  { mutate { id => "mutate_merge_normalize_zeek_files_mime_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_files][mime_type]" } } } | ||||
|  | ||||
|   if ([zeek_ftp][mime_type])                    { mutate { id => "mutate_merge_normalize_zeek_ftp_mime_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_ftp][mime_type]" } } } | ||||
|  | ||||
|   if ([zeek_http][orig_mime_types])             { mutate { id => "mutate_merge_normalize_zeek_http_orig_mime_types" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_http][orig_mime_types]" } } } | ||||
|  | ||||
|   if ([zeek_http][resp_mime_types])             { mutate { id => "mutate_merge_normalize_zeek_http_resp_mime_types" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_http][resp_mime_types]" } } } | ||||
|  | ||||
|   if ([zeek_irc][dcc_mime_type])                { mutate { id => "mutate_merge_normalize_zeek_irc_dcc_mime_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_irc][dcc_mime_type]" } } } | ||||
|  | ||||
|   if ([zeek_intel][file_mime_type])             { mutate { id => "mutate_merge_normalize_zeek_intel_file_mime_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_intel][file_mime_type]" } } } | ||||
|  | ||||
|   if ([zeek_notice][file_mime_type])            { mutate { id => "mutate_merge_normalize_zeek_notice_file_mime_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_notice][file_mime_type]" } } } | ||||
|  | ||||
|   if ([zeek_sip][content_type])                 { mutate { id => "mutate_merge_normalize_zeek_sip_content_type" | ||||
|                                                            merge => { "[zeek][filetype]" => "[zeek_sip][content_type]" } } } | ||||
|  | ||||
|   if ([zeek][filetype]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_filetype_uniq" | ||||
|       code => "event.set('[zeek][filetype]', event.get('[zeek][filetype]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # Filenames ######################################################################################################### | ||||
|   # collect all filenames under the parent [zeek][filename] array | ||||
|  | ||||
|   if ([zeek_ecat_foe_info][filename])           { mutate { id => "mutate_merge_normalize_zeek_ecat_foe_info_filename" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_ecat_foe_info][filename]" } } } | ||||
|  | ||||
|   if ([zeek_files][filename])                   { mutate { id => "mutate_merge_normalize_zeek_files_filename" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_files][filename]" } } } | ||||
|  | ||||
|   if ([zeek_files][extracted])                  { mutate { id => "mutate_merge_normalize_zeek_files_extracted" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_files][extracted]" } } } | ||||
|  | ||||
|   if ([zeek_http][orig_filenames])              { mutate { id => "mutate_merge_normalize_zeek_http_orig_filenames" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_http][orig_filenames]" } } } | ||||
|  | ||||
|   if ([zeek_http][resp_filenames])              { mutate { id => "mutate_merge_normalize_zeek_http_resp_filenames" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_http][resp_filenames]" } } } | ||||
|  | ||||
|   if ([zeek_irc][dcc_file_name])                { mutate { id => "mutate_merge_normalize_zeek_irc_dcc_file_name" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_irc][dcc_file_name]" } } } | ||||
|  | ||||
|   if ([zeek_smb_files][name])                   { mutate { id => "mutate_merge_normalize_zeek_smb_files_name" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_smb_files][name]" } } } | ||||
|  | ||||
|   if ([zeek_smb_files][prev_name])              { mutate { id => "mutate_merge_normalize_zeek_smb_files_prev_name" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_smb_files][prev_name]" } } } | ||||
|  | ||||
|   if ([zeek_tftp][fname])                       { mutate { id => "mutate_merge_normalize_zeek_tftp_fname" | ||||
|                                                            merge => { "[zeek][filename]" => "[zeek_tftp][fname]" } } } | ||||
|  | ||||
|   if ([zeek][filename]) { | ||||
|     ruby { | ||||
|       id => "ruby_zeek_filename_uniq" | ||||
|       code => "event.set('[zeek][filename]', event.get('[zeek][filename]').uniq)" | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,299 @@ | ||||
| filter { | ||||
|  | ||||
|   # set data types for fields that belong to various zeek logs | ||||
|  | ||||
|   # todo | ||||
|   # "[zeek_ecat_dev_info][fmmucnt]" => "integer" | ||||
|   # "[zeek_ecat_dev_info][smcount]" => "integer" | ||||
|  | ||||
|   mutate { | ||||
|     id => "mutate_convert_zeek_bulk" | ||||
|     convert => { | ||||
|       "[zeek_bacnet][invoke_id]" => "integer" | ||||
|       "[zeek_bacnet_discovery][instance_number]" => "integer" | ||||
|       "[zeek_bacnet_discovery][range_low]" => "integer" | ||||
|       "[zeek_bacnet_discovery][range_high]" => "integer" | ||||
|       "[zeek_bacnet_property][instance_number]" => "integer" | ||||
|       "[zeek_bacnet_property][array_index]" => "integer" | ||||
|       "[zeek_bsap_ip_header][type_name]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][data_len]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][header_size]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][mes_seq]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][node_status]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][res_seq]" => "integer" | ||||
|       "[zeek_bsap_ip_rdb][sequence]" => "integer" | ||||
|       "[zeek_bsap_serial_header][ctl]" => "integer" | ||||
|       "[zeek_bsap_serial_header][dadd]" => "integer" | ||||
|       "[zeek_bsap_serial_header][nsb]" => "integer" | ||||
|       "[zeek_bsap_serial_header][sadd]" => "integer" | ||||
|       "[zeek_bsap_serial_header][seq]" => "integer" | ||||
|       "[zeek_bsap_serial_rdb_ext][nsb]" => "integer" | ||||
|       "[zeek_bsap_serial_rdb_ext][seq]" => "integer" | ||||
|       "[zeek_cip][cip_sequence_count]" => "integer" | ||||
|       "[zeek_cip_identity][device_type_id]" => "integer" | ||||
|       "[zeek_cip_identity][encapsulation_version]" => "integer" | ||||
|       "[zeek_cip_identity][product_code]" => "integer" | ||||
|       "[zeek_cip_identity][socket_port]" => "integer" | ||||
|       "[zeek_cip_identity][vendor_id]" => "integer" | ||||
|       "[zeek_cip_io][data_length]" => "integer" | ||||
|       "[zeek_cip_io][sequence_number]" => "integer" | ||||
|       "[zeek_conn][duration]" => "float" | ||||
|       "[zeek_dce_rpc][rtt]" => "float" | ||||
|       "[zeek_dhcp][duration]" => "float" | ||||
|       "[zeek_dnp3_control][index_number]" => "integer" | ||||
|       "[zeek_dnp3_control][execute_count]" => "integer" | ||||
|       "[zeek_dnp3_control][on_time]" => "integer" | ||||
|       "[zeek_dnp3_control][off_time]" => "integer" | ||||
|       "[zeek_dnp3_objects][object_count]" => "integer" | ||||
|       "[zeek_dnp3_objects][range_high]" => "integer" | ||||
|       "[zeek_dnp3_objects][range_low]" => "integer" | ||||
|       "[zeek_dns][rtt]" => "float" | ||||
|       "[zeek_ecat_log_address][length]" => "integer" | ||||
|       "[zeek_enip][length]" => "integer" | ||||
|       "[zeek_ipsec][maj_ver]" => "integer" | ||||
|       "[zeek_ipsec][min_ver]" => "integer" | ||||
|       "[zeek_ipsec][exchange_type]" => "integer" | ||||
|       "[zeek_ipsec][ke_dh_groups]" => "integer" | ||||
|       "[zeek_ipsec][proposals]" => "integer" | ||||
|       "[zeek_ipsec][length]" => "integer" | ||||
|       "[zeek_ldap][version]" => "integer" | ||||
|       "[zeek_ldap_search][result_count]" => "integer" | ||||
|       "[zeek_modbus_detailed][unit_id]" => "integer" | ||||
|       "[zeek_modbus_detailed][address]" => "integer" | ||||
|       "[zeek_modbus_detailed][quantity]" => "integer" | ||||
|       "[zeek_modbus_mask_write_register][unit_id]" => "integer" | ||||
|       "[zeek_modbus_mask_write_register][address]" => "integer" | ||||
|       "[zeek_modbus_mask_write_register][and_mask]" => "integer" | ||||
|       "[zeek_modbus_mask_write_register][or_mask]" => "integer" | ||||
|       "[zeek_modbus_read_write_multiple_registers][unit_id]" => "integer" | ||||
|       "[zeek_modbus_read_write_multiple_registers][write_start_address]" => "integer" | ||||
|       "[zeek_modbus_read_write_multiple_registers][read_start_address]" => "integer" | ||||
|       "[zeek_modbus_read_write_multiple_registers][read_quantity]" => "integer" | ||||
|       "[zeek_modbus_register][delta]" => "float" | ||||
|       "[zeek_modbus_register][new_val]" => "integer" | ||||
|       "[zeek_modbus_register][old_val]" => "integer" | ||||
|       "[zeek_modbus_register][register]" => "integer" | ||||
|       "[zeek_mqtt_publish][payload_len]" => "integer" | ||||
|       "[zeek_mqtt_subscribe][granted_qos_level]" => "integer" | ||||
|       "[zeek_mqtt_subscribe][qos_levels]" => "integer" | ||||
|       "[zeek_ntp][num_exts]" => "integer" | ||||
|       "[zeek_ntp][poll]" => "float" | ||||
|       "[zeek_ntp][precision]" => "float" | ||||
|       "[zeek_ntp][root_delay]" => "float" | ||||
|       "[zeek_ntp][root_disp]" => "float" | ||||
|       "[zeek_ntp][version]" => "integer" | ||||
|       "[zeek_s7comm][item_count]" => "integer" | ||||
|       "[zeek_signatures][host_count]" => "integer" | ||||
|       "[zeek_signatures][signature_count]" => "integer" | ||||
|       "[zeek_smb_cmd][rtt]" => "float" | ||||
|       "[zeek_smb_files][data_len_req]" => "integer" | ||||
|       "[zeek_smb_files][data_len_rsp]" => "integer" | ||||
|       "[zeek_smb_files][data_offset_req]" => "integer" | ||||
|       "[zeek_tftp][size]" => "integer" | ||||
|       "[zeek_tftp][block_sent]" => "integer" | ||||
|       "[zeek_tftp][block_acked]" => "integer" | ||||
|       "[zeek_tftp][error_code]" => "integer" | ||||
|       "[zeek_wireguard][sender_index]" => "integer" | ||||
|       "[zeek_wireguard][receiver_index]" => "integer" | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   # convert all zeek "time" types (minus zeek.ts, which was done earlier) | ||||
|   # https://docs.zeek.org/en/current/script-reference/types.html#type-time | ||||
|  | ||||
|   if ([zeek_kerberos][from]) { | ||||
|     if ([zeek_kerberos][from] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_kerberos_from_zero" | ||||
|                remove_field => [ "[zeek_kerberos][from]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_kerberos_from" | ||||
|         match => [ "[zeek_kerberos][from]", "UNIX" ] | ||||
|         target => "[zeek_kerberos][from]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_kerberos][till]) { | ||||
|     if ([zeek_kerberos][till] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_kerberos_till_zero" | ||||
|                remove_field => [ "[zeek_kerberos][till]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_kerberos_till" | ||||
|         match => [ "[zeek_kerberos][till]", "UNIX" ] | ||||
|         target => "[zeek_kerberos][till]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntp][org_time]) { | ||||
|     if ([zeek_ntp][org_time] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_ntp_org_time_zero" | ||||
|                remove_field => [ "[zeek_ntp][org_time]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_ntp_org_time" | ||||
|         match => [ "[zeek_ntp][org_time]", "UNIX" ] | ||||
|         target => "[zeek_ntp][org_time]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntp][rec_time]) { | ||||
|     if ([zeek_ntp][rec_time] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_ntp_rec_time_zero" | ||||
|                remove_field => [ "[zeek_ntp][rec_time]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_ntp_rec_time" | ||||
|         match => [ "[zeek_ntp][rec_time]", "UNIX" ] | ||||
|         target => "[zeek_ntp][rec_time]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntp][ref_time]) { | ||||
|     if ([zeek_ntp][ref_time] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_ntp_ref_time_zero" | ||||
|                remove_field => [ "[zeek_ntp][ref_time]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_ntp_ref_time" | ||||
|         match => [ "[zeek_ntp][ref_time]", "UNIX" ] | ||||
|         target => "[zeek_ntp][ref_time]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_ntp][xmt_time]) { | ||||
|     if ([zeek_ntp][xmt_time] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_ntp_xmt_time_zero" | ||||
|                remove_field => [ "[zeek_ntp][xmt_time]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_ntp_xmt_time" | ||||
|         match => [ "[zeek_ntp][xmt_time]", "UNIX" ] | ||||
|         target => "[zeek_ntp][xmt_time]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_pe][compile_ts]) { | ||||
|     if ([zeek_pe][compile_ts] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_pe_compile_ts_zero" | ||||
|                remove_field => [ "[zeek_pe][compile_ts]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_pe_compile_ts" | ||||
|         match => [ "[zeek_pe][compile_ts]", "UNIX" ] | ||||
|         target => "[zeek_pe][compile_ts]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][times_accessed]) { | ||||
|     if ([zeek_smb_files][times_accessed] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_smb_files_times_accessed_zero" | ||||
|                remove_field => [ "[zeek_smb_files][times_accessed]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_smb_files_times_accessed" | ||||
|         match => [ "[zeek_smb_files][times_accessed]", "UNIX" ] | ||||
|         target => "[zeek_smb_files][times_accessed]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][times_changed]) { | ||||
|     if ([zeek_smb_files][times_changed] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_smb_files_times_changed_zero" | ||||
|                remove_field => [ "[zeek_smb_files][times_changed]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_smb_files_times_changed" | ||||
|         match => [ "[zeek_smb_files][times_changed]", "UNIX" ] | ||||
|         target => "[zeek_smb_files][times_changed]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][times_created]) { | ||||
|     if ([zeek_smb_files][times_created] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_smb_files_times_created_zero" | ||||
|                remove_field => [ "[zeek_smb_files][times_created]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_smb_files_times_created" | ||||
|         match => [ "[zeek_smb_files][times_created]", "UNIX" ] | ||||
|         target => "[zeek_smb_files][times_created]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][times_modified]) { | ||||
|     if ([zeek_smb_files][times_modified] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_smb_files_times_modified_zero" | ||||
|                remove_field => [ "[zeek_smb_files][times_modified]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_smb_files_times_modified" | ||||
|         match => [ "[zeek_smb_files][times_modified]", "UNIX" ] | ||||
|         target => "[zeek_smb_files][times_modified]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_smb_files][ts]) { | ||||
|     if ([zeek_smb_files][ts] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_smb_files_ts_zero" | ||||
|                remove_field => [ "[zeek_smb_files][ts]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_smb_files_ts" | ||||
|         match => [ "[zeek_smb_files][ts]", "UNIX" ] | ||||
|         target => "[zeek_smb_files][ts]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_snmp][up_since]) { | ||||
|     if ([zeek_snmp][up_since] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_snmp_up_since_zero" | ||||
|                remove_field => [ "[zeek_snmp][up_since]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_snmp_up_since" | ||||
|         match => [ "[zeek_snmp][up_since]", "UNIX" ] | ||||
|         target => "[zeek_snmp][up_since]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_x509][certificate_not_valid_after]) { | ||||
|     if ([zeek_x509][certificate_not_valid_after] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_x509_certificate_not_valid_after_zero" | ||||
|                remove_field => [ "[zeek_x509][certificate_not_valid_after]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_x509_certificate_not_valid_after" | ||||
|         match => [ "[zeek_x509][certificate_not_valid_after]", "UNIX" ] | ||||
|         target => "[zeek_x509][certificate_not_valid_after]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if ([zeek_x509][certificate_not_valid_before]) { | ||||
|     if ([zeek_x509][certificate_not_valid_before] == "0.000000") { | ||||
|       mutate { id => "mutate_remove_field_zeek_x509_certificate_not_valid_before_zero" | ||||
|                remove_field => [ "[zeek_x509][certificate_not_valid_before]" ] } | ||||
|     } else { | ||||
|       date { | ||||
|         id => "date_zeek_x509_certificate_not_valid_before" | ||||
|         match => [ "[zeek_x509][certificate_not_valid_before]", "UNIX" ] | ||||
|         target => "[zeek_x509][certificate_not_valid_before]" | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,773 @@ | ||||
| filter { | ||||
|  | ||||
|   # Map zeek fields to ECS where possible (see https://github.com/idaholab/Malcolm/issues/16) | ||||
|   # For now I will add fields rather than rename them. This will preserve backwards compatibility | ||||
|   # but the records will be somewhat bigger. I'll have to address what (if anything) to do with upgrades. | ||||
|  | ||||
|   # | ||||
|   # Some fields (particularly AS and GEO fields) don't exist at this point in the pipeline, as they | ||||
|   # are added during enrichment. In that case, I will make a note of it here and handle it in | ||||
|   # ./pipelines/enrichment/20_enriched_to_ecs.conf: | ||||
|   # | ||||
|   # Autonomous System and Geo are handled after enrichment in 20_enriched_to_ecs.conf | ||||
|   #  🗹 Autonomous System - Fields describing an Autonomous System (Internet routing prefix). - https://www.elastic.co/guide/en/ecs/current/ecs-as.html | ||||
|   #  🗹 Geo - Fields describing a location. - https://www.elastic.co/guide/en/ecs/current/ecs-geo.html | ||||
|   # | ||||
|   # Risk/severity/priority/whatever will be done *after* enrichment based on normalized fields | ||||
|   # - event.severity, event.risk_score and event.risk_score_norm | ||||
|   # | ||||
|   # TODO: certain other fields that I'm already normalizing for moloch could maybe be moved out of | ||||
|   # here into enriched_to_ecs in the enrichment pipeline, but that kind of depends on what things | ||||
|   # look like when we add more data sources in the future, or if moloch tackles ECS, etc. | ||||
|   # | ||||
|  | ||||
|   # for now don't do anything unles an env explicitly enables it | ||||
|   mutate { | ||||
|     id => "mutate_add_field_env_logstash_zeek_to_ecs" | ||||
|     add_field => { "[@metadata][ENV_LOGSTASH_ZEEK_TO_ECS]" => "${LOGSTASH_TO_ECS:false}" } | ||||
|   } | ||||
|   if ([@metadata][ENV_LOGSTASH_ZEEK_TO_ECS] == "true") { | ||||
|  | ||||
|     # I will mark these ☐ off with a 🗹 or 🗷 as I address them or decide they don't need adressing | ||||
|  | ||||
|     # 🗹 Network - Fields describing the communication path over which the event happened. - https://www.elastic.co/guide/en/ecs/current/ecs-network.html | ||||
|  | ||||
|     # network.direction handled during enrichment pipeline | ||||
|     # network.name      handled during enrichment pipeline | ||||
|     # network.type      handled during enrichment pipeline | ||||
|     # TODO: some of these done here should probably be done after enrichment, too | ||||
|  | ||||
|     # network.application and network.protocol (TODO: what's the difference as far as my logs go) | ||||
|     if ([zeek][service]) { | ||||
|       mutate { id => "mutate_add_field_ecs_network_application" | ||||
|                add_field => { "[network][application]" => "%{[zeek][service]}" } } | ||||
|       mutate { id => "mutate_add_field_ecs_network_protocol" | ||||
|                add_field => { "[network][protocol]" => "%{[zeek][service]}" } } | ||||
|     } | ||||
|  | ||||
|     # network.packets | ||||
|           if ([totPackets]) {                     mutate { id => "mutate_add_field_ecs_network_packets" | ||||
|                                                            add_field => { "[network][packets]" => "%{[totPackets]}" } } } | ||||
|  | ||||
|     # network.bytes | ||||
|           if ([totBytes]) {                       mutate { id => "mutate_add_field_ecs_network_bytes" | ||||
|                                                            add_field => { "[network][bytes]" => "%{[totBytes]}" } } } | ||||
|  | ||||
|     # network.community_id | ||||
|           if ([zeek][community_id]) {             mutate { id => "mutate_add_field_ecs_network_community_id" | ||||
|                                                            add_field => { "[network][community_id]" => "%{[zeek][community_id]}" } } } | ||||
|  | ||||
|     # network.iana_number | ||||
|           if ([ipProtocol]) {                     mutate { id => "mutate_add_field_ecs_network_iana_number" | ||||
|                                                            add_field => { "[network][iana_number]" => "%{[ipProtocol]}" } } } | ||||
|  | ||||
|     # network.transport | ||||
|           if ([zeek][proto]) {                    mutate { id => "mutate_add_field_ecs_network_transport" | ||||
|                                                            add_field => { "[network][transport]" => "%{[zeek][proto]}" } } } | ||||
|  | ||||
|     # 🗹 Client - Fields about the client side of a network connection, used with server. - https://www.elastic.co/guide/en/ecs/current/ecs-client.html | ||||
|  | ||||
|     # client.ip / client.address | ||||
|     if ([zeek][orig_h]) { | ||||
|       mutate { id => "mutate_add_field_ecs_client_address" | ||||
|                add_field => { "[client][address]" => "%{[zeek][orig_h]}" } } | ||||
|       mutate { id => "mutate_add_field_ecs_client_ip" | ||||
|                add_field => { "[client][ip]" => "%{[zeek][orig_h]}" } } | ||||
|     } | ||||
|  | ||||
|     # client.port | ||||
|           if ([zeek][orig_p]) {                   mutate { id => "mutate_add_field_ecs_client_port_orig_p" | ||||
|                                                            add_field => { "[client][port]" => "%{[zeek][orig_p]}" } } } | ||||
|  | ||||
|     # client.domain | ||||
|           if ([zeek][orig_hostname]) {            mutate { id => "mutate_add_field_ecs_client_domain_orig_hostname" | ||||
|                                                            add_field => { "[client][domain]" => "%{[zeek][orig_hostname]}" } } } | ||||
|     else if ([zeek_dhcp][host_name]) {            mutate { id => "mutate_add_field_ecs_client_domain_dhcp_host_name" | ||||
|                                                            add_field => { "[client][domain]" => "%{[zeek_dhcp][host_name]}" } } } | ||||
|     else if ([zeek_dhcp][domain]) {               mutate { id => "mutate_add_field_ecs_client_domain_dhcp_domain" | ||||
|                                                            add_field => { "[client][domain]" => "%{[zeek_dhcp][domain]}" } } } | ||||
|     else if ([zeek_ntlm][host]) {                 mutate { id => "mutate_add_field_ecs_client_domain_ntlm_host_name" | ||||
|                                                            add_field => { "[client][domain]" => "%{[zeek_ntlm][host]}" } } } | ||||
|     else if ([zeek_ntlm][domain]) {               mutate { id => "mutate_add_field_ecs_client_domain_ntlm_domain" | ||||
|                                                            add_field => { "[client][domain]" => "%{[zeek_ntlm][domain]}" } } } | ||||
|  | ||||
|     # client.mac | ||||
|           if ([zeek][orig_l2_addr]) {             mutate { id => "mutate_add_field_ecs_client_mac_orig_l2_addr" | ||||
|                                                            add_field => { "[client][mac]" => "%{[zeek][orig_l2_addr]}" } } } | ||||
|     else if ([zeek_dhcp][mac]) {                  mutate { id => "mutate_add_field_ecs_client_mac_dhcp_mac" | ||||
|                                                            add_field => { "[client][mac]" => "%{[zeek_dhcp][mac]}" } } } | ||||
|     else if ([zeek_radius][mac]) {                mutate { id => "mutate_add_field_ecs_client_mac_radius_mac" | ||||
|                                                            add_field => { "[client][mac]" => "%{[zeek_radius][mac]}" } } } | ||||
|  | ||||
|     # client.bytes | ||||
|           if ([zeek_conn][orig_ip_bytes]) {       mutate { id => "mutate_add_field_ecs_client_bytes_conn_orig_ip_bytes" | ||||
|                                                            add_field => { "[client][bytes]" => "%{[zeek_conn][orig_ip_bytes]}" } } } | ||||
|     else if ([zeek_conn][orig_bytes]) {           mutate { id => "mutate_add_field_ecs_client_bytes_conn_orig_bytes" | ||||
|                                                            add_field => { "[client][bytes]" => "%{[zeek_conn][orig_bytes]}" } } } | ||||
|     else if ([zeek_http][request_body_len]) {     mutate { id => "mutate_add_field_ecs_client_bytes_http_request_body_len" | ||||
|                                                            add_field => { "[client][bytes]" => "%{[zeek_http][request_body_len]}" } } } | ||||
|     else if ([zeek_mqtt_publish][payload_len]) {  mutate { id => "mutate_add_field_ecs_client_bytes_mqtt_publish_payload_len" | ||||
|                                                            add_field => { "[client][bytes]" => "%{[zeek_mqtt_publish][payload_len]}" } } } | ||||
|     else if ([zeek_sip][request_body_len]) {      mutate { id => "mutate_add_field_ecs_client_bytes_sip_request_body_len" | ||||
|                                                            add_field => { "[client][bytes]" => "%{[zeek_sip][request_body_len]}" } } } | ||||
|  | ||||
|     # client.packets | ||||
|          if ([zeek_conn][orig_pkts]) {            mutate { id => "mutate_add_field_ecs_client_packets_conn_orig_pkts" | ||||
|                                                            add_field => { "[client][packets]" => "%{[zeek_conn][orig_pkts]}" } } } | ||||
|  | ||||
|     # 🗹 Server - Fields about the server side of a network connection, used with client. - https://www.elastic.co/guide/en/ecs/current/ecs-server.html | ||||
|  | ||||
|     # server.ip / server.address | ||||
|     if ([zeek][resp_h]) { | ||||
|       mutate { id => "mutate_add_field_ecs_server_address" | ||||
|                add_field => { "[server][address]" => "%{[zeek][resp_h]}" } } | ||||
|       mutate { id => "mutate_add_field_ecs_server_ip" | ||||
|                add_field => { "[server][ip]" => "%{[zeek][resp_h]}" } } | ||||
|     } | ||||
|  | ||||
|     # server.port | ||||
|           if ([zeek][resp_p]) {                   mutate { id => "mutate_add_field_ecs_server_port_resp_p" | ||||
|                                                            add_field => { "[server][port]" => "%{[zeek][resp_p]}" } } } | ||||
|  | ||||
|     # server.domain | ||||
|           if ([zeek][resp_hostname]) {            mutate { id => "mutate_add_field_ecs_server_domain_resp_hostname" | ||||
|                                                            add_field => { "[server][domain]" => "%{[zeek][resp_hostname]}" } } } | ||||
|  | ||||
|     # server.mac | ||||
|           if ([zeek][resp_l2_addr]) {             mutate { id => "mutate_add_field_ecs_server_mac_resp_l2_addr" | ||||
|                                                            add_field => { "[server][mac]" => "%{[zeek][resp_l2_addr]}" } } } | ||||
|  | ||||
|     # server.bytes | ||||
|           if ([zeek_conn][resp_ip_bytes]) {       mutate { id => "mutate_add_field_ecs_server_bytes_conn_resp_ip_bytes" | ||||
|                                                            add_field => { "[server][bytes]" => "%{[zeek_conn][resp_ip_bytes]}" } } } | ||||
|     else if ([zeek_conn][resp_bytes]) {           mutate { id => "mutate_add_field_ecs_server_bytes_conn_resp_bytes" | ||||
|                                                            add_field => { "[server][bytes]" => "%{[zeek_conn][resp_bytes]}" } } } | ||||
|     else if ([zeek_http][response_body_len]) {    mutate { id => "mutate_add_field_ecs_server_bytes_http_response_body_len" | ||||
|                                                            add_field => { "[server][bytes]" => "%{[zeek_http][response_body_len]}" } } } | ||||
|     else if ([zeek_sip][response_body_len]) {     mutate { id => "mutate_add_field_ecs_server_bytes_sip_response_body_len" | ||||
|                                                            add_field => { "[server][bytes]" => "%{[zeek_sip][response_body_len]}" } } } | ||||
|  | ||||
|     # server.packets | ||||
|          if ([zeek_conn][resp_pkts]) {            mutate { id => "mutate_add_field_ecs_server_packets_conn_resp_pkts" | ||||
|                                                            add_field => { "[server][packets]" => "%{[zeek_conn][resp_pkts]}" } } } | ||||
|  | ||||
|     # ☐ Event - Fields breaking down the event details. - https://www.elastic.co/guide/en/ecs/current/ecs-event.html | ||||
|  | ||||
|     # event.action from zeek.action | ||||
|          if ([zeek][action]) {                    mutate { id => "mutate_add_field_ecs_event_action" | ||||
|                                                            add_field => { "[event][action]" => "%{[zeek][action]}" } } } | ||||
|  | ||||
|     # event.dataset from zeek.logtype | ||||
|     mutate { id => "mutate_add_field_ecs_event_dataset" | ||||
|              add_field => { "[event][dataset]" => "zeek.%{[zeek][logType]}" } } | ||||
|  | ||||
|     # event.duration | ||||
|     if ([zeek_conn][duration]) { | ||||
|       # convert duration (floating-point seconds) to nanoseconds | ||||
|       ruby { | ||||
|         id => "ruby_zeek_duration_to_ecs_event_duration" | ||||
|         code => "event.set('[event][duration]', (1000000000 * event.get('[zeek_conn][duration]').to_f).round(0))" | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     # for event.start/event.end, we'll the moloch firstPacket/lastPacket field as we already did the math | ||||
|     if ([firstPacket]) {                          mutate { id => "mutate_add_field_ecs_event_start" | ||||
|                                                            add_field => { "[event][start]" => "%{[firstPacket]}" } } } | ||||
|     if ([lastPacket]) {                           mutate { id => "mutate_add_field_ecs_event_end" | ||||
|                                                            add_field => { "[event][end]" => "%{[lastPacket]}" } } } | ||||
|  | ||||
|     # UIDs and FUIDs constitude unique IDs | ||||
|     if ([zeek][uid]) {                            mutate { id => "mutate_add_field_ecs_id_uid" | ||||
|                                                            merge => { "[event][id]" => "[zeek][uid]" } } } | ||||
|     if ([zeek][fuid]) {                           mutate { id => "mutate_add_field_ecs_id_fuid" | ||||
|                                                            merge => { "[event][id]" => "[zeek][fuid]" } } } | ||||
|  | ||||
|     # event.provider | ||||
|     if (![event][provider]) {                     mutate { id => "mutate_add_field_event_provider_zeek" | ||||
|                                                            add_field => { "[event][provider]" => "zeek" } } } | ||||
|  | ||||
|     # event.kind - https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-kind.html | ||||
|     if ([zeek_notice]) or ([zeek_signatures]) or ([zeek_weird]) { | ||||
|       mutate { id => "mutate_add_field_ecs_event_kind_alert" | ||||
|                add_field => { "[event][kind]" => "alert" } } | ||||
|     } else { | ||||
|       mutate { id => "mutate_add_field_ecs_event_kind_event" | ||||
|                add_field => { "[event][kind]" => "event" } } | ||||
|     } | ||||
|  | ||||
|     # event.category - https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-category.html | ||||
|     translate { | ||||
|       id => "translate_zeek_ecs_event_category" | ||||
|       field => "[zeek][logType]" | ||||
|       destination => "[event][category]" | ||||
|       dictionary_path => "/etc/zeek_log_ecs_categories.yaml" | ||||
|     } | ||||
|  | ||||
|     # TODO: this gets very granular and varies wildly per protocol, not sure I can translate these 100% from zeek.action and zeek.result | ||||
|     # event.type - https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-type.html | ||||
|     # event.outcome - https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-outcome.html | ||||
|     # Eeesh, this is a swag... | ||||
|     # if ([zeek][result]) { | ||||
|     #   ruby { | ||||
|     #     id => "ruby_ecs_event_outcome_zeek_result" | ||||
|     #     code => " | ||||
|     #       event.get('[zeek][result]').each { |zeekResult| | ||||
|     #         zeekResult.downcase! | ||||
|     #         if zeekResult =~ /(abo?rt|bad|busy|close|conflict|crit|declin|denied|deny|disabl|discon|down|err|exceed|exhaust|expir|fail|forbid|illeg|imposs|inappr|incorr|insuff|interrupt|misdirected|nak|no[ _-]*such|overload|problem|refus|reject|terminat|timeout|violat|wrong|(im|dis|mis|un|un|not)[ _-]*(avail|allow|assign|auth|deciph|process|permit|found|support|exist|enough|implem|known|ok|okay|reach|respond|consist|access|satis|succes|valid|want)|too[ _-]*(large|long|small|short|early|late|many|few))/ | ||||
|     #           event.set('[event][outcome]', 'failure') | ||||
|     #           break | ||||
|     #         elsif zeekResult =~ /(ok|okay|success|ack|complet|correct|good|ready|finish|valid)/ | ||||
|     #           event.set('[event][outcome]', 'success') | ||||
|     #           break | ||||
|     #         end | ||||
|     #       } | ||||
|     #     " | ||||
|     #   } | ||||
|     # } | ||||
|  | ||||
|     # ☐ DNS - Fields describing DNS queries and answers. - https://www.elastic.co/guide/en/ecs/current/ecs-dns.html | ||||
|     if ([zeek_dns]) { | ||||
|  | ||||
|       # dns.resolved_ip | ||||
|       if ([dns][ip]) {                            mutate { id => "mutate_merge_ecs_dhs_resolved_ip" | ||||
|                                                            merge => { "[dns][resolved_ip]" => "[dns][ip]" } } } | ||||
|  | ||||
|       # dns.answers and dns.type:answer | ||||
|       if ([zeek_dns][answers]) { | ||||
|         ruby { | ||||
|           id => "ruby_zeek_dns_answers_to_ecs" | ||||
|           code => ' | ||||
|             event.set("[dns][answers]", [Array(event.get("[zeek_dns][answers]")), Array(event.get("[zeek_dns][TTLs]"))].transpose.map{ |d| Hash[[:data, :ttl].zip(d)] }) | ||||
|         '} | ||||
|         mutate { id => "mutate_add_field_ecs_dns_type_answer" | ||||
|                  add_field => { "[dns][type]" => "answer" } } | ||||
|       } | ||||
|  | ||||
|       # dns.op_code | ||||
|       if ([dns][opcode]) {                          mutate { id => "mutate_add_field_ecs_dns_opcode" | ||||
|                                                              add_field => { "[dns][op_code]" => "%{[dns][opcode]}" } } } | ||||
|  | ||||
|       # dns.question.class | ||||
|       if ([zeek_dns][qclass_name]) {                mutate { id => "mutate_add_field_ecs_dns_qclass" | ||||
|                                                              add_field => { "[dns][question][class]" => "%{[zeek_dns][qclass_name]}" } } } | ||||
|  | ||||
|       # dns.question.type | ||||
|       if ([zeek_dns][qtype_name]) {                 mutate { id => "mutate_add_field_ecs_dns_qtype" | ||||
|                                                              add_field => { "[dns][question][type]" => "%{[zeek_dns][qtype_name]}" } } } | ||||
|  | ||||
|       # dns.question.name and dns.type:query | ||||
|       if ([zeek_dns][query]) { | ||||
|                             mutate { id => "mutate_add_field_ecs_dns_query" | ||||
|                                      add_field => { "[dns][question][name]" => "%{[zeek_dns][query]}" } } | ||||
|         if (![dns][type]) { mutate { id => "mutate_add_field_ecs_dns_type_query" | ||||
|                                      add_field => { "[dns][type]" => "query" } } } | ||||
|       } | ||||
|  | ||||
|       if ([dns][type]) { | ||||
|         # dns.header_flags | ||||
|         if ([zeek][AA] == "T") {                    mutate { id => "mutate_add_field_ecs_dns_header_flag_aa" | ||||
|                                                              add_field => { "[dns][header_flags]" => "AA" } } } | ||||
|         if ([zeek][TC] == "T") {                    mutate { id => "mutate_add_field_ecs_dns_header_flag_tc" | ||||
|                                                              add_field => { "[dns][header_flags]" => "TC" } } } | ||||
|         if ([zeek][RD] == "T") {                    mutate { id => "mutate_add_field_ecs_dns_header_flag_rd" | ||||
|                                                              add_field => { "[dns][header_flags]" => "RD" } } } | ||||
|         if ([zeek][RA] == "T") {                    mutate { id => "mutate_add_field_ecs_dns_header_flag_ra" | ||||
|                                                              add_field => { "[dns][header_flags]" => "RA" } } } | ||||
|       } | ||||
|  | ||||
|       # dns.response_code | ||||
|       if ([zeek_dns][rcode_name]) {                 mutate { id => "mutate_add_field_ecs_dns_response_code" | ||||
|                                                              add_field => { "[dns][response_code]" => "%{[zeek_dns][rcode_name]}" } } } | ||||
|  | ||||
|       # dns.id | ||||
|       if ([zeek_dns][trans_id]) {                   mutate { id => "mutate_add_field_ecs_dns_id" | ||||
|                                                              add_field => { "[dns][id]" => "%{[zeek_dns][trans_id]}" } } } | ||||
|  | ||||
|       # TODO: domain stuff (dns.question.registered_domain, dns.question.subdomain, dns.question.top_level_domain) | ||||
|       # perhaps use something like https://github.com/plutonbacon/logstash-filter-publicsuffix | ||||
|     } | ||||
|  | ||||
|     # 🗹 File - Fields describing files. - https://www.elastic.co/guide/en/ecs/current/ecs-file.html | ||||
|  | ||||
|     if ([zeek_files]) { | ||||
|  | ||||
|       # file.type | ||||
|       mutate { id => "mutate_add_field_ecs_file_type" | ||||
|                add_field => { "[file][type]" => "file" } } | ||||
|  | ||||
|       # file.directory, file.name, file.path | ||||
|       if ([zeek_files][filename]) { | ||||
|         mutate { id => "mutate_add_field_ecs_file_path" | ||||
|                  add_field => { "[file][path]" => "%{[zeek_files][filename]}" } } | ||||
|         grok { | ||||
|           id => "grok_zeek_files_filename_ecs" | ||||
|           match => { "[zeek_files][filename]" => [ "%{GREEDYDATA:[file][directory]}[\\\/]%{DATA:[file][name]}" ] } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       # file.mime_type | ||||
|       if ([zeek_files][mime_type]) {                mutate { id => "mutate_add_field_ecs_files_mime_type" | ||||
|                                                              add_field => { "[file][mime_type]" => "%{[zeek_files][mime_type]}" } } } | ||||
|  | ||||
|       # file.size | ||||
|       if ([zeek_files][total_bytes]) {              mutate { id => "mutate_add_field_ecs_files_size" | ||||
|                                                              add_field => { "[file][size]" => "%{[zeek_files][total_bytes]}" } } } | ||||
|  | ||||
|       # 🗹 Hash - Hashes, usually file hashes. - https://www.elastic.co/guide/en/ecs/current/ecs-hash.html | ||||
|       # file.hash.md5,sha1,sha256 | ||||
|       if ([zeek_files][md5]) {                      mutate { id => "mutate_add_field_ecs_files_hash_md5" | ||||
|                                                              add_field => { "[file][hash][md5]" => "%{[zeek_files][md5]}" } } } | ||||
|       if ([zeek_files][sha1]) {                     mutate { id => "mutate_add_field_ecs_files_hash_sha1" | ||||
|                                                              add_field => { "[file][hash][sha1]" => "%{[zeek_files][sha1]}" } } } | ||||
|       if ([zeek_files][sha256]) {                   mutate { id => "mutate_add_field_ecs_files_hash_sha256" | ||||
|                                                              add_field => { "[file][hash][sha256]" => "%{[zeek_files][sha256]}" } } } | ||||
|     } | ||||
|  | ||||
|     if ([zeek_smb_files]) { | ||||
|  | ||||
|       # from smb_files, file.created,accessed,ctime,mtime,size | ||||
|       if ([zeek_smb_files][times_created]) {        mutate { id => "mutate_add_field_ecs_smb_created" | ||||
|                                                              add_field => { "[file][created]" => "%{[zeek_smb_files][times_created]}" } } } | ||||
|  | ||||
|       if ([zeek_smb_files][times_accessed]) {       mutate { id => "mutate_add_field_ecs_smb_accessed" | ||||
|                                                              add_field => { "[file][accessed]" => "%{[zeek_smb_files][times_accessed]}" } } } | ||||
|  | ||||
|       if ([zeek_smb_files][times_changed]) {        mutate { id => "mutate_add_field_ecs_smb_changed" | ||||
|                                                              add_field => { "[file][ctime]" => "%{[zeek_smb_files][times_changed]}" } } } | ||||
|  | ||||
|       if ([zeek_smb_files][times_modified]) {       mutate { id => "mutate_add_field_ecs_smb_modified" | ||||
|                                                              add_field => { "[file][mtime]" => "%{[zeek_smb_files][times_modified]}" } } } | ||||
|  | ||||
|       if ([zeek_smb_files][size]) {                 mutate { id => "mutate_add_field_ecs_smb_size" | ||||
|                                                              add_field => { "[file][size]" => "%{[zeek_smb_files][size]}" } } } | ||||
|  | ||||
|       # file.name from smb_files.name | ||||
|       if (![file][name]) and ([zeek_smb_files][name]) { | ||||
|         mutate { id => "mutate_add_field_ecs_file_smb_files_name" | ||||
|                  add_field => { "[file][name]" => "%{[zeek_smb_files][name]}" } } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     # file.directory from zeek_smb_files.smb_path | ||||
|     if ([@metadata][smb_path]) { | ||||
|       if (![file][type]) { mutate { id => "mutate_add_field_ecs_file_type_smb_path" | ||||
|                                     add_field => { "[file][type]" => "file" } } } | ||||
|  | ||||
|       mutate { id => "mutate_add_field_ecs_file_directory_from_smb" | ||||
|                add_field => { "[file][directory]" => "%{[@metadata][smb_path]}" } } | ||||
|     } | ||||
|  | ||||
|     # file.path from file.directory and file.name, if present and not already populated | ||||
|     if ([file][directory]) and (![file][path]) { | ||||
|       if ([file][name]) { | ||||
|         mutate { id => "mutate_add_field_ecs_path_from_dir_and_name" | ||||
|                  add_field => { "[file][path]" => "%{[file][directory]}/%{[file][name]}" } } | ||||
|       } else { | ||||
|         mutate { id => "mutate_add_field_ecs_path_from_dir_only" | ||||
|                  add_field => { "[file][path]" => "%{[file][directory]}" } } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if ([file][name]) { | ||||
|       if (![file][type]) { mutate { id => "mutate_add_field_ecs_file_type_name" | ||||
|                                     add_field => { "[file][type]" => "file" } } } | ||||
|  | ||||
|       # file.extension | ||||
|       grok { | ||||
|         id => "grok_zeek_files_fileext_ecs" | ||||
|         match => { "[file][name]" => [ "%{GREEDYDATA}\.%{DATA:[file][extension]}" ] } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     # 🗹 HTTP - Fields describing an HTTP request. - https://www.elastic.co/guide/en/ecs/current/ecs-http.html | ||||
|     if ([zeek_http]) { | ||||
|  | ||||
|       if ([zeek_http][request_body_len]) {        mutate { id => "mutate_add_field_ecs_http_request_body_bytes" | ||||
|                                                            add_field => { "[http][request][body][bytes]" => "%{[zeek_http][request_body_len]}" } } } | ||||
|  | ||||
|       if ([zeek_http][method]) {                  mutate { id => "mutate_add_field_ecs_http_request_method" | ||||
|                                                            add_field => { "[http][request][method]" => "%{[zeek_http][method]}" } } } | ||||
|  | ||||
|       if ([zeek_http][referrer]) {                mutate { id => "mutate_add_field_ecs_http_request_referrer" | ||||
|                                                            add_field => { "[http][request][referrer]" => "%{[zeek_http][referrer]}" } } } | ||||
|  | ||||
|       if ([zeek_http][response_body_len]) {       mutate { id => "mutate_add_field_ecs_http_response_body_bytes" | ||||
|                                                            add_field => { "[http][response][body][bytes]" => "%{[zeek_http][response_body_len]}" } } } | ||||
|  | ||||
|       if ([zeek_http][status_code]) {             mutate { id => "mutate_add_field_ecs_http_response_status_cocde" | ||||
|                                                            add_field => { "[http][response][status_cocde]" => "%{[zeek_http][status_code]}" } } } | ||||
|  | ||||
|       if ([zeek_http][version]) {                 mutate { id => "mutate_add_field_ecs_http_version" | ||||
|                                                            add_field => { "[http][version]" => "%{[zeek_http][version]}" } } } | ||||
|  | ||||
|       # ☐ URL - Fields that let you store URLs in various forms. - https://www.elastic.co/guide/en/ecs/current/ecs-url.html | ||||
|       # todo: handle URIs from other protocols (SIP, FTP, ...) | ||||
|       if ([zeek_http][uri]) or ([zeek_http][host]) { | ||||
|         ruby { | ||||
|           id => "ruby_ecs_uri_parse_from_zeek_http" | ||||
|           init => "require 'uri'" | ||||
|           code => " | ||||
|             scheme = 'http' | ||||
|             user = event.get('[zeek][user]') | ||||
|             password = event.get('[zeek][password]') | ||||
|             host = event.get('[zeek_http][host]') | ||||
|             port = event.get('[zeek][resp_p]') | ||||
|             uri = event.get('[zeek_http][uri]') | ||||
|             ext = (uri.nil? || !(uri.include? '/')) ? nil : File.extname(uri).partition('.').last.split(/[\?#]/)[0] | ||||
|             fragment = uri.nil? ? nil : uri.partition('#').last | ||||
|             query = uri.nil? ? nil : uri.partition('?').last | ||||
|             event.set('[url][scheme]', scheme) | ||||
|             event.set('[url][original]', scheme + '://' + (host.nil? ? '' : host) + (uri.nil? ? '' : uri)) | ||||
|             event.set('[url][full]', scheme + '://' + (user.nil? ? '' : Array(user).first) + (password.nil? ? '' : ':' + password) + ((user.nil? && password.nil?) ? '' : '@') + (host.nil? ? '' : host) + (port.nil? ? '' : ':' + port) + (uri.nil? ? '' : uri)) | ||||
|             event.set('[url][domain]', host) unless host.nil? | ||||
|             event.set('[url][extension]', ext) unless ext.nil? || ext.empty? | ||||
|             event.set('[url][fragment]', fragment) unless fragment.nil? || fragment.empty? | ||||
|             event.set('[url][password]', password) unless password.nil? | ||||
|             event.set('[url][path]', uri) unless uri.nil? | ||||
|             event.set('[url][port]', port) unless port.nil? | ||||
|             event.set('[url][query]', query) unless query.nil? || query.empty? | ||||
|             event.set('[url][user]', Array(user).first) unless user.nil? | ||||
|           " | ||||
|           # TODO: domain stuff (url.registered_domain, url.top_level_domain) | ||||
|           # perhaps use something like https://github.com/plutonbacon/logstash-filter-publicsuffix | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     # 🗹 Related - Fields meant to facilitate pivoting around a piece of data. - https://www.elastic.co/guide/en/ecs/current/ecs-related.html | ||||
|  | ||||
|     # related.user (zeek.user is already the array we want) | ||||
|     if ([zeek][user]) { mutate { id => "mutate_merge_field_related_zeek_user" | ||||
|                                  merge => { "[related][user]" => "[zeek][user]" } } } | ||||
|  | ||||
|     # related.hash (accumulate all hash/fingerprint fields into related.hash) | ||||
|     if ([zeek_files][md5]) {                      mutate { id => "mutate_merge_field_related_hash_files_md5" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_files][md5]" } } } | ||||
|     if ([zeek_files][sha1]) {                     mutate { id => "mutate_merge_field_related_hash_files_sha1" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_files][sha1]" } } } | ||||
|     if ([zeek_files][sha256]) {                   mutate { id => "mutate_merge_field_related_hash_files_sha256" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_files][sha256]" } } } | ||||
|     if ([zeek_ssh][hassh]) {                      mutate { id => "mutate_merge_field_related_hash_ssh_hassh" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_ssh][hassh]" } } } | ||||
|     if ([zeek_ssh][hasshServer]) {                mutate { id => "mutate_merge_field_related_hash_ssh_hasshServer" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_ssh][hasshServer]" } } } | ||||
|     if ([zeek_ssl][ja3]) {                        mutate { id => "mutate_merge_field_related_hash_ssl_ja3" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_ssl][ja3]" } } } | ||||
|     if ([zeek_ssl][ja3s]) {                       mutate { id => "mutate_merge_field_related_hash_zeek_ssl_ja3s" | ||||
|                                                            merge => { "[related][hash]" => "[zeek_ssl][ja3s]" } } } | ||||
|  | ||||
|     # related.ip (all IP-type fields get rolled up into related.ip) | ||||
|     if ([zeek][destination_geo][ip]) {           mutate { id => "mutate_merge_field_related_ip_zeek_destination_geo_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek][destination_geo][ip]" } } } | ||||
|     if ([zeek][orig_h]) {                        mutate { id => "mutate_merge_field_related_ip_zeek_orig_h" | ||||
|                                                           merge => { "[related][ip]" => "[zeek][orig_h]" } } } | ||||
|     if ([zeek][resp_h]) {                        mutate { id => "mutate_merge_field_related_ip_zeek_resp_h" | ||||
|                                                          merge => { "[related][ip]" => "[zeek][resp_h]" } } } | ||||
|     if ([zeek][source_geo][ip]) {                mutate { id => "mutate_merge_field_related_ip_zeek_source_geo_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek][source_geo][ip]" } } } | ||||
|     if ([zeek_dhcp][assigned_ip]) {              mutate { id => "mutate_merge_field_related_ip_zeek_dhcp_assigned_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_dhcp][assigned_ip]" } } } | ||||
|     if ([zeek_dhcp][requested_ip]) {             mutate { id => "mutate_merge_field_related_ip_zeek_dhcp_requested_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_dhcp][requested_ip]" } } } | ||||
|     if ([zeek_enip_list_identity][device_ip]) {  mutate { id => "mutate_merge_field_related_ip_zeek_enip_list_identity_device_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_enip_list_identity][device_ip]" } } } | ||||
|     if ([zeek_files][rx_hosts]) {                mutate { id => "mutate_merge_field_related_ip_zeek_files_rx_hosts" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_files][rx_hosts]" } } } | ||||
|     if ([zeek_files][tx_hosts]) {                mutate { id => "mutate_merge_field_related_ip_zeek_files_tx_hosts" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_files][tx_hosts]" } } } | ||||
|     if ([zeek_ftp][data_channel_orig_h]) {       mutate { id => "mutate_merge_field_related_ip_zeek_ftp_data_channel_orig_h" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_ftp][data_channel_orig_h]" } } } | ||||
|     if ([zeek_ftp][data_channel_resp_h]) {       mutate { id => "mutate_merge_field_related_ip_zeek_ftp_data_channel_resp_h" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_ftp][data_channel_resp_h]" } } } | ||||
|     if ([zeek_notice][dst]) {                    mutate { id => "mutate_merge_field_related_ip_zeek_notice_dst" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_notice][dst]" } } } | ||||
|     if ([zeek_notice][src]) {                    mutate { id => "mutate_merge_field_related_ip_zeek_notice_src" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_notice][src]" } } } | ||||
|     if ([zeek_radius][framed_addr]) {            mutate { id => "mutate_merge_field_related_ip_zeek_radius_framed_addr" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_radius][framed_addr]" } } } | ||||
|     if ([zeek_smtp][path]) {                     mutate { id => "mutate_merge_field_related_ip_zeek_smtp_path" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_smtp][path]" } } } | ||||
|     if ([zeek_smtp][x_originating_ip]) {         mutate { id => "mutate_merge_field_related_ip_zeek_smtp_x_originating_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_smtp][x_originating_ip]" } } } | ||||
|     if ([zeek_socks][bound_host]) {              mutate { id => "mutate_merge_field_related_ip_zeek_socks_bound_host" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_socks][bound_host]" } } } | ||||
|     if ([zeek_socks][request_host]) {            mutate { id => "mutate_merge_field_related_ip_zeek_socks_request_host" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_socks][request_host]" } } } | ||||
|     if ([zeek_x509][san_ip]) {                   mutate { id => "mutate_merge_field_related_ip_zeek_x509_san_ip" | ||||
|                                                           merge => { "[related][ip]" => "[zeek_x509][san_ip]" } } } | ||||
|     if ([related][ip]) { | ||||
|       ruby { | ||||
|         id => "ruby_related_ip_uniq" | ||||
|         code => "event.set('[related][ip]', event.get('[related][ip]').uniq)" | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     # 🗹 Rule - Fields to capture details about rules used to generate alerts or other notable events. - https://www.elastic.co/guide/en/ecs/current/ecs-rule.html | ||||
|     #   - signatures | ||||
|     #     - engine - >rule.author | ||||
|     #     - signature_id -> rule.name | ||||
|     #     - event_msg -> rule.description | ||||
|     #   - notice | ||||
|     #     - category -> rule.category, rule.author (mapped), rule.reference (mapped), rule.license (mapped) | ||||
|     #     - sub_category -> rule.name | ||||
|     #   - weird | ||||
|     #     - name -> rule.name | ||||
|  | ||||
|     if ([zeek_signatures]) { | ||||
|       if ([zeek_signatures][engine]) {       mutate { id => "mutate_merge_field_ecs_rule_author_signatures_engine" | ||||
|                                                       merge => { "[rule][author]" => "[zeek_signatures][engine]" } } } | ||||
|  | ||||
|       if ([zeek_signatures][signature_id]) { mutate { id => "mutate_add_field_ecs_rule_id_signature_name" | ||||
|                                                       merge => { "[rule][name]" => "[zeek_signatures][signature_id]" } } } | ||||
|  | ||||
|       if ([zeek_signatures][event_msg]) {    mutate { id => "mutate_add_field_ecs_rule_id_signature_event_msg"                                                      merge => { "[rule][description]" => "[zeek_signatures][event_msg]" } } } | ||||
|     } | ||||
|  | ||||
|     if ([zeek_notice]) { | ||||
|  | ||||
|       mutate { id => "mutate_add_field_ecs_rule_ruleset_notice_zeek" | ||||
|                add_field => { "[rule][ruleset]" => "Zeek Notices" } } | ||||
|  | ||||
|       if ([zeek_notice][category]) {     mutate { id => "mutate_add_field_ecs_rule_category_notice_category" | ||||
|                                                   add_field => { "[rule][category]" => "%{[zeek_notice][category]}" } } } | ||||
|  | ||||
|       if ([zeek_notice][sub_category]) { mutate { id => "mutate_add_field_ecs_rule_category_notice_sub_category" | ||||
|                                                   add_field => { "[rule][name]" => "%{[zeek_notice][sub_category]}" } } } | ||||
|  | ||||
|       translate { | ||||
|         id => "translate_zeek_notice_author" | ||||
|         field => "[zeek_notice][category]" | ||||
|         destination => "[@metadata][zeek_noticed_mapped_author]" | ||||
|         dictionary_path => "/etc/notice_authors.yaml" | ||||
|         fallback => "Zeek" | ||||
|       } | ||||
|       if ([@metadata][zeek_noticed_mapped_author]) { | ||||
|         mutate { id => "mutate_merge_zeek_noticed_mapped_author" | ||||
|                  merge => { "[rule][author]" => "[@metadata][zeek_noticed_mapped_author]" } } | ||||
|       } | ||||
|  | ||||
|       translate { | ||||
|         id => "translate_zeek_notice_reference" | ||||
|         field => "[zeek_notice][category]" | ||||
|         destination => "[@metadata][zeek_noticed_mapped_reference]" | ||||
|         dictionary_path => "/etc/notice_reference.yaml" | ||||
|         fallback => "https://docs.zeek.org/en/current/zeek-noticeindex.html" | ||||
|       } | ||||
|       if ([@metadata][zeek_noticed_mapped_reference]) { | ||||
|         mutate { id => "mutate_merge_zeek_noticed_mapped_reference" | ||||
|                  merge => { "[rule][reference]" => "[@metadata][zeek_noticed_mapped_reference]" } } | ||||
|       } | ||||
|  | ||||
|       translate { | ||||
|         id => "translate_zeek_notice_license" | ||||
|         field => "[zeek_notice][category]" | ||||
|         destination => "[@metadata][zeek_noticed_mapped_license]" | ||||
|         dictionary_path => "/etc/notice_license.yaml" | ||||
|         fallback => "https://raw.githubusercontent.com/zeek/zeek/master/COPYING" | ||||
|       } | ||||
|       if ([@metadata][zeek_noticed_mapped_license]) { | ||||
|         mutate { id => "mutate_merge_zeek_noticed_mapped_license" | ||||
|                  merge => { "[rule][license]" => "[@metadata][zeek_noticed_mapped_license]" } } | ||||
|       } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     if ([zeek_weird][name]) { | ||||
|       mutate { id => "mutate_add_field_ecs_rule_author_zeek_weird" | ||||
|                add_field => { "[rule][author]" => "Zeek" } } | ||||
|       mutate { id => "mutate_add_field_ecs_rule_ruleset_zeek_weird" | ||||
|                add_field => { "[rule][ruleset]" => "Zeek Weird Logs" } } | ||||
|       mutate { id => "mutate_add_field_ecs_rule_reference_zeek_weird" | ||||
|                add_field => { "[rule][reference]" => "https://docs.zeek.org/en/current/scripts/base/frameworks/notice/weird.zeek.html" } } | ||||
|       mutate { id => "mutate_add_field_ecs_rule_name_weird_name" | ||||
|                add_field => { "[rule][name]" => "%{[zeek_weird][name]}" } } | ||||
|     } | ||||
|  | ||||
|     # 🗹 Threat - Fields to classify events and alerts according to a threat taxonomy. - https://www.elastic.co/guide/en/ecs/current/ecs-threat.html | ||||
|     if ([zeek_notice]) { | ||||
|  | ||||
|       if ([zeek_notice][category] == "ATTACK") { | ||||
|  | ||||
|         # populate threat information for MITRE ATT&CK notices from mitre-attack/bzar plugin | ||||
|         mutate { id => "mutate_add_field_ecs_threat_framework_mitre_attack" | ||||
|                  add_field => { "[threat][framework]" => "MITRE ATT&CK" } } | ||||
|  | ||||
|         if ([zeek_notice][sub_category]) { | ||||
|           mutate { id => "mutate_add_field_ecs_threat_tactic_name_mitre" | ||||
|                    add_field => { "[threat][tactic][name]" => "%{[zeek_notice][sub_category]}" } } | ||||
|           mutate { id => "mutate_gsub_ecs_threat_tactic_name_notice_sub" | ||||
|                    gsub => [ "[threat][tactic][name]", "_,", " " ] } | ||||
|           translate { | ||||
|             id => "translate_zeek_mitre_attack_tactic_name_to_id" | ||||
|             field => "[zeek_notice][sub_category]" | ||||
|             destination => "[threat][tactic][id]" | ||||
|             dictionary_path => "/etc/mitre_attack_tactic_ids.yaml" | ||||
|           } | ||||
|           translate { | ||||
|             id => "translate_zeek_mitre_attack_tactic_name_to_reference" | ||||
|             field => "[zeek_notice][sub_category]" | ||||
|             destination => "[threat][tactic][reference]" | ||||
|             dictionary_path => "/etc/mitre_attack_tactic_reference.yaml" | ||||
|             fallback => "https://attack.mitre.org/tactics/enterprise/" | ||||
|           } | ||||
|         } | ||||
|  | ||||
|         if ([zeek_notice][sub]) and ([zeek_notice][sub] =~ /^T/) { | ||||
|           # eg., T1077 Windows Admin Shares + T1105 Remote File Copy | ||||
|           ruby { | ||||
|             id => "ruby_ecs_threat_technique_from_attack" | ||||
|             code => " | ||||
|               idArray = Array.new | ||||
|               nameArray = Array.new | ||||
|               event.get('[zeek_notice][sub]').split('+').each do |technique| | ||||
|                 id, name = technique.strip.match(/(^T.*?)\s+(.+$)/).captures | ||||
|                 idArray.push(id) unless id.nil? | ||||
|                 nameArray.push(name) unless name.nil? | ||||
|               end | ||||
|               event.set('[threat][technique][id]', idArray) | ||||
|               event.set('[threat][technique][name]', nameArray) | ||||
|               event.set('[threat][technique][reference]', idArray.clone.map(&:clone).map{|x| x.prepend('https://attack.mitre.org/techniques/')}) | ||||
|             " | ||||
|           } | ||||
|         } | ||||
|  | ||||
|       } else if ([zeek_notice][category] == "EternalSafety") { | ||||
|         # populate threat information for EternalSafety from 0xl3x1/zeek-EternalSafety plugin | ||||
|         mutate { id => "mutate_add_field_ecs_threat_framework_eternal_safety" | ||||
|                  add_field => { "[threat][framework]" => "EternalSafety" } } | ||||
|         if ([zeek_notice][sub_category]) { mutate { id => "mutate_add_field_ecs_threat_technique_name_eternal" | ||||
|                                                     add_field => { "[threat][technique][name]" => "%{[zeek_notice][sub_category]}" } } } | ||||
|         if ([rule][reference])           { mutate { id => "mutate_add_field_ecs_threat_technique_reference_eternal" | ||||
|                                                     add_field => { "[threat][technique][reference]" => "%{[rule][reference]}" } } } | ||||
|       } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     # 🗹 TLS - Fields describing a TLS connection. - https://www.elastic.co/guide/en/ecs/current/ecs-tls.html | ||||
|     if ([zeek_ssl]) { | ||||
|  | ||||
|       if ([zeek_ssl][ssl_version]) { | ||||
|         # turn TLSv10, TLSv13, TSLv12, etc. to 'tls' and '1.2', etc. | ||||
|         # TODO: tls.cipher already exists as a Arkime field, will this conflict/duplicate that? | ||||
|         # EDIT: it won't duplicate it, but it will replace it. I guess that's okay for now. | ||||
|         ruby { | ||||
|           id => "ruby_ecs_ssl_version_parse" | ||||
|           code => " | ||||
|             verMatch = event.get('[zeek_ssl][ssl_version]').tr('.', '').match(/(.+)\s*[v-]\s*([\d\.]+)/i) | ||||
|             verParts = verMatch.nil? ? nil : verMatch.captures | ||||
|             unless verParts.nil? | ||||
|               event.set('[tls][version_protocol]', verParts[0].downcase) | ||||
|               event.set('[tls][version]', verParts[1].split(//).join('.')) | ||||
|             end | ||||
|           " | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if ([zeek_ssl][established]) {          mutate { id => "mutate_add_field_ecs_zeek_tls_established" | ||||
|                                                        add_field => { "[tls][established]" => "%{[zeek_ssl][established]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][resumed]) {              mutate { id => "mutate_add_field_ecs_zeek_tls_resumed" | ||||
|                                                        add_field => { "[tls][resumed]" => "%{[zeek_ssl][resumed]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][next_protocol]) { | ||||
|         mutate { id => "mutate_add_field_ecs_zeek_tls_next_protocol" | ||||
|                        add_field => { "[tls][next_protocol]" => "%{[zeek_ssl][next_protocol]}" } } | ||||
|         mutate { id => "mutate_lowercase_field_ecs_zeek_tls_next_protocol" | ||||
|                  lowercase => [ "[tls][next_protocol]" ] } | ||||
|       } | ||||
|  | ||||
|       # TODO: tls.cipher already exists as a Arkime field, will this conflict/duplicate that? | ||||
|       # EDIT: apparently it does duplicate the value, so I'm commenting this out for now... | ||||
|       #if ([zeek_ssl][cipher]) {               mutate { id => "mutate_add_field_ecs_zeek_tls_cipher" | ||||
|       #                                                 add_field => { "[tls][cipher]" => "%{[zeek_ssl][cipher]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][curve]) {                mutate { id => "mutate_add_field_ecs_zeek_tls_client_curve" | ||||
|                                                        add_field => { "[tls][curve]" => "%{[zeek_ssl][curve]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][ja3]) {                  mutate { id => "mutate_add_field_ecs_zeek_tls_client_ja3" | ||||
|                                                        add_field => { "[tls][client][ja3]" => "%{[zeek_ssl][ja3]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][client_issuer_full]) {   mutate { id => "mutate_add_field_ecs_zeek_tls_client_issuer_full" | ||||
|                                                        add_field => { "[tls][client][issuer]" => "%{[zeek_ssl][client_issuer_full]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][client_subject_full]) {  mutate { id => "mutate_add_field_ecs_zeek_tls_client_subject_full" | ||||
|                                                        add_field => { "[tls][client][subject]" => "%{[zeek_ssl][client_subject_full]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][server_name]) { | ||||
|         mutate { id => "mutate_add_field_ecs_zeek_tls_client_server_name" | ||||
|                  add_field => { "[tls][client][server_name]" => "%{[zeek_ssl][server_name]}" } } | ||||
|         mutate { id => "mutate_add_field_ecs_zeek_tls_client_server_name_destination_domain" | ||||
|                  add_field => { "[destination][domain]" => "%{[zeek_ssl][server_name]}" } } | ||||
|       } | ||||
|  | ||||
|       if ([zeek_ssl][issuer_full]) {          mutate { id => "mutate_add_field_ecs_zeek_tls_issuer_full" | ||||
|                                                        add_field => { "[tls][server][issuer]" => "%{[zeek_ssl][issuer_full]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][ja3s]) {                 mutate { id => "mutate_add_field_ecs_zeek_tls_server_ja3s" | ||||
|                                                        add_field => { "[tls][server][ja3s]" => "%{[zeek_ssl][ja3s]}" } } } | ||||
|  | ||||
|       if ([zeek_ssl][subject_full]) {         mutate { id => "mutate_add_field_ecs_zeek_tls_subject_full" | ||||
|                                                        add_field => { "[tls][server][subject]" => "%{[zeek_ssl][subject_full]}" } } } | ||||
|     } | ||||
|  | ||||
|     # ☐ User agent - Fields to describe a browser user_agent string. - https://www.elastic.co/guide/en/ecs/current/ecs-user_agent.html | ||||
|     #    - TODO: potentially more parsing could be done for user agent strings (.name, .device.name, .version) | ||||
|  | ||||
|     if ([zeek_gquic][user_agent]) { mutate { id => "mutate_add_field_metadata_http_ecs_useragent_gquic" | ||||
|                                              add_field => { "[@metadata][generic_user_agent]" => "%{[zeek_gquic][user_agent]}" } } } | ||||
|     if ([zeek_http][user_agent]) {  mutate { id => "mutate_add_field_metadata_http_ecs_useragent_http" | ||||
|                                              add_field => { "[@metadata][generic_user_agent]" => "%{[zeek_http][user_agent]}" } } } | ||||
|     if ([zeek_sip][user_agent]) {   mutate { id => "mutate_add_field_metadata_http_ecs_useragent_sip" | ||||
|                                              add_field => { "[@metadata][generic_user_agent]" => "%{[zeek_sip][user_agent]}" } } } | ||||
|     if ([zeek_smtp][user_agent]) {  mutate { id => "mutate_add_field_metadata_http_ecs_useragent_smtp" | ||||
|                                              add_field => { "[@metadata][generic_user_agent]" => "%{[zeek_smtp][user_agent]}" } } } | ||||
|     if ([@metadata][generic_user_agent]) { | ||||
|       mutate { id => "mutate_add_field_ecs_user_agent_original_zeek" | ||||
|                add_field => { "[user_agent][original]" => "%{[@metadata][generic_user_agent]}" } } | ||||
|     } | ||||
|  | ||||
|     # ☐ Agent - Fields about the monitoring agent. - https://www.elastic.co/guide/en/ecs/current/ecs-agent.html | ||||
|     #   - agent will be set for logs coming from a sensor (hedgehog) | ||||
|     #   - double-check agent set for local Malcolm filebeat Zeek logs to ensure it's set correctly, too | ||||
|     # ☐ Observer - Fields describing an entity observing the event from outside the host. - https://www.elastic.co/guide/en/ecs/current/ecs-observer.html | ||||
|     #   - anything useful we could get here from either Malcolm or Hedgehog? | ||||
|     # ☐ Destination - Fields about the destination side of a network connection, used with source. - https://www.elastic.co/guide/en/ecs/current/ecs-destination.html | ||||
|     # ☐ Source - Fields about the source side of a network connection, used with destination. - https://www.elastic.co/guide/en/ecs/current/ecs-source.html | ||||
|     #   - I have client/server, do I need to do anything with this as well? | ||||
|     # ☐ Error - Fields about errors of any kind. - https://www.elastic.co/guide/en/ecs/current/ecs-error.html | ||||
|     #   - There could be a lot of cases where there are errors, do we lump them all in here? we'd need to idenfity | ||||
|     #     instances of error, error_msg, reply, status code, etc... | ||||
|     # ☐ User - Fields to describe the user relevant to the event. - https://www.elastic.co/guide/en/ecs/current/ecs-user.html | ||||
|     #   - a *lot* of the details ECS wants for the user (client, destination, email, domain, etc.) aren't provided by Zeek | ||||
|     #     also, it appears that there is an issue with type mismatch between Arkime's "user" field and ECS "user.name", etc. | ||||
|     # ☐ Vulnerability - Fields to describe the vulnerability relevant to an event. - https://www.elastic.co/guide/en/ecs/current/ecs-vulnerability.html | ||||
|     #   - There are some CVE zeek plugins, they may be mappable to this (?) | ||||
|     # ☐ VLAN - Fields to describe observed VLAN information. - https://www.elastic.co/guide/en/ecs/current/ecs-vlan.html | ||||
|     #   - conflicts with Arkime's VLAN field: | ||||
|     #       Can't merge a non object mapping [vlan] with an object mapping [vlan]", "caused_by"=>{"type"=>"illegal_argument_exception", | ||||
|     #       "reason"=>"Can't merge a non object mapping [vlan] with an object mapping [vlan] | ||||
|  | ||||
|     # 🗷 Base - All fields defined directly at the top level - https://www.elastic.co/guide/en/ecs/current/ecs-base.html | ||||
|     # 🗷 Cloud - Fields about the cloud resource. - https://www.elastic.co/guide/en/ecs/current/ecs-cloud.html | ||||
|     # 🗷 Code Signature - These fields contain information about binary code signatures. - https://www.elastic.co/guide/en/ecs/current/ecs-code_signature.html | ||||
|     # 🗷 Container - Fields describing the container that generated this event. - https://www.elastic.co/guide/en/ecs/current/ecs-container.html | ||||
|     # 🗷 DLL - These fields contain information about code libraries dynamically loaded into processes. - https://www.elastic.co/guide/en/ecs/current/ecs-dll.html | ||||
|     # 🗷 ECS - Meta-information specific to ECS. - https://www.elastic.co/guide/en/ecs/current/ecs-ecs.html | ||||
|     # 🗷 Group - User's group relevant to the event. - https://www.elastic.co/guide/en/ecs/current/ecs-group.html | ||||
|     # 🗷 Host - Fields describing the relevant computing instance. - https://www.elastic.co/guide/en/ecs/current/ecs-host.html | ||||
|     # 🗷 Interface - Fields to describe observer interface information. - https://www.elastic.co/guide/en/ecs/current/ecs-interface.html | ||||
|     # 🗷 Log - Details about the event's logging mechanism. - https://www.elastic.co/guide/en/ecs/current/ecs-log.html | ||||
|     # 🗷 Operating System - OS fields contain information about the operating system. - https://www.elastic.co/guide/en/ecs/current/ecs-os.html | ||||
|     # 🗷 Organization - Fields describing the organization or company the event is associated with. - https://www.elastic.co/guide/en/ecs/current/ecs-organization.html | ||||
|     # 🗷 Package - These fields contain information about an installed software package. - https://www.elastic.co/guide/en/ecs/current/ecs-package.html | ||||
|     #   - I almost mapped "software" to this but it doesn't really line up (installed packages vs. software network traffic observed) | ||||
|     # 🗷 PE Header - These fields contain Windows Portable Executable (PE) metadata. - https://www.elastic.co/guide/en/ecs/current/ecs-pe.html | ||||
|     #   - You would think zeek_pe would line up here, but this is just header stuff specific to windows executables and there's not much that lines up | ||||
|     # 🗷 Process - These fields contain information about a process. - https://www.elastic.co/guide/en/ecs/current/ecs-process.html | ||||
|     # 🗷 Registry - Fields related to Windows Registry operations. - https://www.elastic.co/guide/en/ecs/current/ecs-registry.html | ||||
|     # 🗷 Service - Fields describing the service for or from which the data was collected. - https://www.elastic.co/guide/en/ecs/current/ecs-service.html | ||||
|     # 🗷 Tracing - Fields related to distributed tracing. - https://www.elastic.co/guide/en/ecs/current/ecs-tracing.html | ||||
|  | ||||
|   } # end if ENV_LOGSTASH_ZEEK_TO_ECS | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,5 @@ | ||||
| output { | ||||
|   pipeline { | ||||
|     send_to => ["log-enrichment"] | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user