Skip to content

Commit

Permalink
work on idaholab#19, assigning severity to certain types of events
Browse files Browse the repository at this point in the history
  • Loading branch information
mmguero committed Aug 17, 2021
1 parent 9bf3991 commit dbef81a
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 32 deletions.
3 changes: 1 addition & 2 deletions logstash/maps/malcolm_event_categories_severity.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
"CONNECTION_INBOUND": 50
"CONNECTION_INTERNAL": 0
"CONNECTION_OUTBOUND": 25
"DGA_HIGH_ENTROPY": 40
"FILE_TYPE": 10
"FILE_TYPE": 5
"FILE_TYPE_HIGH": 75
"FILE_TYPE_MEDIUM": 50
"NOTICE_VULN": 90
Expand Down
110 changes: 80 additions & 30 deletions logstash/pipelines/enrichment/19_severity.conf
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
filter {

# see malcolm_event_categories_severity.yaml for mappings to severity scores

# identify cross-segment traffic based on previously-populated tag
if ("cross_segment" in [tags]) {
mutate { id => "mutate_add_field_severity_item_cross_segment"
add_field => { "[zeek][severity_tags]" => "CONNECTION_CROSS_SEGMENT" } }
add_field => { "[event][severity_tags]" => "CONNECTION_CROSS_SEGMENT" } }
}

# inbound/outbound/internal/external connection based on previously-populated tag
if ("internal_source" in [tags]) and ("internal_destination" in [tags]) {
mutate { id => "mutate_add_field_severity_item_internal"
add_field => { "[zeek][severity_tags]" => "CONNECTION_INTERNAL" } }
add_field => { "[event][severity_tags]" => "CONNECTION_INTERNAL" } }
} else if ("external_source" in [tags]) and ("external_destination" in [tags]) {
mutate { id => "mutate_add_field_severity_item_external"
add_field => { "[zeek][severity_tags]" => "CONNECTION_EXTERNAL" } }
add_field => { "[event][severity_tags]" => "CONNECTION_EXTERNAL" } }
} else if ("internal_source" in [tags]) and ("external_destination" in [tags]) {
mutate { id => "mutate_add_field_severity_item_outbound"
add_field => { "[zeek][severity_tags]" => "CONNECTION_OUTBOUND" } }
add_field => { "[event][severity_tags]" => "CONNECTION_OUTBOUND" } }
} else if ("external_source" in [tags]) and ("internal_destination" in [tags]) {
mutate { id => "mutate_add_field_severity_item_inbound"
add_field => { "[zeek][severity_tags]" => "CONNECTION_INBOUND" } }
add_field => { "[event][severity_tags]" => "CONNECTION_INBOUND" } }
}

# these (high/medium) file types pulled from extractor_override.interesting.zeek
# and probably ought to be modified if that file is modified
if ([zeek][filetype]) {
# these (high/medium) file types pulled from extractor_override.interesting.zeek

# "high" severity files are executables and scripts (?)
if (("application/PowerShell" in [zeek][filetype]) or
("application/vnd.microsoft.portable-executable" in [zeek][filetype]) or
("application/x-csh" in [zeek][filetype]) or
Expand All @@ -35,7 +42,9 @@ filter {
("application/x-sh" in [zeek][filetype]) or
("text/vbscript" in [zeek][filetype])) {
mutate { id => "mutate_add_field_severity_file_type_high"
add_field => { "[zeek][severity_tags]" => "FILE_TYPE_HIGH" } }
add_field => { "[event][severity_tags]" => "FILE_TYPE_HIGH" } }

# "medium" severity files are everything else in the "interesting" list
} else if (("application/binary" in [zeek][filetype]) or
("application/ecmascript" in [zeek][filetype]) or
("application/hta" in [zeek][filetype]) or
Expand Down Expand Up @@ -119,70 +128,85 @@ filter {
("text/jscript" in [zeek][filetype]) or
("text/rtf" in [zeek][filetype])) {
mutate { id => "mutate_add_field_severity_file_type_medium"
add_field => { "[zeek][severity_tags]" => "FILE_TYPE_MEDIUM" } }
add_field => { "[event][severity_tags]" => "FILE_TYPE_MEDIUM" } }

# "low" severity files are other file transfers
} else {
mutate { id => "mutate_add_field_severity_file_type"
add_field => { "[zeek][severity_tags]" => "FILE_TYPE" } }
add_field => { "[event][severity_tags]" => "FILE_TYPE" } }
}
}

# assign severity to notice based on category
if ([zeek_notice]) {
if ([zeek_notice][category] == "ATTACK") {
mutate { id => "mutate_add_field_severity_notice_mitre_attack"
add_field => { "[zeek][severity_tags]" => "NOTICE_MITRE_ATTACK" } }
add_field => { "[event][severity_tags]" => "NOTICE_MITRE_ATTACK" } }
} else if ([zeek_notice][category] == "Scan") {
mutate { id => "mutate_add_field_severity_notice_scan"
add_field => { "[zeek][severity_tags]" => "NOTICE_SCAN" } }
add_field => { "[event][severity_tags]" => "NOTICE_SCAN" } }
} else if (([zeek_notice][category] == "FTP") or
([zeek_notice][category] == "HTTP") or
([zeek_notice][category] == "HTTPATTACKS") or
([zeek_notice][category] == "SSL")) {
mutate { id => "mutate_add_field_severity_notice_protocol"
add_field => { "[zeek][severity_tags]" => "NOTICE_PROTOCOL" } }
add_field => { "[event][severity_tags]" => "NOTICE_PROTOCOL" } }
} else if (([zeek_notice][category] =~ /^CVE/) or
([zeek_notice][category] == "EternalSafety") or
([zeek_notice][category] == "Ripple20") or
([zeek_notice][category] == "Zerologon")) {
mutate { id => "mutate_add_field_severity_notice_vuln"
add_field => { "[zeek][severity_tags]" => "NOTICE_VULN" } }
add_field => { "[event][severity_tags]" => "NOTICE_VULN" } }
} else {
mutate { id => "mutate_add_field_severity_notice_other"
add_field => { "[zeek][severity_tags]" => "NOTICE_OTHER" } }
add_field => { "[event][severity_tags]" => "NOTICE_OTHER" } }
}
}

# weird logs get one score at the moment
if ([zeek_weird]) {
mutate { id => "mutate_add_field_severity_weird_other"
add_field => { "[zeek][severity_tags]" => "WEIRD_OTHER" } }
add_field => { "[event][severity_tags]" => "WEIRD_OTHER" } }
}

# if zeek.password exists, it's assumed to be in cleartext
if ([zeek][password]) {
mutate { id => "mutate_add_field_severity_password_exists"
add_field => { "[zeek][severity_tags]" => "PASSWORD_CLEARTEXT" } }
add_field => { "[event][severity_tags]" => "PASSWORD_CLEARTEXT" } }
}

# assign score to signatures based on engine
if ([zeek_signatures]) {
if ([zeek_signatures][engine] == 'capa') {
mutate { id => "mutate_add_field_severity_signatures_capa"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_CAPA" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_CAPA" } }
} else if ([zeek_signatures][engine] == 'clamav') {
mutate { id => "mutate_add_field_severity_signatures_clamav"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_CLAMAV" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_CLAMAV" } }
} else if ([zeek_signatures][engine] == 'malass') {
mutate { id => "mutate_add_field_severity_signatures_malass"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_MALASS" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_MALASS" } }
} else if ([zeek_signatures][engine] == 'virustotal') {
mutate { id => "mutate_add_field_severity_signatures_virustotal"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_VIRUSTOTAL" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_VIRUSTOTAL" } }
} else if ([zeek_signatures][engine] == 'yara') {
mutate { id => "mutate_add_field_severity_signatures_yara"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_YARA" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_YARA" } }
} else {
mutate { id => "mutate_add_field_severity_signatures_other"
add_field => { "[zeek][severity_tags]" => "SIGNATURES_OTHER" } }
add_field => { "[event][severity_tags]" => "SIGNATURES_OTHER" } }
}
}

# insecure/outdated protocols requires a little bit more code than logstash can do
# so we'll do it in Ruby. at the moment these are mirroring what's in the
# Security Overview (95479950-41f2-11ea-88fa-7151df485405) dashboard, so they
# probably should be kept up-to-date with that.
#
# in addition to insecure/outdated protocols, append PROTOCOL_XXX to the
# severity_tags list, where XXX is the uppercased value of zeek.service,
# so that if the user wants to add PROTOCOL_SSH or whatever to their mapping
# for a custom severity value it will just work
if (!([zeek][logType] =~ /^known/)) {
ruby {
id => "ruby_add_field_severity_insecure_protocols"
Expand Down Expand Up @@ -224,21 +248,47 @@ filter {
end
end
end
sevtags = Array.new unless (sevtags = event.get('[event][severity_tags]'))
if !sevtags.kind_of?(Array) then
newtags = Array.new
newtags.push(sevtags)
sevtags = newtags
end
if found > 0 then
sevtags = Array.new unless (sevtags = event.get('[zeek][severity_tags]'))
if !sevtags.kind_of?(Array) then
newtags = Array.new
newtags.push(sevtags)
sevtags = newtags
end
sevtags.push('PROTOCOL_OUTDATED_OR_INSECURE')
event.set('[zeek][severity_tags]', sevtags)
end
sevtags.push(*service.map{|x| 'PROTOCOL_' + x.upcase})
event.set('[event][severity_tags]', sevtags)
end"
}
}

# "DGA_HIGH_ENTROPY": 40
ruby {
id => "ruby_calculate_final_severity_score"
# pre-load severity score mapping in init outside of processing pipeline
init => "
require 'yaml'; $severityMappings = YAML.load(File.read('/etc/malcolm_event_categories_severity.yaml'))
"
# to calculate severity:
# - look up list of severity_tags against severity score mapping (generate hash), ignoring <= 0 or missing (nil) values
# - set summed severity scores in event.severity
# - set pruned severity_tags back to event.severity_tags
code => "
sevtags = event.get('[event][severity_tags]')
if !sevtags.nil? and !sevtags.kind_of?(Array) then
tagsarr = Array.new
tagsarr.push(sevtags)
sevtags = tagsarr
end
if !sevtags.nil? and (sevtags.length > 0) and ($severityMappings.length > 0) then
sevhash = Hash[sevtags.select{|key| ($severityMappings[key].nil? ? 0 : $severityMappings[key]) > 0}.map{|key| [key, $severityMappings[key]]}]
event.set('[event][severity_tags]', sevhash.keys)
event.set('[event][severity]', [sevhash.values.sum, 100].min)
end"
}




} # filter

0 comments on commit dbef81a

Please sign in to comment.