From 8314b18092e217a66441d4cd98b0480dc35bc2fe Mon Sep 17 00:00:00 2001 From: Mohan Dhawan Date: Thu, 24 Apr 2025 23:24:40 +0530 Subject: [PATCH 1/2] Add fine-grained groups for Intel events --- scripts/policy/frameworks/intel/seen/dns.zeek | 2 +- .../frameworks/intel/seen/file-hashes.zeek | 2 +- .../frameworks/intel/seen/file-names.zeek | 10 +- .../frameworks/intel/seen/http-headers.zeek | 104 ++++++++++-------- .../frameworks/intel/seen/http-url.zeek | 2 +- .../frameworks/intel/seen/pubkey-hashes.zeek | 2 +- .../frameworks/intel/seen/smb-filenames.zeek | 2 +- .../intel/seen/smtp-url-extraction.zeek | 4 +- .../policy/frameworks/intel/seen/smtp.zeek | 28 ++++- scripts/policy/frameworks/intel/seen/ssl.zeek | 4 +- .../policy/frameworks/intel/seen/x509.zeek | 9 +- 11 files changed, 104 insertions(+), 65 deletions(-) diff --git a/scripts/policy/frameworks/intel/seen/dns.zeek b/scripts/policy/frameworks/intel/seen/dns.zeek index 9218586c95..cfc5a6a6c3 100644 --- a/scripts/policy/frameworks/intel/seen/dns.zeek +++ b/scripts/policy/frameworks/intel/seen/dns.zeek @@ -1,7 +1,7 @@ @load base/frameworks/intel @load ./where-locations -event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) +event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) &group="Intel::DOMAIN" { Intel::seen([$indicator=query, $indicator_type=Intel::DOMAIN, diff --git a/scripts/policy/frameworks/intel/seen/file-hashes.zeek b/scripts/policy/frameworks/intel/seen/file-hashes.zeek index e3295c5609..701c0cc254 100644 --- a/scripts/policy/frameworks/intel/seen/file-hashes.zeek +++ b/scripts/policy/frameworks/intel/seen/file-hashes.zeek @@ -1,7 +1,7 @@ @load base/frameworks/intel @load ./where-locations -event file_hash(f: fa_file, kind: string, hash: string) +event file_hash(f: fa_file, kind: string, hash: string) &group="Intel::FILE_HASH" { local seen = Intel::Seen($indicator=hash, $indicator_type=Intel::FILE_HASH, diff --git a/scripts/policy/frameworks/intel/seen/file-names.zeek b/scripts/policy/frameworks/intel/seen/file-names.zeek index 10c563f05e..3280822cf8 100644 --- a/scripts/policy/frameworks/intel/seen/file-names.zeek +++ b/scripts/policy/frameworks/intel/seen/file-names.zeek @@ -1,7 +1,7 @@ @load base/frameworks/intel @load ./where-locations -event file_new(f: fa_file) +event file_new(f: fa_file) &group="Intel::FILE_NAME" { # If there are connections attached, we'll be using # file_over_new_connection() for reporting the @@ -16,11 +16,11 @@ event file_new(f: fa_file) $where=Files::IN_NAME]); } -event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=-5 +event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) &priority=-5 &group="Intel::FILE_NAME" { - # Skip SMB, there's a custom implementation in smb-filenames.zeek - if ( f$source == "SMB" ) - return; + # Skip SMB, there's a custom implementation in smb-filenames.zeek + if ( f$source == "SMB" ) + return; if ( f?$info && f$info?$filename ) Intel::seen([$indicator=f$info$filename, diff --git a/scripts/policy/frameworks/intel/seen/http-headers.zeek b/scripts/policy/frameworks/intel/seen/http-headers.zeek index 066d10c0fc..75116be923 100644 --- a/scripts/policy/frameworks/intel/seen/http-headers.zeek +++ b/scripts/policy/frameworks/intel/seen/http-headers.zeek @@ -2,54 +2,72 @@ @load ./where-locations @load base/utils/addrs -event http_header(c: connection, is_orig: bool, name: string, value: string) +event http_header(c: connection, is_orig: bool, name: string, value: string) &group="Intel::ADDR" { - if ( is_orig ) + if ( ! is_orig ) + return; + + switch ( name ) { - switch ( name ) + case "HOST": + # Remove the occasional port value that shows up here. + local host = gsub(value, /:[[:digit:]]+$/, ""); + if ( is_valid_ip(host) ) + Intel::seen([$host=to_addr(host), + $indicator_type=Intel::ADDR, + $conn=c, + $where=HTTP::IN_HOST_HEADER]); + break; + + case "X-FORWARDED-FOR": + if ( is_valid_ip(value) ) { - case "HOST": - # Remove the occasional port value that shows up here. - local host = gsub(value, /:[[:digit:]]+$/, ""); - if ( is_valid_ip(host) ) - Intel::seen([$host=to_addr(host), - $indicator_type=Intel::ADDR, - $conn=c, - $where=HTTP::IN_HOST_HEADER]); - else - Intel::seen([$indicator=host, - $indicator_type=Intel::DOMAIN, - $conn=c, - $where=HTTP::IN_HOST_HEADER]); - break; - - case "REFERER": - Intel::seen([$indicator=sub(value, /^.*:\/\//, ""), - $indicator_type=Intel::URL, - $conn=c, - $where=HTTP::IN_REFERRER_HEADER]); - break; - - case "X-FORWARDED-FOR": - if ( is_valid_ip(value) ) + local addrs = extract_ip_addresses(value); + for ( i in addrs ) { - local addrs = extract_ip_addresses(value); - for ( i in addrs ) - { - Intel::seen([$host=to_addr(addrs[i]), - $indicator_type=Intel::ADDR, - $conn=c, - $where=HTTP::IN_X_FORWARDED_FOR_HEADER]); - } + Intel::seen([$host=to_addr(addrs[i]), + $indicator_type=Intel::ADDR, + $conn=c, + $where=HTTP::IN_X_FORWARDED_FOR_HEADER]); } - break; - - case "USER-AGENT": - Intel::seen([$indicator=value, - $indicator_type=Intel::SOFTWARE, - $conn=c, - $where=HTTP::IN_USER_AGENT_HEADER]); - break; } + break; } } + +event http_header(c: connection, is_orig: bool, name: string, value: string) &group="Intel::DOMAIN" + { + if ( ! is_orig || name != "HOST" ) + return; + + # Remove the occasional port value that shows up here. + local host = gsub(value, /:[[:digit:]]+$/, ""); + if ( ! is_valid_ip(host) ) + Intel::seen([$indicator=host, + $indicator_type=Intel::DOMAIN, + $conn=c, + $where=HTTP::IN_HOST_HEADER]); + } + + +event http_header(c: connection, is_orig: bool, name: string, value: string) &group="Intel::URL" + { + if ( ! is_orig || name != "REFERER" ) + return; + + Intel::seen([$indicator=sub(value, /^.*:\/\//, ""), + $indicator_type=Intel::URL, + $conn=c, + $where=HTTP::IN_REFERRER_HEADER]); + } + +event http_header(c: connection, is_orig: bool, name: string, value: string) &group="Intel::SOFTWARE" + { + if ( ! is_orig || name != "USER-AGENT" ) + return; + + Intel::seen([$indicator=value, + $indicator_type=Intel::SOFTWARE, + $conn=c, + $where=HTTP::IN_USER_AGENT_HEADER]); + } diff --git a/scripts/policy/frameworks/intel/seen/http-url.zeek b/scripts/policy/frameworks/intel/seen/http-url.zeek index 340ae3c5ab..9611cb1e8e 100644 --- a/scripts/policy/frameworks/intel/seen/http-url.zeek +++ b/scripts/policy/frameworks/intel/seen/http-url.zeek @@ -2,7 +2,7 @@ @load base/protocols/http/utils @load ./where-locations -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) +event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &group="Intel::URL" { if ( is_orig && c?$http ) Intel::seen([$indicator=HTTP::build_url(c$http), diff --git a/scripts/policy/frameworks/intel/seen/pubkey-hashes.zeek b/scripts/policy/frameworks/intel/seen/pubkey-hashes.zeek index b6471e811b..1fcc426c24 100644 --- a/scripts/policy/frameworks/intel/seen/pubkey-hashes.zeek +++ b/scripts/policy/frameworks/intel/seen/pubkey-hashes.zeek @@ -2,7 +2,7 @@ @load base/protocols/ssh @load ./where-locations -event ssh_server_host_key(c: connection, hash: string) +event ssh_server_host_key(c: connection, hash: string) &group="Intel::PUBKEY_HASH" { local seen = Intel::Seen($indicator=hash, $indicator_type=Intel::PUBKEY_HASH, diff --git a/scripts/policy/frameworks/intel/seen/smb-filenames.zeek b/scripts/policy/frameworks/intel/seen/smb-filenames.zeek index 66c8977bb0..6009959d2e 100644 --- a/scripts/policy/frameworks/intel/seen/smb-filenames.zeek +++ b/scripts/policy/frameworks/intel/seen/smb-filenames.zeek @@ -2,7 +2,7 @@ @load base/frameworks/intel @load ./where-locations -event file_new(f: fa_file) +event file_new(f: fa_file) &group="Intel::FILE_NAME" { if ( f$source != "SMB" ) return; diff --git a/scripts/policy/frameworks/intel/seen/smtp-url-extraction.zeek b/scripts/policy/frameworks/intel/seen/smtp-url-extraction.zeek index 343beb277e..c0a21d5d8c 100644 --- a/scripts/policy/frameworks/intel/seen/smtp-url-extraction.zeek +++ b/scripts/policy/frameworks/intel/seen/smtp-url-extraction.zeek @@ -3,7 +3,7 @@ @load base/utils/urls @load ./where-locations -event intel_mime_data(f: fa_file, data: string) +event intel_mime_data(f: fa_file, data: string) &group="Intel::URL" { if ( ! f?$conns ) return; @@ -21,7 +21,7 @@ event intel_mime_data(f: fa_file, data: string) } } -event file_new(f: fa_file) +event file_new(f: fa_file) &group="Intel::URL" { if ( f$source == "SMTP" ) Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, [$stream_event=intel_mime_data]); diff --git a/scripts/policy/frameworks/intel/seen/smtp.zeek b/scripts/policy/frameworks/intel/seen/smtp.zeek index 268928b57d..0ae9e82269 100644 --- a/scripts/policy/frameworks/intel/seen/smtp.zeek +++ b/scripts/policy/frameworks/intel/seen/smtp.zeek @@ -17,18 +17,36 @@ event mime_end_entity(c: connection) $where=SMTP::IN_RECEIVED_HEADER]); } } + } + } +event mime_end_entity(c: connection) &group="Intel::ADDR" + { + if ( c?$smtp ) + { + if ( c$smtp?$x_originating_ip ) + Intel::seen([$host=c$smtp$x_originating_ip, + $conn=c, + $where=SMTP::IN_X_ORIGINATING_IP_HEADER]); + } + } + +event mime_end_entity(c: connection) &group="Intel::SOFTWARE" + { + if ( c?$smtp ) + { if ( c$smtp?$user_agent ) Intel::seen([$indicator=c$smtp$user_agent, $indicator_type=Intel::SOFTWARE, $conn=c, $where=SMTP::IN_HEADER]); + } + } - if ( c$smtp?$x_originating_ip ) - Intel::seen([$host=c$smtp$x_originating_ip, - $conn=c, - $where=SMTP::IN_X_ORIGINATING_IP_HEADER]); - +event mime_end_entity(c: connection) &group="Intel::EMAIL" + { + if ( c?$smtp ) + { if ( c$smtp?$mailfrom ) { Intel::seen([$indicator=c$smtp$mailfrom, diff --git a/scripts/policy/frameworks/intel/seen/ssl.zeek b/scripts/policy/frameworks/intel/seen/ssl.zeek index 5d386a5bc7..8b00d0720f 100644 --- a/scripts/policy/frameworks/intel/seen/ssl.zeek +++ b/scripts/policy/frameworks/intel/seen/ssl.zeek @@ -2,7 +2,7 @@ @load base/protocols/ssl @load ./where-locations -event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) +event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) &group="Intel::DOMAIN" { if ( is_orig && c?$ssl && c$ssl?$server_name ) Intel::seen([$indicator=c$ssl$server_name, @@ -11,7 +11,7 @@ event ssl_extension_server_name(c: connection, is_orig: bool, names: string_vec) $where=SSL::IN_SERVER_NAME]); } -event ssl_established(c: connection) +event ssl_established(c: connection) &group="Intel::DOMAIN" { if ( ! c$ssl?$cert_chain || |c$ssl$cert_chain| == 0 || ! c$ssl$cert_chain[0]?$x509 ) diff --git a/scripts/policy/frameworks/intel/seen/x509.zeek b/scripts/policy/frameworks/intel/seen/x509.zeek index deb7c23ab0..335a459a9b 100644 --- a/scripts/policy/frameworks/intel/seen/x509.zeek +++ b/scripts/policy/frameworks/intel/seen/x509.zeek @@ -9,7 +9,7 @@ export { option enable_x509_ext_subject_alternative_name = T; } -event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) +event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativeName) &group="Intel::DOMAIN" { if ( enable_x509_ext_subject_alternative_name && ext?$dns ) { @@ -21,7 +21,7 @@ event x509_ext_subject_alternative_name(f: fa_file, ext: X509::SubjectAlternativ } } -event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) +event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &group="Intel::EMAIL" { if ( /emailAddress=/ in cert$subject ) { @@ -32,7 +32,10 @@ event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certifi $f=f, $where=X509::IN_CERT]); } + } +event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certificate) &group="Intel::CERT_HASH" + { if ( f$info?$sha1 ) # if the file_hash event was raised before the x509 event... { Intel::seen([$indicator=f$info$sha1, @@ -42,7 +45,7 @@ event x509_certificate(f: fa_file, cert_ref: opaque of x509, cert: X509::Certifi } } -event file_hash(f: fa_file, kind: string, hash: string) +event file_hash(f: fa_file, kind: string, hash: string) &group="Intel::CERT_HASH" { if ( ! f?$info || ! f$info?$x509 || kind != "sha1" ) return; From 36c4d112c8dd723b91bc187abfa2a7db3464a52a Mon Sep 17 00:00:00 2001 From: Mohan Dhawan Date: Tue, 29 Apr 2025 16:30:31 +0530 Subject: [PATCH 2/2] coalesce smtp handlers for ADDR --- scripts/policy/frameworks/intel/seen/smtp.zeek | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/scripts/policy/frameworks/intel/seen/smtp.zeek b/scripts/policy/frameworks/intel/seen/smtp.zeek index 0ae9e82269..940278cb9d 100644 --- a/scripts/policy/frameworks/intel/seen/smtp.zeek +++ b/scripts/policy/frameworks/intel/seen/smtp.zeek @@ -3,7 +3,7 @@ @load base/protocols/smtp @load ./where-locations -event mime_end_entity(c: connection) +event mime_end_entity(c: connection) &group="Intel::ADDR" { if ( c?$smtp ) { @@ -17,13 +17,7 @@ event mime_end_entity(c: connection) $where=SMTP::IN_RECEIVED_HEADER]); } } - } - } -event mime_end_entity(c: connection) &group="Intel::ADDR" - { - if ( c?$smtp ) - { if ( c$smtp?$x_originating_ip ) Intel::seen([$host=c$smtp$x_originating_ip, $conn=c,