added Malcolm
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
input {
|
||||
pipeline {
|
||||
address => "log-enrichment"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
filter {
|
||||
|
||||
# todo: make added fields not zeek-specific? (see ECS topic branch)
|
||||
# all the lookups are done here, but some of them are still zeek-specific which
|
||||
# IMO isn't the cleanest. could be refactored/split.
|
||||
|
||||
######## MAC address OUI (manufacturer) lookup #################################################
|
||||
|
||||
# if OUI lookup is requested, enable it
|
||||
mutate {
|
||||
id => "mutate_add_field_env_logstash_oui_lookup"
|
||||
add_field => { "[@metadata][ENV_LOGSTASH_OUI_LOOKUP]" => "${LOGSTASH_OUI_LOOKUP:false}" }
|
||||
}
|
||||
if ([@metadata][ENV_LOGSTASH_OUI_LOOKUP] == "true") {
|
||||
|
||||
# srcMac/dstMac are arrays at this point, as Arkime expects them to be
|
||||
|
||||
if ([srcMac]) and ([srcMac][0]) {
|
||||
|
||||
# attempt lookup of srcMac oui
|
||||
ieee_oui {
|
||||
id => "ieee_oui_srcMac"
|
||||
source => "[srcMac][0]"
|
||||
target => "[zeek][orig_l2_oui]"
|
||||
ouifile => "/usr/share/logstash/config/oui-logstash.txt"
|
||||
refresh_interval => 0
|
||||
}
|
||||
|
||||
if ([zeek][orig_l2_oui]) {
|
||||
|
||||
# merge orig_l2_oui into srcOui array (with a count of 1)
|
||||
mutate { id => "mutate_merge_field_srcOui"
|
||||
merge => { "[srcOui]" => "[zeek][orig_l2_oui]" } }
|
||||
mutate { id => "mutate_add_field_srcOuiCnt"
|
||||
add_field => { "[srcOuiCnt]" => "1" } }
|
||||
|
||||
# if this is a DHCP log type, copy srcOui to dhcp.oui
|
||||
if ([dhcp][mac]) {
|
||||
mutate {
|
||||
id => "mutate_add_fields_dhcp_oui"
|
||||
add_field => { "[dhcp][oui]" => "%{[srcOui]}" }
|
||||
}
|
||||
mutate {
|
||||
id => "mutate_add_fields_dhcp_ouiCnt"
|
||||
add_field => { "[dhcp][ouiCnt]" => "%{[srcOuiCnt]}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} # end if [srcMac]
|
||||
|
||||
if ([dstMac]) and ([dstMac][0]) {
|
||||
|
||||
# attempt lookup of dstMac oui
|
||||
ieee_oui {
|
||||
id => "ieee_oui_dstMac"
|
||||
source => "[dstMac][0]"
|
||||
target => "[zeek][resp_l2_oui]"
|
||||
ouifile => "/usr/share/logstash/config/oui-logstash.txt"
|
||||
refresh_interval => 0
|
||||
}
|
||||
|
||||
if ([zeek][resp_l2_oui]) {
|
||||
|
||||
# merge resp_l2_oui into dstOui array (with a count of 1)
|
||||
mutate { id => "mutate_merge_field_dstOui"
|
||||
merge => { "[dstOui]" => "[zeek][resp_l2_oui]" } }
|
||||
mutate { id => "mutate_add_field_dstOuiCnt"
|
||||
add_field => { "[dstOuiCnt]" => "1" } }
|
||||
}
|
||||
|
||||
} # end if [dstMac]
|
||||
|
||||
} # end if ENV_LOGSTASH_OUI_LOOKUP
|
||||
################################################################################################
|
||||
|
||||
######## IP address class tagging, GeoIP/ASN lookups, and reverse DNS ###########################
|
||||
if ([srcIp]) {
|
||||
cidr {
|
||||
id => "cidr_add_tag_internal_source"
|
||||
add_tag => [ "internal_source" ]
|
||||
address => [ "%{srcIp}" ]
|
||||
network => [ "0.0.0.0/8", "10.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.2.0/24",
|
||||
"192.88.99.0/24", "192.168.0.0/16", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "224.0.0.0/4", "240.0.0.0/4",
|
||||
"255.255.255.255/32", "::/0", "::/128", "::1/128", "fc00::/7", "fe80::/10", "ff00::/8"]
|
||||
}
|
||||
if (!("internal_source" in [tags])) {
|
||||
mutate { id => "mutate_add_tag_external_source"
|
||||
add_tag => [ "external_source" ] }
|
||||
# map srcIp to GEO countries
|
||||
geoip {
|
||||
id => "geoip_srcIp_geo"
|
||||
source => "[srcIp]"
|
||||
target => "[zeek][source_geo]"
|
||||
}
|
||||
geoip {
|
||||
id => "geoip_srcIp_asn"
|
||||
default_database_type => "ASN"
|
||||
source => "[srcIp]"
|
||||
target => "[@metadata][orig_asn]"
|
||||
}
|
||||
if ([zeek][source_geo] and [zeek][source_geo][country_code2]) {
|
||||
mutate { id => "mutate_add_field_srcGEO"
|
||||
add_field => { "[srcGEO]" => "%{[zeek][source_geo][country_code2]}" } }
|
||||
}
|
||||
if ([@metadata][orig_asn] and [@metadata][orig_asn][as_org] and [@metadata][orig_asn][asn]) {
|
||||
mutate { id => "mutate_add_field_srcASN"
|
||||
add_field => { "[srcASN]" => "AS%{[@metadata][orig_asn][asn]} %{[@metadata][orig_asn][as_org]}" } }
|
||||
}
|
||||
|
||||
# if reverse DNS for public IP addresses is enabled (via environment variable) do it
|
||||
mutate {
|
||||
add_field => { "[@metadata][ENV_LOGSTASH_REVERSE_DNS]" => "${LOGSTASH_REVERSE_DNS:false}" }
|
||||
}
|
||||
if ([@metadata][ENV_LOGSTASH_REVERSE_DNS] == "true") {
|
||||
mutate {
|
||||
id => "mutate_add_field_srcip_for_dns"
|
||||
add_field => {
|
||||
"[zeek][source_ip_reverse_dns]" => "%{[srcIp]}"
|
||||
}
|
||||
}
|
||||
dns {
|
||||
id => "dns_source_ip_reverse_dns"
|
||||
reverse => [ "[zeek][source_ip_reverse_dns]" ]
|
||||
action => "replace"
|
||||
hit_cache_size => 8000
|
||||
hit_cache_ttl => 300
|
||||
failed_cache_size => 8000
|
||||
failed_cache_ttl => 60
|
||||
}
|
||||
if ([srcIp] == [zeek][source_ip_reverse_dns]) {
|
||||
mutate {
|
||||
id => "mutate_remove_field_source_ip_reverse_dns"
|
||||
remove_field => [ "[zeek][source_ip_reverse_dns]" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cidr {
|
||||
id => "cidr_detect_network_type_ipv4_source"
|
||||
add_field => { "[network][type]" => "ipv4" }
|
||||
address => [ "%{srcIp}" ]
|
||||
network => [ "0.0.0.0/0" ]
|
||||
}
|
||||
if (![network][type]) {
|
||||
mutate { id => "mutate_add_network_type_ipv4_source"
|
||||
add_field => { "[network][type]" => "ipv6" } }
|
||||
}
|
||||
} # if ([srcIp])
|
||||
|
||||
if ([dstIp]) {
|
||||
cidr {
|
||||
id => "cidr_add_tag_internal_destination"
|
||||
add_tag => [ "internal_destination" ]
|
||||
address => [ "%{dstIp}" ]
|
||||
network => [ "0.0.0.0/8", "10.0.0.0/8", "100.64.0.0/10", "127.0.0.0/8", "169.254.0.0/16", "172.16.0.0/12", "192.0.0.0/24", "192.0.2.0/24",
|
||||
"192.88.99.0/24", "192.168.0.0/16", "198.18.0.0/15", "198.51.100.0/24", "203.0.113.0/24", "224.0.0.0/4", "240.0.0.0/4",
|
||||
"255.255.255.255/32", "::/0", "::/128", "::1/128", "fc00::/7", "fe80::/10", "ff00::/8"]
|
||||
}
|
||||
if (!("internal_destination" in [tags])) {
|
||||
mutate { id => "mutate_add_tag_external_destination"
|
||||
add_tag => [ "external_destination" ] }
|
||||
# map dstIp to GEO countries
|
||||
geoip {
|
||||
id => "geoip_dstIp_geo"
|
||||
source => "[dstIp]"
|
||||
target => "[zeek][destination_geo]"
|
||||
}
|
||||
geoip {
|
||||
id => "geoip_dstIp_asn"
|
||||
default_database_type => "ASN"
|
||||
source => "[dstIp]"
|
||||
target => "[@metadata][resp_asn]"
|
||||
}
|
||||
if ([zeek][destination_geo] and [zeek][destination_geo][country_code2]) {
|
||||
mutate { id => "mutate_add_field_dstGEO"
|
||||
add_field => { "[dstGEO]" => "%{[zeek][destination_geo][country_code2]}" } }
|
||||
}
|
||||
if ([@metadata][resp_asn] and [@metadata][resp_asn][as_org] and [@metadata][resp_asn][asn]) {
|
||||
mutate { id => "mutate_add_field_dstASN"
|
||||
add_field => { "[dstASN]" => "AS%{[@metadata][resp_asn][asn]} %{[@metadata][resp_asn][as_org]}" } }
|
||||
}
|
||||
|
||||
# if reverse DNS for public IP addresses is enabled (via environment variable) do it
|
||||
if (![@metadata][ENV_LOGSTASH_REVERSE_DNS]) {
|
||||
mutate {
|
||||
add_field => { "[@metadata][ENV_LOGSTASH_REVERSE_DNS]" => "${LOGSTASH_REVERSE_DNS:false}" }
|
||||
}
|
||||
}
|
||||
if ([@metadata][ENV_LOGSTASH_REVERSE_DNS] == "true") {
|
||||
mutate {
|
||||
id => "mutate_add_field_dstip_for_dns"
|
||||
add_field => {
|
||||
"[zeek][destination_ip_reverse_dns]" => "%{[dstIp]}"
|
||||
}
|
||||
}
|
||||
dns {
|
||||
id => "dns_destination_ip_reverse_dns"
|
||||
reverse => [ "[zeek][destination_ip_reverse_dns]" ]
|
||||
action => "replace"
|
||||
hit_cache_size => 8000
|
||||
hit_cache_ttl => 300
|
||||
failed_cache_size => 8000
|
||||
failed_cache_ttl => 60
|
||||
}
|
||||
if ([dstIp] == [zeek][destination_ip_reverse_dns]) {
|
||||
mutate {
|
||||
id => "mutate_remove_field_destination_ip_reverse_dns"
|
||||
remove_field => [ "[zeek][destination_ip_reverse_dns]" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (![network][type]) {
|
||||
cidr {
|
||||
id => "cidr_detect_network_type_ipv4_dest"
|
||||
add_field => { "[network][type]" => "ipv4" }
|
||||
address => [ "%{dstIp}" ]
|
||||
network => [ "0.0.0.0/0" ]
|
||||
}
|
||||
if (![network][type]) {
|
||||
mutate { id => "mutate_add_network_type_ipv4_dest"
|
||||
add_field => { "[network][type]" => "ipv6" } }
|
||||
}
|
||||
}
|
||||
} # if ([dstIp])
|
||||
|
||||
if ([dns][host]) {
|
||||
# if requested, look up DNS queries using freq_server.py to get entropy scores
|
||||
|
||||
ruby {
|
||||
id => "ruby_dns_freq_lookup"
|
||||
init => "
|
||||
require 'net/http'
|
||||
require 'cgi'
|
||||
$freqLookupEnabled = ENV['FREQ_LOOKUP'] || 'false'
|
||||
"
|
||||
# freq_server.py returns a string like: (2.9333, 3.6353)
|
||||
code => "
|
||||
if ($freqLookupEnabled == 'true') then
|
||||
scoresv1 = Array.new
|
||||
scoresv2 = Array.new
|
||||
scoresTmp = Array.new
|
||||
begin
|
||||
event.get('[dns][host]').each { |query|
|
||||
if (query.length >= 4) and (query !~ /(ip6\.int|ip6\.arpa|in-addr\.arpa|b32\.i2p)$/i) then
|
||||
scoresTmp.clear
|
||||
scoresTmp.concat(Net::HTTP.get_response(URI.parse('http://freq:10004/measure/' + CGI.escape(query))).body.gsub(/(^\(|\)$|\s+)/, '').split(',').map(&:to_f))
|
||||
if (scoresTmp.length == 2) then
|
||||
scoresv1 << scoresTmp[0]
|
||||
scoresv2 << scoresTmp[1]
|
||||
end
|
||||
end
|
||||
}
|
||||
rescue Exception => e
|
||||
event.set('ruby_exception', 'ruby_dns_freq_lookup: ' + e.message)
|
||||
end
|
||||
event.set('[zeek][freq_score_v1]', scoresv1) unless (scoresv1.length == 0)
|
||||
event.set('[zeek][freq_score_v2]', scoresv2) unless (scoresv2.length == 0)
|
||||
end"
|
||||
}
|
||||
} # end if dns.ip
|
||||
|
||||
if ([dns][ip]) and ([dns][ip][0]) {
|
||||
# if this is a DNS record with an IP, GeoIP it as well
|
||||
geoip {
|
||||
id => "geoip_dns_ip_asn"
|
||||
default_database_type => "ASN"
|
||||
source => "[dns][ip][0]"
|
||||
target => "[@metadata][dns_asn]"
|
||||
}
|
||||
if ([@metadata][dns_asn] and [@metadata][dns_asn][as_org] and [@metadata][dns_asn][asn]) {
|
||||
# this is stupid, the %{} doesn't seem to be liked by mutate.merge
|
||||
mutate { id => "mutate_add_field_dns_asn"
|
||||
add_field => { "[@metadata][asn_str]" => "AS%{[@metadata][dns_asn][asn]} %{[@metadata][dns_asn][as_org]}" } }
|
||||
mutate { id => "mutate_merge_dns_asn"
|
||||
merge => { "[dns][ASN]" => "[@metadata][asn_str]" } }
|
||||
}
|
||||
|
||||
geoip {
|
||||
id => "geoip_dns_ip_geo"
|
||||
source => "[dns][ip][0]"
|
||||
target => "[@metadata][dns_geo]"
|
||||
}
|
||||
if ([@metadata][dns_geo] and [@metadata][dns_geo][country_code2]) {
|
||||
mutate { id => "mutate_merge_dns_geo"
|
||||
merge => { "[dns][GEO]" => "[@metadata][dns_geo][country_code2]" } }
|
||||
}
|
||||
} # end if dns.ip
|
||||
|
||||
if ([radius]) {
|
||||
|
||||
# if this is a Radius record with IP addresses, GeoIP them as well
|
||||
if ([radius][framedIp]) and ([radius][framedIp][0]) {
|
||||
geoip {
|
||||
id => "geoip_radius_framedIp_asn"
|
||||
default_database_type => "ASN"
|
||||
source => "[radius][framedIp][0]"
|
||||
target => "[@metadata][radius_asn]"
|
||||
}
|
||||
if ([@metadata][radius_asn] and [@metadata][radius_asn][as_org] and [@metadata][radius_asn][asn]) {
|
||||
# this is stupid, the %{} doesn't seem to be liked by mutate.merge
|
||||
mutate { id => "mutate_add_field_radius_asn"
|
||||
add_field => { "[@metadata][asn_str]" => "AS%{[@metadata][radius_asn][asn]} %{[@metadata][radius_asn][as_org]}" } }
|
||||
mutate { id => "mutate_merge_radius_asn"
|
||||
merge => { "[radius][framedASN]" => "[@metadata][asn_str]" } }
|
||||
}
|
||||
geoip {
|
||||
id => "geoip_radius_framedIp_geo"
|
||||
source => "[radius][framedIp][0]"
|
||||
target => "[@metadata][radius_geo]"
|
||||
}
|
||||
if ([@metadata][radius_geo] and [@metadata][radius_geo][country_code2]) {
|
||||
mutate { id => "mutate_merge_radius_geo"
|
||||
merge => { "[radius][framedGEO]" => "[@metadata][radius_geo][country_code2]" } }
|
||||
}
|
||||
} # end if radius.framedIp
|
||||
|
||||
if ([radius][endpointIp]) and ([radius][endpointIp][0]) {
|
||||
geoip {
|
||||
id => "geoip_radius_endpointIp_asn"
|
||||
default_database_type => "ASN"
|
||||
source => "[radius][endpointIp][0]"
|
||||
target => "[@metadata][radius_asn]"
|
||||
}
|
||||
if ([@metadata][radius_asn] and [@metadata][radius_asn][as_org] and [@metadata][radius_asn][asn]) {
|
||||
# this is stupid, the %{} doesn't seem to be liked by mutate.merge
|
||||
mutate { id => "mutate_add_field_radius_endpoint_asn"
|
||||
add_field => { "[@metadata][asn_str]" => "AS%{[@metadata][radius_asn][asn]} %{[@metadata][radius_asn][as_org]}" } }
|
||||
mutate { id => "mutate_merge_radius_endpoint_asn"
|
||||
merge => { "[radius][endpointASN]" => "[@metadata][asn_str]" } }
|
||||
}
|
||||
|
||||
geoip {
|
||||
id => "geoip_radius_endpointIp_geo"
|
||||
source => "[radius][endpointIp][0]"
|
||||
target => "[@metadata][radius_geo]"
|
||||
}
|
||||
if ([@metadata][radius_geo] and [@metadata][radius_geo][country_code2]) {
|
||||
mutate { id => "mutate_merge_radius_endpoint_geo"
|
||||
merge => { "[radius][endpointGEO]" => "[@metadata][radius_geo][country_code2]" } }
|
||||
}
|
||||
} # end if radius.endpointIp
|
||||
|
||||
} # end if radius
|
||||
|
||||
if ([zeek_cip_identity][socket_address]) {
|
||||
|
||||
# if this is a zeek_cip_identity record with socket_address, ASN/GeoIP it as well
|
||||
geoip {
|
||||
id => "geoip_zeek_cip_identity_socket_address"
|
||||
default_database_type => "ASN"
|
||||
source => "[zeek_cip_identity][socket_address]"
|
||||
target => "[@metadata][zeek_cip_identity_asn]"
|
||||
}
|
||||
if ([@metadata][zeek_cip_identity_asn] and [@metadata][zeek_cip_identity_asn][as_org] and [@metadata][zeek_cip_identity_asn][asn]) {
|
||||
# this is stupid, the %{} doesn't seem to be liked by mutate.merge
|
||||
mutate { id => "mutate_add_field_zeek_cip_identity_asn"
|
||||
add_field => { "[@metadata][cip_asn_str]" => "AS%{[@metadata][zeek_cip_identity_asn][asn]} %{[@metadata][zeek_cip_identity_asn][as_org]}" } }
|
||||
mutate { id => "mutate_merge_zeek_cip_identity_asn"
|
||||
merge => { "[zeek_cip_identity][socket_address_asn]" => "[@metadata][cip_asn_str]" } }
|
||||
}
|
||||
geoip {
|
||||
id => "geoip_zeek_cip_identity_socket_address_geo"
|
||||
source => "[zeek_cip_identity][socket_address]"
|
||||
target => "[zeek_cip_identity][socket_address_geo]"
|
||||
}
|
||||
|
||||
} # end if zeek_cip_identity.socket_address
|
||||
|
||||
if ([zeek_ssl][server_name]) {
|
||||
mutate {
|
||||
add_field => { "[@metadata][ENV_FREQ_LOOKUP]" => "${FREQ_LOOKUP:false}" }
|
||||
}
|
||||
if ([@metadata][ENV_FREQ_LOOKUP] == "true") {
|
||||
# if requested, look up zeek_ssl.server_name queries using freq_server.py to get entropy scores
|
||||
http {
|
||||
id => "rest_zeek_ssl_server_name_freq_lookup"
|
||||
url => "http://freq:10004/measure/%{[zeek_ssl][server_name]}"
|
||||
target_body => "[@metadata][zeek_ssl_server_name_freq]"
|
||||
}
|
||||
if ([@metadata][zeek_ssl_server_name_freq]) {
|
||||
grok {
|
||||
id => "grok_zeek_ssl_server_name_freq_parse"
|
||||
match => { "[@metadata][zeek_ssl_server_name_freq]" => [ "^\(%{NUMBER:[zeek][freq_score_v1]}, %{NUMBER:[zeek][freq_score_v2]}\)$" ] }
|
||||
}
|
||||
}
|
||||
}
|
||||
} # end if zeek_ssl.server_name
|
||||
|
||||
################################################################################################
|
||||
|
||||
######## JA3 community hashes lookup ###########################################################
|
||||
# ja3/ja3s are arrays at this point, as Arkime expects them to be
|
||||
|
||||
if ([tls][ja3]) and ([tls][ja3][0]) {
|
||||
translate {
|
||||
id => "translate_ssl_ja3"
|
||||
field => "[tls][ja3][0]"
|
||||
destination => "[zeek_ssl][ja3_desc]"
|
||||
dictionary_path => "/etc/ja3.yaml"
|
||||
}
|
||||
}
|
||||
|
||||
if ([tls][ja3s]) and ([tls][ja3s][0]) {
|
||||
translate {
|
||||
id => "translate_ssl_ja3s"
|
||||
field => "[tls][ja3s][0]"
|
||||
destination => "[zeek_ssl][ja3s_desc]"
|
||||
dictionary_path => "/etc/ja3.yaml"
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################################
|
||||
|
||||
# this identifies which node the log came from
|
||||
if ([host][name]) {
|
||||
mutate { id => "mutate_add_field_host_name_node"
|
||||
add_field => { "[node]" => "%{[host][name]}" } }
|
||||
} else {
|
||||
mutate { id => "mutate_add_field_logstash_node"
|
||||
add_field => { "[node]" => "logs" } }
|
||||
}
|
||||
|
||||
if ([log][file][path]) {
|
||||
# trim path portion of log.file.path
|
||||
mutate { id => "mutate_gsub_field_zeek_log_file_path"
|
||||
gsub => [ "[log][file][path]", "^.*/", "" ] }
|
||||
}
|
||||
|
||||
# remove some useless beats-related fields
|
||||
mutate {
|
||||
id => "mutate_remove_field_beats_useless"
|
||||
remove_field => [
|
||||
"[beat]",
|
||||
"[agent][ephemeral_id]",
|
||||
"[log][offset]",
|
||||
"[input][type]",
|
||||
"[prospector]",
|
||||
"[message]"
|
||||
]
|
||||
}
|
||||
|
||||
} # end Filter
|
||||
@@ -0,0 +1,79 @@
|
||||
filter {
|
||||
|
||||
# set data types for fields that belong to multiple types of logs
|
||||
# _dataconversion tag (for missing fields) will be removed in 18_tags_finalize.conf
|
||||
mutate {
|
||||
id => "mutate_convert_misc"
|
||||
convert => {
|
||||
"[certCnt]" => "integer"
|
||||
"[dhcp][hostCnt]" => "integer"
|
||||
"[dhcp][idCnt]" => "integer"
|
||||
"[dhcp][macCnt]" => "integer"
|
||||
"[dhcp][ouiCnt]" => "integer"
|
||||
"[dns][hostCnt]" => "integer"
|
||||
"[dns][ipCnt]" => "integer"
|
||||
"[dns][opcodeCnt]" => "integer"
|
||||
"[dns][qcCnt]" => "integer"
|
||||
"[dns][qtCnt]" => "integer"
|
||||
"[dstBytes]" => "integer"
|
||||
"[dstDataBytes]" => "integer"
|
||||
"[dstMacCnt]" => "integer"
|
||||
"[dstOuiCnt]" => "integer"
|
||||
"[dstPackets]" => "integer"
|
||||
"[dstPort]" => "integer"
|
||||
"[email][dstCnt]" => "integer"
|
||||
"[email][idCnt]" => "integer"
|
||||
"[email][srcCnt]" => "integer"
|
||||
"[email][subjectCnt]" => "integer"
|
||||
"[email][useragentCnt]" => "integer"
|
||||
"[email][smtpHelloCnt]" => "integer"
|
||||
"[firstPacket]" => "integer"
|
||||
"[http][bodyMagicCnt]" => "integer"
|
||||
"[http][clientVersionCnt]" => "integer"
|
||||
"[http][hostCnt]" => "integer"
|
||||
"[http][methodCnt]" => "integer"
|
||||
"[http][statuscodeCnt]" => "integer"
|
||||
"[http][uriCnt]" => "integer"
|
||||
"[http][useragentCnt]" => "integer"
|
||||
"[ipProtocol]" => "integer"
|
||||
"[irc][channelCnt]" => "integer"
|
||||
"[irc][nickCnt]" => "integer"
|
||||
"[krb5][cnameCnt]" => "integer"
|
||||
"[krb5][snameCnt]" => "integer"
|
||||
"[lastPacket]" => "integer"
|
||||
"[length]" => "integer"
|
||||
"[protocolCnt]" => "integer"
|
||||
"[quic][hostCnt]" => "integer"
|
||||
"[quic][useragentCnt]" => "integer"
|
||||
"[quic][versionCnt]" => "integer"
|
||||
"[radius][endpointegerIpCnt]" => "integer"
|
||||
"[radius][framedIpCnt]" => "integer"
|
||||
"[radius][macCnt]" => "integer"
|
||||
"[segmentCnt]" => "integer"
|
||||
"[srcBytes]" => "integer"
|
||||
"[srcDataBytes]" => "integer"
|
||||
"[srcMacCnt]" => "integer"
|
||||
"[srcOuiCnt]" => "integer"
|
||||
"[srcPackets]" => "integer"
|
||||
"[srcPort]" => "integer"
|
||||
"[ssh][hasshCnt]" => "integer"
|
||||
"[ssh][hasshServerCnt]" => "integer"
|
||||
"[ssh][keyCnt]" => "integer"
|
||||
"[ssh][versionCnt]" => "integer"
|
||||
"[timestamp]" => "integer"
|
||||
"[tls][cipherCnt]" => "integer"
|
||||
"[tls][ja3Cnt]" => "integer"
|
||||
"[tls][ja3sCnt]" => "integer"
|
||||
"[tls][versionCnt]" => "integer"
|
||||
"[totBytes]" => "integer"
|
||||
"[totDataBytes]" => "integer"
|
||||
"[totPackets]" => "integer"
|
||||
"[userCnt]" => "integer"
|
||||
"[vlan]" => "integer"
|
||||
"[vlanCnt]" => "integer"
|
||||
"[zeek][freq_score_v1]" => "float"
|
||||
"[zeek][freq_score_v2]" => "float"
|
||||
}
|
||||
}
|
||||
|
||||
} # end Filter
|
||||
@@ -0,0 +1,12 @@
|
||||
filter {
|
||||
|
||||
if ([zeek][resp_segment] and [zeek][orig_segment]) and
|
||||
([zeek][resp_segment] != [zeek][orig_segment]) {
|
||||
mutate {
|
||||
id => "mutate_add_tag_cross_segment"
|
||||
add_tag => [ "cross_segment" ]
|
||||
}
|
||||
}
|
||||
|
||||
} # filter
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
filter {
|
||||
|
||||
# remove tags we'd rather not see
|
||||
|
||||
mutate { id => "mutate_enrichment_tags_remove"
|
||||
remove_tag => [ "beats_input_codec_plain_applied",
|
||||
"_dateparsefailure",
|
||||
"_grokparsefailure",
|
||||
"_jsonparsefailure",
|
||||
"_dissectfailure",
|
||||
"_ouilookupfailure",
|
||||
"_geoip_lookup_failure" ] }
|
||||
|
||||
# deduplicate tags
|
||||
|
||||
ruby {
|
||||
id => "ruby_zeek_tags_deduplicate"
|
||||
code => "event.set('[tags]', event.get('[tags]').uniq)"
|
||||
}
|
||||
|
||||
# count tags (for moloch)
|
||||
|
||||
ruby {
|
||||
id => "ruby_enrichment_tagsCnt"
|
||||
code => "event.set('[tagsCnt]', event.get('[tags]').length)"
|
||||
}
|
||||
mutate {
|
||||
id => "mutate_convert_enrichment_tagsCnt"
|
||||
convert => { "[tagsCnt]" => "integer" }
|
||||
}
|
||||
|
||||
} # filter
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
filter {
|
||||
|
||||
# Map enriched 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.
|
||||
|
||||
# for now don't do anything unles an env explicitly enables it
|
||||
mutate {
|
||||
id => "mutate_add_field_env_logstash_enriched_to_ecs"
|
||||
add_field => { "[@metadata][ENV_LOGSTASH_ENRICHED_TO_ECS]" => "${LOGSTASH_TO_ECS:false}" }
|
||||
}
|
||||
if ([@metadata][ENV_LOGSTASH_ENRICHED_TO_ECS] == "true") {
|
||||
|
||||
# 🗹 Network - Fields describing the communication path over which the event happened. - https://www.elastic.co/guide/en/ecs/current/ecs-network.html
|
||||
|
||||
# network.direction (from tags assigned during 11_lookups.conf)
|
||||
if ("internal_source" in [tags]) and ("internal_destination" in [tags]) {
|
||||
mutate { id => "mutate_add_field_metadata_network_direction_internal"
|
||||
add_field => { "[@metadata][network_direction]" => "internal" } }
|
||||
} else if ("external_source" in [tags]) and ("external_destination" in [tags]) {
|
||||
mutate { id => "mutate_add_field_metadata_network_direction_external"
|
||||
add_field => { "[@metadata][network_direction]" => "external" } }
|
||||
} else if ("internal_source" in [tags]) and ("external_destination" in [tags]) {
|
||||
mutate { id => "mutate_add_field_metadata_network_direction_outbound"
|
||||
add_field => { "[@metadata][network_direction]" => "outbound" } }
|
||||
} else if ("external_source" in [tags]) and ("internal_destination" in [tags]) {
|
||||
mutate { id => "mutate_add_field_metadata_network_direction_inbound"
|
||||
add_field => { "[@metadata][network_direction]" => "inbound" } }
|
||||
}
|
||||
if ([@metadata][network_direction]) {
|
||||
mutate { id => "mutate_add_field_ecs_network_direction"
|
||||
add_field => { "[network][direction]" => "%{[@metadata][network_direction]}" } }
|
||||
}
|
||||
|
||||
# network.name (based on info from [zeek][resp_segment] and [zeek][orig_segment])
|
||||
if ([zeek][resp_segment]) { mutate { id => "mutate_add_field_ecs_network_name_resp"
|
||||
merge => { "[network][name]" => "[zeek][resp_segment]" } } }
|
||||
if ([zeek][orig_segment]) { mutate { id => "mutate_add_field_ecs_network_name_orig"
|
||||
merge => { "[network][name]" => "[zeek][orig_segment]" } } }
|
||||
|
||||
# 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
|
||||
|
||||
# ecs.version is required in all events - https://www.elastic.co/guide/en/ecs/current/ecs-ecs.html
|
||||
if (![ecs][version]) { mutate { id => "mutate_add_field_ecs_version"
|
||||
add_field => { "[ecs][version]" => "1.5.0" } } }
|
||||
|
||||
# event.ingested
|
||||
if (![event][ingested]) {
|
||||
ruby {
|
||||
id => "ruby_event_ingested_now_zeek"
|
||||
init => "require 'time'"
|
||||
code => "event.set('[event][ingested]', Time.now.to_f)"
|
||||
}
|
||||
date {
|
||||
id => "date_event_ingested_conv"
|
||||
match => [ "[event][ingested]", "UNIX" ]
|
||||
target => "[event][ingested]"
|
||||
}
|
||||
}
|
||||
|
||||
# event.provider
|
||||
if (![event][provider]) { mutate { id => "mutate_add_field_event_provider_enrichment"
|
||||
add_field => { "[event][provider]" => "malcolm" } } }
|
||||
|
||||
} # end if ENV_LOGSTASH_ENRICHED_TO_ECS
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
output {
|
||||
pipeline {
|
||||
send_to => [_MALCOLM_ELASTICSEARCH_OUTPUT_PIPELINES_]
|
||||
}
|
||||
}
|
||||
3
Vagrant/resources/malcolm/logstash/pipelines/external/00_config.conf
vendored
Normal file
3
Vagrant/resources/malcolm/logstash/pipelines/external/00_config.conf
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
queue.type: persisted
|
||||
queue.max_bytes: 4gb
|
||||
path.queue: "/logstash-persistent-queue"
|
||||
6
Vagrant/resources/malcolm/logstash/pipelines/external/01_input_external_es.conf
vendored
Normal file
6
Vagrant/resources/malcolm/logstash/pipelines/external/01_input_external_es.conf
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
input {
|
||||
pipeline {
|
||||
address => "${ELASTICSEARCH_PIPELINE_ADDRESS_EXTERNAL:external-es}"
|
||||
}
|
||||
}
|
||||
|
||||
13
Vagrant/resources/malcolm/logstash/pipelines/external/99_elastic_output.conf
vendored
Normal file
13
Vagrant/resources/malcolm/logstash/pipelines/external/99_elastic_output.conf
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
output {
|
||||
elasticsearch {
|
||||
id => "output_external_elasticsearch_moloch"
|
||||
hosts => "${ES_EXTERNAL_HOSTS}"
|
||||
ssl => "${ES_EXTERNAL_SSL:true}"
|
||||
ssl_certificate_verification => "${ES_EXTERNAL_SSL_CERTIFICATE_VERIFICATION:false}"
|
||||
user => "${ES_EXTERNAL_USER:}"
|
||||
password => "${ES_EXTERNAL_PASSWORD:}"
|
||||
manage_template => false
|
||||
index => "sessions2-%{+YYMMdd}"
|
||||
document_id => "%{+YYMMdd}-%{zeekLogDocId}"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
input {
|
||||
beats {
|
||||
id => "input_beats"
|
||||
host => "0.0.0.0"
|
||||
port => 5044
|
||||
ssl => "${BEATS_SSL:false}"
|
||||
ssl_certificate_authorities => ["/certs/ca.crt"]
|
||||
ssl_certificate => "/certs/server.crt"
|
||||
ssl_key => "/certs/server.key"
|
||||
ssl_verify_mode => "none"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
output {
|
||||
pipeline {
|
||||
send_to => [_MALCOLM_PARSE_PIPELINE_ADDRESSES_]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
input {
|
||||
pipeline {
|
||||
address => "${ELASTICSEARCH_PIPELINE_ADDRESS_INTERNAL:internal-es}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
output {
|
||||
elasticsearch {
|
||||
id => "output_elasticsearch_moloch"
|
||||
hosts => "${ES_HOSTS:elasticsearch:9200}"
|
||||
manage_template => false
|
||||
index => "sessions2-%{+YYMMdd}"
|
||||
document_id => "%{+YYMMdd}-%{zeekLogDocId}"
|
||||
}
|
||||
}
|
||||
@@ -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