diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index c31bf8fc95..f317a33599 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -21,9 +21,15 @@ namespace zeek::analyzer::dns { namespace detail { +// Used for checking whether the connection being parsed comes from NetBIOS, +// since it's similar to DNS but does some things differently. +constexpr int NETBIOS_PORT = 137; + DNS_Interpreter::DNS_Interpreter(analyzer::Analyzer* arg_analyzer) { analyzer = arg_analyzer; first_message = true; + is_netbios = + ntohs(analyzer->Conn()->OrigPort()) == NETBIOS_PORT || ntohs(analyzer->Conn()->RespPort()) == NETBIOS_PORT; } void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { @@ -42,7 +48,8 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { unsigned short flags = ntohs(hdr->flags); int opcode = (flags & 0x7800) >> 11; - if ( opcode != DNS_OP_QUERY ) { + // NetBIOS registration and release messages look like regular DNS requests, so parse them as such + if ( opcode != DNS_OP_QUERY && ! is_netbios ) { analyzer->Weird("DNS_unknown_opcode", util::fmt("%d", opcode)); analyzer->Conn()->CheckHistory(zeek::session::detail::HIST_UNKNOWN_PKT, 'X'); return; @@ -256,7 +263,7 @@ bool DNS_Interpreter::ParseAnswer(detail::DNS_MsgInfo* msg, const u_char*& data, case detail::TYPE_NBS: status = ParseRR_NBS(msg, data, len, rdlength, msg_start); break; case detail::TYPE_SRV: - if ( ntohs(analyzer->Conn()->RespPort()) == 137 ) { + if ( ntohs(analyzer->Conn()->RespPort()) == NETBIOS_PORT ) { // This is an NBSTAT (NetBIOS NODE STATUS) record. // The SRV RFC reused the value that was already being // used for this. @@ -399,7 +406,7 @@ bool DNS_Interpreter::ExtractLabel(const u_char*& data, int& len, u_char*& name, if ( label_len > 63 && // NetBIOS name service look ups can use longer labels. - ntohs(analyzer->Conn()->RespPort()) != 137 ) { + ntohs(analyzer->Conn()->RespPort()) != NETBIOS_PORT ) { analyzer->Weird("DNS_label_too_long"); return false; } diff --git a/src/analyzer/protocol/dns/DNS.h b/src/analyzer/protocol/dns/DNS.h index 8ed6b92d45..0894b3bad8 100644 --- a/src/analyzer/protocol/dns/DNS.h +++ b/src/analyzer/protocol/dns/DNS.h @@ -328,7 +328,7 @@ public: ///< for forward lookups }; -class DNS_Interpreter { +class DNS_Interpreter final { public: explicit DNS_Interpreter(analyzer::Analyzer* analyzer); @@ -390,6 +390,7 @@ protected: analyzer::Analyzer* analyzer; bool first_message; + bool is_netbios; }; enum TCP_DNS_state { diff --git a/testing/external/commit-hash.zeek-testing-private b/testing/external/commit-hash.zeek-testing-private index 342d403386..9d834eb6e3 100644 --- a/testing/external/commit-hash.zeek-testing-private +++ b/testing/external/commit-hash.zeek-testing-private @@ -1 +1 @@ -4a2735a9768b124d290a1692d47a25fd8d365320 +e051f29d1f03f2264b8cf1ff5ed9bfba9d326c45