diff --git a/src/analyzer/protocol/dns/DNS.cc b/src/analyzer/protocol/dns/DNS.cc index 54a374cfc3..c31bf8fc95 100644 --- a/src/analyzer/protocol/dns/DNS.cc +++ b/src/analyzer/protocol/dns/DNS.cc @@ -27,6 +27,7 @@ DNS_Interpreter::DNS_Interpreter(analyzer::Analyzer* arg_analyzer) { } void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { + // Every packet for every opcode starts with same size header. int hdr_len = sizeof(detail::DNS_RawMsgHdr); if ( len < hdr_len ) { @@ -34,7 +35,20 @@ void DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) { return; } - detail::DNS_MsgInfo msg((detail::DNS_RawMsgHdr*)data, is_query); + // The flags section may be different between the different opcodes, but the + // opcode is always in the same location. Parse out just that part of it here + // even though it will probably be reparsed later. + auto* hdr = (detail::DNS_RawMsgHdr*)data; + unsigned short flags = ntohs(hdr->flags); + int opcode = (flags & 0x7800) >> 11; + + if ( opcode != DNS_OP_QUERY ) { + analyzer->Weird("DNS_unknown_opcode", util::fmt("%d", opcode)); + analyzer->Conn()->CheckHistory(zeek::session::detail::HIST_UNKNOWN_PKT, 'X'); + return; + } + + detail::DNS_MsgInfo msg(hdr, is_query); if ( first_message && msg.QR && is_query == 1 ) { is_query = msg.is_query = 0; diff --git a/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log b/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log new file mode 100644 index 0000000000..77bb64abc0 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.dns.dynamic-update/weird.log @@ -0,0 +1,12 @@ +### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path weird +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p name addl notice peer source +#types time string addr port addr port string string bool string string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.106 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.105 62763 192.168.1.108 53 DNS_unknown_opcode 5 F zeek DNS +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/README b/testing/btest/Traces/README index 43942584f2..818e32bd8b 100644 --- a/testing/btest/Traces/README +++ b/testing/btest/Traces/README @@ -21,3 +21,9 @@ Trace Index/Sources: - ldap/ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap: Harvested from CTU-SME-11 (Experiment-VM-Microsoft-Windows7AD-1) dataset, filtering on tcp port 389 and port 50041. https://zenodo.org/records/7958259 (DOI 10.5281/zenodo.7958258). +- dns/tkey.pcap: Harvested from CTU-SME-11 + (Experiment-VM-Microsoft-Windows7AD-1) dataset, filtering on tcp port 53. + https://zenodo.org/records/7958259 (DOI 10.5281/zenodo.7958258). +- dns/dynamic-update.pcap: : Harvested from CTU-SME-11 + (Experiment-VM-Microsoft-Windows7AD-1) dataset, filtering on tcp port 53. + https://zenodo.org/records/7958259 (DOI 10.5281/zenodo.7958258). \ No newline at end of file diff --git a/testing/btest/Traces/dns/dynamic-update.pcap b/testing/btest/Traces/dns/dynamic-update.pcap new file mode 100644 index 0000000000..7fb25ac632 Binary files /dev/null and b/testing/btest/Traces/dns/dynamic-update.pcap differ diff --git a/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek b/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek new file mode 100644 index 0000000000..704ee0bb1a --- /dev/null +++ b/testing/btest/scripts/base/protocols/dns/dynamic-update.zeek @@ -0,0 +1,6 @@ +# @TEST-DOC: Tests that a DNS dynamic update packet doesn't error but reports an unknown opcode weird +# @TEST-EXEC: zeek -b -C -r $TRACES/dns/dynamic-update.pcap %INPUT +# @TEST-EXEC: btest-diff weird.log + +@load base/frameworks/notice/weird +@load base/protocols/dns