diff --git a/scripts/base/protocols/ldap/consts.zeek b/scripts/base/protocols/ldap/consts.zeek index 5b29fd22e4..9eeb9f89af 100644 --- a/scripts/base/protocols/ldap/consts.zeek +++ b/scripts/base/protocols/ldap/consts.zeek @@ -26,6 +26,8 @@ export { const BIND_SIMPLE = "bind simple"; const BIND_SASL = "bind SASL"; + const BIND_SICILY_NEGOTIATE = "sicily_negotiate"; + const BIND_SICILY_RESPONSE= "sicily_response"; const RESULT_CODES = { [ LDAP::ResultCode_SUCCESS ] = "success", [ LDAP::ResultCode_OPERATIONS_ERROR ] = "operations error", [ diff --git a/scripts/base/protocols/ldap/main.zeek b/scripts/base/protocols/ldap/main.zeek index da4a21871c..edf77a4aac 100644 --- a/scripts/base/protocols/ldap/main.zeek +++ b/scripts/base/protocols/ldap/main.zeek @@ -372,13 +372,23 @@ event LDAP::bind_request(c: connection, if ( m?$opcode ) Reporter::conn_weird("LDAP_bind_opcode_already_set", c, m$opcode, "LDAP"); - if (authType == LDAP::BindAuthType_BIND_AUTH_SIMPLE) { + switch ( authType ) { + case LDAP::BindAuthType_BIND_AUTH_SIMPLE: m$opcode = BIND_SIMPLE; - } else if (authType == LDAP::BindAuthType_BIND_AUTH_SASL) { + break; + case LDAP::BindAuthType_BIND_AUTH_SASL: m$opcode = BIND_SASL; - } else { + break; + case LDAP::BindAuthType_SICILY_NEGOTIATE: + m$opcode = BIND_SICILY_NEGOTIATE; + break; + case LDAP::BindAuthType_SICILY_RESPONSE: + m$opcode = BIND_SICILY_RESPONSE; + break; + default: Reporter::conn_weird("LDAP_unknown_auth_type", c, cat(authType), "LDAP"); m$opcode = cat(authType); + break; } } diff --git a/src/analyzer/protocol/ldap/ldap.spicy b/src/analyzer/protocol/ldap/ldap.spicy index 0816e6afe9..74f388a60f 100644 --- a/src/analyzer/protocol/ldap/ldap.spicy +++ b/src/analyzer/protocol/ldap/ldap.spicy @@ -365,6 +365,12 @@ public type Message = unit(ctx: Ctx&) { public type BindAuthType = enum { BIND_AUTH_SIMPLE = 0, BIND_AUTH_SASL = 3, + + # https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/8b9dbfb2-5b6a-497a-a533-7e709cb9a982 + # 5.1.1.1.3 Sicily Authentication + SICILY_PACKAGE_DISCOVERY = 9, + SICILY_NEGOTIATE = 10, + SICILY_RESPONSE = 11, }; type GSS_SPNEGO_negTokenInit = unit { @@ -410,6 +416,13 @@ type SaslCredentials = unit() { }; }; +type SicilyMessage = unit() { + # Just ensure the signature matches. We could do more, + # but it'd be better to forward to an NTLM analyzer. + signature: skip b"NTLMSSP"; + var signature_decoded: string = "NTLMSSP"; +}; + type GSS_SPNEGO_Subsequent = unit { switch { -> spnegoChoiceByte: uint8(0xa1); @@ -423,6 +436,7 @@ type GSS_SPNEGO_Subsequent = unit { type GSS_SPNEGO_negTokenResp = unit { var accepted: bool; var supportedMech: ASN1::ASN1Message; + var responseToken: optional; # Parse the contained Sequence. seq: ASN1::ASN1Message(True) { @@ -433,7 +447,7 @@ type GSS_SPNEGO_negTokenResp = unit { } else if ( msg.application_id == 1 ) { self.supportedMech = msg; } else if ( msg.application_id == 2 ) { - # ignore responseToken + self.responseToken = msg.application_data; } else if ( msg.application_id == 3 ) { # ignore mechListMec } else { @@ -468,18 +482,30 @@ type BindRequest = unit(inout message: Message, ctx: Ctx&) { self.authType = cast(cast($$.application_id)); self.authData = $$.application_data; } - if ((self.authType == BindAuthType::BIND_AUTH_SIMPLE) && (|self.authData| > 0)) { - self.simpleCreds = self.authData.decode(); - if (|self.simpleCreds| > 0) { - message.arg = self.simpleCreds; - } - } - } - saslCreds: SaslCredentials() &parse-from=self.authData if ((self.authType == BindAuthType::BIND_AUTH_SASL) && - (|self.authData| > 0)) { - message.arg = self.saslCreds.mechanism; - ctx.saslMechanism = self.saslCreds.mechanism; } + + if ( |self.authData| > 0 ) { + switch ( self.authType ) { + BindAuthType::BIND_AUTH_SIMPLE -> + : void { + self.simpleCreds = self.authData.decode(); + message.arg = self.simpleCreds; + } + + BindAuthType::BIND_AUTH_SASL -> + saslCreds: SaslCredentials { + message.arg = self.saslCreds.mechanism; + ctx.saslMechanism = self.saslCreds.mechanism; + } + + BindAuthType::SICILY_NEGOTIATE, BindAuthType::SICILY_RESPONSE -> + sicilyMessage: SicilyMessage { + message.arg = self.sicilyMessage.signature_decoded; + } + + * -> : void; + } &parse-from=self.authData; + }; } &requires=(self?.authType && (self.authType != BindAuthType::Undef)); type ServerSaslCreds = unit { @@ -523,7 +549,7 @@ type BindResponse = unit(inout message: Message, ctx: Ctx&) { if ( $$?.negTokenResp ) { local token = $$.negTokenResp; if ( token.accepted && token?.supportedMechOid ) { - if ( token.supportedMechOid == GSSAPI_MECH_MS_KRB5 ) { + if ( token.supportedMechOid == GSSAPI_MECH_MS_KRB5 && token.responseToken ) { ctx.messageMode = MessageMode::MS_KRB5; } } diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap.log b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap.log new file mode 100644 index 0000000000..740ca715e6 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap.log @@ -0,0 +1,11 @@ +### 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 ClEkJM2Vm5giqnMf4h 192.168.226.131 54544 192.168.226.136 389 1440128865 3 bind SASL success - User1 GSS-SPNEGO +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap_search.log b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap_search.log new file mode 100644 index 0000000000..76424d5afc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/krb.ldap_search.log @@ -0,0 +1,11 @@ +### 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_search +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p message_id scope deref_aliases base_object result_count result diagnostic_message filter attributes +#types time string addr port addr port int string string string count string string string vector[string] +XXXXXXXXXX.XXXXXX ClEkJM2Vm5giqnMf4h 192.168.226.131 54544 192.168.226.136 389 1319382063 tree never dc=ADHACKING,dc=LOCAL 3 success - (&(&(sAMAccountName=*)(mail=*))(!(UserAccountControl:1.2.840.113556.1.4.803:=2))) - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap.log b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap.log new file mode 100644 index 0000000000..a1caacd709 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap.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 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.226.131 37618 192.168.226.136 389 173945320 3 sicily_negotiate success - User1 NTLMSSP +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.226.131 37618 192.168.226.136 389 1489001992 3 sicily_response success - User1 NTLMSSP +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap_search.log b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap_search.log new file mode 100644 index 0000000000..a02df616d7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ldap.aduser1/ntlm.ldap_search.log @@ -0,0 +1,11 @@ +### 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_search +#open XXXX-XX-XX-XX-XX-XX +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p message_id scope deref_aliases base_object result_count result diagnostic_message filter attributes +#types time string addr port addr port int string string string count string string string vector[string] +XXXXXXXXXX.XXXXXX CHhAvVGS1DHFjwGM9 192.168.226.131 37618 192.168.226.136 389 1673297393 tree never dc=ADHACKING,dc=LOCAL 3 success - (&(&(sAMAccountName=*)(mail=*))(!(UserAccountControl:1.2.840.113556.1.4.803:=2))) - +#close XXXX-XX-XX-XX-XX-XX diff --git a/testing/btest/Traces/README b/testing/btest/Traces/README index dd8d0350fe..e4209961ea 100644 --- a/testing/btest/Traces/README +++ b/testing/btest/Traces/README @@ -32,3 +32,6 @@ Trace Index/Sources: - quic/merlinc2_Zeek_example.pcapng Provided by Faan Rossouw on #4198 https://github.com/zeek/zeek/issues/4198 +- ldap/adduser1.pcap ldap/adduser1-ntlm.pcap + Provided by Mohan-Dhawan on #4275 + https://github.com/zeek/zeek/issues/4275 diff --git a/testing/btest/Traces/ldap/aduser1-ntlm.pcap b/testing/btest/Traces/ldap/aduser1-ntlm.pcap new file mode 100644 index 0000000000..3498d7a3cb Binary files /dev/null and b/testing/btest/Traces/ldap/aduser1-ntlm.pcap differ diff --git a/testing/btest/Traces/ldap/aduser1.pcap b/testing/btest/Traces/ldap/aduser1.pcap new file mode 100644 index 0000000000..a1d1c5aa4a Binary files /dev/null and b/testing/btest/Traces/ldap/aduser1.pcap differ diff --git a/testing/btest/scripts/base/protocols/ldap/aduser1.zeek b/testing/btest/scripts/base/protocols/ldap/aduser1.zeek new file mode 100644 index 0000000000..fdafa692f6 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ldap/aduser1.zeek @@ -0,0 +1,11 @@ +# @TEST-REQUIRES: have-spicy +# @TEST-EXEC: zeek -C -r ${TRACES}/ldap/aduser1.pcap %INPUT +# @TEST-EXEC: mkdir krb && mv *.log krb +# @TEST-EXEC: zeek -C -r ${TRACES}/ldap/aduser1-ntlm.pcap %INPUT +# @TEST-EXEC: mkdir ntlm && mv *.log ntlm +# @TEST-EXEC: btest-diff krb/ldap.log +# @TEST-EXEC: btest-diff krb/ldap_search.log +# @TEST-EXEC: btest-diff ntlm/ldap.log +# @TEST-EXEC: btest-diff ntlm/ldap_search.log +# +# @TEST-DOC: Check two traces using different authentication mechanisms, but the same search request.