diff --git a/src/analyzer/protocol/ldap/ldap.spicy b/src/analyzer/protocol/ldap/ldap.spicy index 96f942d7a3..52ab0e6160 100644 --- a/src/analyzer/protocol/ldap/ldap.spicy +++ b/src/analyzer/protocol/ldap/ldap.spicy @@ -375,26 +375,29 @@ type GSS_SPNEGO_negTokenInit = unit { : skip bytes &eod; }; -# Peak into GSS-SPNEGO payload and ensure it is indeed GSS-SPNEGO. +# Peak into GSS-SPNEGO payload and ensure it is indeed GSS-SPNEGO, +# or GSS-SPNEGO with a NTMLSSP payload that starts with NTLMSSP. type GSS_SPNEGO_Init = unit { # This is the optional octet string in SaslCredentials. credentialsHeader: ASN1::ASN1Header &requires=($$.tag.type_ == ASN1::ASN1Type::OctetString); # Now we either have the initial message as specified in RFC2743 or - # a continuation from RFC4178 + # a continuation from RFC4178, or a "NTMLSSP" signature. # - # 60 -> APPLICATION [0] https://datatracker.ietf.org/doc/html/rfc2743#page-81) + # 60 -> APPLICATION [0] https://datatracker.ietf.org/doc/html/rfc2743#page-81 # a1 -> CHOICE [1] https://www.rfc-editor.org/rfc/rfc4178#section-4.2 + # "NTMLSSP" https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/907f519d-6217-45b1-b421-dca10fc8af0d # - gssapiHeader: ASN1::ASN1Header &requires=( - $$.tag.class == ASN1::ASN1Class::Application && $$.tag.type_ == ASN1::ASN1Type(0) - || $$.tag.class == ASN1::ASN1Class::ContextSpecific && $$.tag.type_ == ASN1::ASN1Type(1) - ); + switch { + -> spnegoInitByte: uint8(0x60); + -> spnegoChoiceByte: uint8(0xa1); + -> ntlmSignature: skip b"NTLMSSP"; # Unsupported, should forward to child analyzer! + }; - switch ( self.gssapiHeader.tag.type_ ) { - ASN1::ASN1Type(0) -> initial: GSS_SPNEGO_negTokenInit; - * -> : skip bytes &eod; - } &size=self.gssapiHeader.len.len; + spnegoLen: skip ASN1::LengthType if (self?.spnegoInitByte || self?.spnegoChoiceByte); + + # Peak into the SPNEGO_negTokenInit + spnegoInitial: skip GSS_SPNEGO_negTokenInit if (self?.spnegoInitByte); }; type SaslCredentials = unit() { @@ -408,10 +411,13 @@ type SaslCredentials = unit() { }; type GSS_SPNEGO_Subsequent = unit { - token: ASN1::ASN1Header &requires=($$.tag.class == ASN1::ASN1Class::ContextSpecific); - switch ( self.token.tag.type_ ) { - ASN1::ASN1Type(1) -> negTokenResp: GSS_SPNEGO_negTokenResp; + switch { + -> spnegoChoiceByte: uint8(0xa1); + -> ntmlSignature: skip b"NTLMSSP"; # Unsupported, should forward to NTLM! }; + + spnegoChoiceLen: skip ASN1::LengthType if (self?.spnegoChoiceByte); + negTokenResp: GSS_SPNEGO_negTokenResp if (self?.spnegoChoiceByte); }; type GSS_SPNEGO_negTokenResp = unit { diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/conn.log b/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/conn.log new file mode 100644 index 0000000000..84a495d3fb --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/conn.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 conn +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes tunnel_parents +#types time string addr port addr port enum string interval count count string count string count count count count set[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.105 50041 192.168.1.108 389 tcp ldap_tcp 0.004745 93 283 RSTR 0 ShADdFar 5 305 4 455 - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.107 50041 192.168.1.108 389 tcp ldap_tcp 0.005883 93 283 RSTR 0 ShADdFar 5 305 4 455 - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/ldap.log b/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/ldap.log new file mode 100644 index 0000000000..07355e0e78 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.spnego-ntlmssp/ldap.log @@ -0,0 +1,14 @@ +### 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 ldap +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p message_id version opcode result diagnostic_message object argument +#types time string addr port addr port int int string string string string string +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.105 50041 192.168.1.108 389 160 3 bind SASL SASL bind in progress - - GSS-SPNEGO +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.1.105 50041 192.168.1.108 389 161 - unbind - - - - +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.107 50041 192.168.1.108 389 427 3 bind SASL SASL bind in progress - - GSS-SPNEGO +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.1.107 50041 192.168.1.108 389 428 - unbind - - - - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/README b/testing/btest/Traces/README index bc5a304436..43942584f2 100644 --- a/testing/btest/Traces/README +++ b/testing/btest/Traces/README @@ -18,3 +18,6 @@ Trace Index/Sources: - one `\x30` byte in the ciphertext changed to `\x00` - ldap/issue-32.pcapng: Provided by GH user martinvanhensbergen, +- 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). diff --git a/testing/btest/Traces/ldap/ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap b/testing/btest/Traces/ldap/ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap new file mode 100644 index 0000000000..dd2b34ce4a Binary files /dev/null and b/testing/btest/Traces/ldap/ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap differ diff --git a/testing/btest/scripts/base/protocols/ldap/spnego-ntlmssp.zeek b/testing/btest/scripts/base/protocols/ldap/spnego-ntlmssp.zeek new file mode 100644 index 0000000000..e936332b47 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ldap/spnego-ntlmssp.zeek @@ -0,0 +1,15 @@ +# Copyright (c) 2024 by the Zeek Project. See LICENSE for details. +# +# The ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap file was harvested +# from the CTU-SME-11 (Experiment-VM-Microsoft-Windows7AD-1) dataset +# at https://zenodo.org/records/7958259 (DOI 10.5281/zenodo.7958258). + +# @TEST-REQUIRES: have-spicy +# @TEST-EXEC: zeek -C -r ${TRACES}/ldap/ctu-sme-11-win7ad-1-ldap-tcp-50041.pcap +# @TEST-EXEC: cat conn.log | zeek-cut -Cn local_orig local_resp > conn.log2 && mv conn.log2 conn.log +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff ldap.log +# @TEST-EXEC: ! test -f dpd.log +# @TEST-EXEC: ! test -f analyzer.log +# +# @TEST-DOC: SASL bindRequest with SPNEGO NTLMSSP.