From 9c70bcecbc6b8786d72600c2ccf4855ed3b59fef Mon Sep 17 00:00:00 2001 From: Jon Siwek Date: Mon, 16 Mar 2020 19:00:01 -0700 Subject: [PATCH] GH-865: fix parsing of SMB NegotiateContextList * The compression capability was incorrectly set to 0x0004 instead of 0x0003 * The padding was 4-byte instead of 8-byte aligned and also the spec. does not strictly require the padding for the last item in the list. * Add a default case to handle parsing of unknown context types. --- .../protocol/smb/smb2-com-negotiate.pac | 33 +++++++++++++----- .../out | 4 +++ testing/btest/Traces/smb/SMBGhost.pcap | Bin 0 -> 1400 bytes .../base/protocols/smb/compression-cap.zeek | 33 ++++++++++++++++++ 4 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 testing/btest/Baseline/scripts.base.protocols.smb.compression-cap/out create mode 100644 testing/btest/Traces/smb/SMBGhost.pcap create mode 100644 testing/btest/scripts/base/protocols/smb/compression-cap.zeek diff --git a/src/analyzer/protocol/smb/smb2-com-negotiate.pac b/src/analyzer/protocol/smb/smb2-com-negotiate.pac index 175d8e9642..65719201e5 100644 --- a/src/analyzer/protocol/smb/smb2-com-negotiate.pac +++ b/src/analyzer/protocol/smb/smb2-com-negotiate.pac @@ -11,7 +11,7 @@ enum smb3_capabilities { enum smb3_context_type { SMB2_PREAUTH_INTEGRITY_CAPABILITIES = 0x0001, SMB2_ENCRYPTION_CAPABILITIES = 0x0002, - SMB2_COMPRESSION_CAPABILITIES = 0x0004, + SMB2_COMPRESSION_CAPABILITIES = 0x0003, SMB2_NETNAME_NEGOTIATE_CONTEXT_ID = 0x0005, }; @@ -50,9 +50,13 @@ refine connection SMB_Conn += { VectorVal* cv = new VectorVal(BifType::Vector::SMB2::NegotiateContextValues); - if ( ${val.dialect_revision} == 0x0311 ) - for ( auto i = 0u; i < ${val.smb3_ncl.vals}->size(); ++i ) - cv->Assign(i, BuildSMB2ContextVal(${val.smb3_ncl.vals[i]})); + if ( ${val.dialect_revision} == 0x0311 && ${val.negotiate_context_count} > 0 ) + { + for ( auto i = 0u; i < ${val.smb3_ncl.list.vals}->size(); ++i ) + cv->Assign(i, BuildSMB2ContextVal(${val.smb3_ncl.list.vals[i].ncv})); + + cv->Assign(${val.smb3_ncl.list.vals}->size(), BuildSMB2ContextVal(${val.smb3_ncl.list.last_val})); + } nr->Assign(6, cv); @@ -97,8 +101,13 @@ type SMB3_negotiate_context_value = record { SMB2_ENCRYPTION_CAPABILITIES -> encryption_capabilities : SMB3_encryption_capabilities; SMB2_COMPRESSION_CAPABILITIES -> compression_capabilities : SMB3_compression_capabilities; SMB2_NETNAME_NEGOTIATE_CONTEXT_ID -> netname_negotiate_context_id : SMB3_netname_negotiate_context_id(data_length); + default -> unknown_context_data : bytestring &length=data_length; }; - pad : padding align 4; +}; + +type Padded_SMB3_negotiate_context_value = record { + ncv: SMB3_negotiate_context_value; + pad: padding align 8; }; type SMB2_negotiate_request(header: SMB2_Header) = record { @@ -115,8 +124,16 @@ type SMB2_negotiate_request(header: SMB2_Header) = record { }; type NegotiateContextList(len: uint16) = record { - vals : SMB3_negotiate_context_value[len]; -} + vals: Padded_SMB3_negotiate_context_value[len - 1]; + last_val: SMB3_negotiate_context_value; +}; + +type OptNegotiateContextList(len: uint16) = record { + opt: case len of { + 0 -> nil: empty; + default -> list: NegotiateContextList(len); + }; +}; type SMB2_negotiate_response(header: SMB2_Header) = record { structure_size : uint16; @@ -136,7 +153,7 @@ type SMB2_negotiate_response(header: SMB2_Header) = record { security_blob : bytestring &length=security_length; pad1 : padding to (dialect_revision == 0x0311 ? negotiate_context_offset - header.head_length : 0); negotiate_context_list : case dialect_revision of { - 0x0311 -> smb3_ncl : NegotiateContextList(negotiate_context_count); + 0x0311 -> smb3_ncl : OptNegotiateContextList(negotiate_context_count); default -> unknown : empty; }; } &byteorder=littleendian, &let { diff --git a/testing/btest/Baseline/scripts.base.protocols.smb.compression-cap/out b/testing/btest/Baseline/scripts.base.protocols.smb.compression-cap/out new file mode 100644 index 0000000000..f60ebed00e --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.smb.compression-cap/out @@ -0,0 +1,4 @@ +context value type 1, length 38 + [hash_alg_count=1, salt_length=32, hash_alg=[1], salt=\xfbV\x86\xeb\xb8\x8f\x1e\xb2\x1f\xd1?&\x94\xa5\xa53'\x01\x96\x96:\xca.\xcc\xa5\xa8\xd2\xf9\x15\xd7*\x92] +context value type 3, length 10 + [alg_count=1, algs=[1]] diff --git a/testing/btest/Traces/smb/SMBGhost.pcap b/testing/btest/Traces/smb/SMBGhost.pcap new file mode 100644 index 0000000000000000000000000000000000000000..3f06d3276ea0d2c5c8ac710c9c2154986155be69 GIT binary patch literal 1400 zcma)+ZAep57{{M;?)5U~2GcY~gf2B-@}(niBw&j~nKxM*F(pa2H!A9H(XEINbPqRp#0|p^~5%$tRaAD z3uV!oz$jm@MWq;_+$J$M82jV2Ran?aX=%a1w);%bC^@(h#iJe9C=)f%bec(lqnv?D z|N6dndCy=-}>h}>*^pSl3F3~7xag8UwQc6=p#@ap~(eXZ_sjaNCS2ntw zL7*F{ZK%81a^~5qE`IVpKOTSUP)b|Z?up}j^NZeGt|cG%4!8Mt)6>HB&iMfS_6&06 zw@NVhaifAPwsx}EssFyJx5;H{v2DZfidt{D`D5gEs+=}ep4B}t zP@GMAddemWUknURucplIy8{qfQ5Y7Uh1Jq9)>4eSsbjZl;b{1+l658ZbwliKF3qVG z`6w?YMXykfM5QDm<-JNdogYF`UbB#wC&%tlUY^h4bzL`vb**<8OvzJ%N_iEVa$cc) Mib_caSl$Wn7YZ#M&j0`b literal 0 HcmV?d00001 diff --git a/testing/btest/scripts/base/protocols/smb/compression-cap.zeek b/testing/btest/scripts/base/protocols/smb/compression-cap.zeek new file mode 100644 index 0000000000..9c3dbc576a --- /dev/null +++ b/testing/btest/scripts/base/protocols/smb/compression-cap.zeek @@ -0,0 +1,33 @@ +# @TEST-EXEC: zeek -b -r $TRACES/smb/SMBGhost.pcap %INPUT >out +# @TEST-EXEC: btest-diff out + +@load base/protocols/smb + +event smb2_negotiate_response(c: connection, hdr: SMB2::Header, response: SMB2::NegotiateResponse) + { + for ( i in response$negotiate_context_values ) + { + local ncv = response$negotiate_context_values[i]; + + print fmt("context value type %s, length %s", + ncv$context_type, ncv$data_length); + + switch ( ncv$context_type ) { + case 0x001: + print fmt(" %s", ncv$preauth_info); + break; + case 0x002: + print fmt(" %s", ncv$encryption_info); + break; + case 0x003: + print fmt(" %s", ncv$compression_info); + break; + case 0x005: + print fmt(" %s", ncv$netname); + break; + default: + print " unknown context value type"; + break; + } + } + }