diff --git a/scripts/base/protocols/dns/main.zeek b/scripts/base/protocols/dns/main.zeek index b8cb2b80b5..3906ab5cf0 100644 --- a/scripts/base/protocols/dns/main.zeek +++ b/scripts/base/protocols/dns/main.zeek @@ -456,6 +456,21 @@ event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, strs: string_v hook DNS::do_reply(c, msg, ans, txt_strings); } +event dns_SPF_reply(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec) &priority=5 + { + local spf_strings: string = ""; + + for ( i in strs ) + { + if ( i > 0 ) + spf_strings += " "; + + spf_strings += fmt("SPF %d %s", |strs[i]|, strs[i]); + } + + hook DNS::do_reply(c, msg, ans, spf_strings); + } + event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5 { hook DNS::do_reply(c, msg, ans, fmt("%s", a)); diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index c9e2c61cd7..51a8d1cec3 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -281,6 +281,10 @@ int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg, status = ParseRR_TXT(msg, data, len, rdlength, msg_start); break; + case TYPE_SPF: + status = ParseRR_SPF(msg, data, len, rdlength, msg_start); + break; + case TYPE_CAA: status = ParseRR_CAA(msg, data, len, rdlength, msg_start); break; @@ -1321,6 +1325,36 @@ int DNS_Interpreter::ParseRR_TXT(DNS_MsgInfo* msg, return rdlength == 0; } +int DNS_Interpreter::ParseRR_SPF(DNS_MsgInfo* msg, + const u_char*& data, int& len, int rdlength, + const u_char* msg_start) + { + if ( ! dns_SPF_reply || msg->skip_event ) + { + data += rdlength; + len -= rdlength; + return 1; + } + + VectorVal* char_strings = new VectorVal(string_vec); + StringVal* char_string; + + while ( (char_string = extract_char_string(analyzer, data, len, rdlength)) ) + char_strings->Assign(char_strings->Size(), char_string); + + if ( dns_SPF_reply ) + analyzer->ConnectionEventFast(dns_SPF_reply, { + analyzer->BuildConnVal(), + msg->BuildHdrVal(), + msg->BuildAnswerVal(), + char_strings, + }); + else + Unref(char_strings); + + return rdlength == 0; + } + int DNS_Interpreter::ParseRR_CAA(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, const u_char* msg_start) diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index a4975cdaa1..8a82768ce0 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -63,6 +63,8 @@ typedef enum { TYPE_DNSKEY = 48, ///< DNS Key record (RFC 4034) TYPE_DS = 43, ///< Delegation signer (RFC 4034) TYPE_NSEC3 = 50, + // Obsoleted + TYPE_SPF = 99, ///< Alternative: storing SPF data in TXT records, using the same format (RFC 4408). Support for it was discontinued in RFC 7208 // The following are only valid in queries. TYPE_AXFR = 252, TYPE_ALL = 255, @@ -282,6 +284,9 @@ protected: int ParseRR_TXT(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, const u_char* msg_start); + int ParseRR_SPF(DNS_MsgInfo* msg, + const u_char*& data, int& len, int rdlength, + const u_char* msg_start); int ParseRR_CAA(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength, const u_char* msg_start); diff --git a/src/analyzer/protocol/dns/events.bif b/src/analyzer/protocol/dns/events.bif index ae57219775..7ddbd0c7b3 100644 --- a/src/analyzer/protocol/dns/events.bif +++ b/src/analyzer/protocol/dns/events.bif @@ -15,7 +15,7 @@ ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end ## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_query_reply dns_rejected ## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -42,7 +42,7 @@ event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end ## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -71,7 +71,7 @@ event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qcl ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end ## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -97,7 +97,7 @@ event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qc ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end ## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_rejected ## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -123,7 +123,7 @@ event dns_query_reply%(c: connection, msg: dns_msg, query: string, ## ## .. zeek:see:: dns_AAAA_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply ## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -148,7 +148,7 @@ event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); ## ## .. zeek:see:: dns_A_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply ## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered ## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified ## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request ## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -173,7 +173,7 @@ event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); ## ## .. zeek:see:: dns_A_reply dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply ## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered ## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified ## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request ## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -198,7 +198,7 @@ event dns_A6_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -223,7 +223,7 @@ event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply ## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered ## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified ## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request ## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -248,7 +248,7 @@ event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: strin ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -273,7 +273,7 @@ event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string% ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -296,7 +296,7 @@ event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa% ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_end dns_full_request +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -319,7 +319,7 @@ event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_MX_reply ## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered ## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified ## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request ## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -346,7 +346,7 @@ event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -378,6 +378,31 @@ event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, ## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec%); +## Generated for DNS replies of type *SPF*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Zeek analyzes both UDP and TCP DNS +## sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## strs: The textual information returned by the reply. +## +## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_SPF_reply%(c: connection, msg: dns_msg, ans: dns_answer, strs: string_vec%); + ## Generated for DNS replies of type *CAA* (Certification Authority Authorization). ## For replies with multiple answers, an individual event of the corresponding type ## is raised for each. @@ -425,7 +450,7 @@ event dns_CAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, flags: count, ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -444,7 +469,7 @@ event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer, target: strin ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_SRV_reply dns_end +## dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_SRV_reply dns_end event dns_unknown_reply%(c: connection, msg: dns_msg, ans: dns_answer%); ## Generated for DNS replies of type *EDNS*. For replies with multiple answers, @@ -463,7 +488,7 @@ event dns_unknown_reply%(c: connection, msg: dns_msg, ans: dns_answer%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply ## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl -## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered ## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified ## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request ## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl @@ -486,7 +511,7 @@ event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_SRV_reply dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_end dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout @@ -575,7 +600,7 @@ event dns_DS%(c: connection, msg: dns_msg, ans: dns_answer, ds: dns_ds_rr%); ## ## .. zeek:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl ## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply -## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_full_request +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_SPF_reply dns_WKS_reply dns_full_request ## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name ## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply ## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.spf/dns.log b/testing/btest/Baseline/scripts.base.protocols.dns.spf/dns.log new file mode 100644 index 0000000000..ebec6a3979 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dns.spf/dns.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#open 2019-06-14-15-15-00 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id rtt query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected +#types time string addr port addr port enum count interval string count string count string count string bool bool bool bool count vector[string] vector[interval] bool +1560524739.386971 CHhAvVGS1DHFjwGM9 10.91.0.62 57806 10.91.1.59 53 udp 64161 - mail.vladg.net - - - - 0 NOERROR F F F T 0 SPF 19 v=spf1 mx -all test,SPF 14 v=spf1 mx -all 300.000000,300.000000 F +#close 2019-06-14-15-15-00 diff --git a/testing/btest/Traces/dns-spf.pcap b/testing/btest/Traces/dns-spf.pcap new file mode 100644 index 0000000000..4781bcd416 Binary files /dev/null and b/testing/btest/Traces/dns-spf.pcap differ diff --git a/testing/btest/scripts/base/protocols/dns/spf.zeek b/testing/btest/scripts/base/protocols/dns/spf.zeek new file mode 100644 index 0000000000..14d743cb1d --- /dev/null +++ b/testing/btest/scripts/base/protocols/dns/spf.zeek @@ -0,0 +1,4 @@ +# @TEST-EXEC: zeek -b -r $TRACES/dns-spf.pcap %INPUT +# @TEST-EXEC: btest-diff dns.log + +@load base/protocols/dns \ No newline at end of file