diff --git a/CHANGES b/CHANGES index 321860170b..5bb57a4876 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +7.2.0-dev.541 | 2025-04-16 09:34:09 +0200 + + * ldap: Clean up from code review (Arne Welzel, Corelight) + + * ldap: Add Sicily Authentication constants (Arne Welzel, Corelight) + + * GH-4275: ldap: Only switch into MS_KRB5 mode if responseToken exists (Arne Welzel, Corelight) + 7.2.0-dev.536 | 2025-04-15 18:31:28 +0200 * IXWebSocket: Bump to latest upstream master (Arne Welzel, Corelight) diff --git a/VERSION b/VERSION index aa35ec5de7..909206f19c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.2.0-dev.536 +7.2.0-dev.541 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 8b7f062901..c0a2f90bb3 100644 --- a/scripts/base/protocols/ldap/main.zeek +++ b/scripts/base/protocols/ldap/main.zeek @@ -376,13 +376,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 f448d71f0c..4848109616 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 6f9576cb71..ec244576a9 100644 --- a/testing/btest/Traces/README +++ b/testing/btest/Traces/README @@ -49,4 +49,7 @@ Trace Index/Sources: - tunnels/geneve-tagged-udp-packet.pcap Provided by Eldon Koyle Corelight for testing. - cdp-v1.pcap - From the Wireshark library of captures at https://wiki.wireshark.org/samplecaptures. \ No newline at end of file + From the Wireshark library of captures at https://wiki.wireshark.org/samplecaptures. +- 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.