Merge remote-tracking branch 'origin/topic/awelzel/3853-ldap-spnego-ntlmssp'

* origin/topic/awelzel/3853-ldap-spnego-ntlmssp:
  ldap: Recognize SASL+SPNEGO+NTLMSSP
This commit is contained in:
Arne Welzel 2024-07-26 15:14:36 +02:00
commit 152bbbd680
8 changed files with 75 additions and 15 deletions

10
CHANGES
View file

@ -1,3 +1,13 @@
7.1.0-dev.66 | 2024-07-26 15:14:36 +0200
* GH-3853: ldap: Recognize SASL+SPNEGO+NTLMSSP (Arne Welzel, Corelight)
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).
Closes #3853
7.1.0-dev.63 | 2024-07-25 09:19:20 -0700
* Use accessor to reach into X509_ALGOR (Theo Buehler)

View file

@ -1 +1 @@
7.1.0-dev.63
7.1.0-dev.66

View file

@ -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 {

View file

@ -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

View file

@ -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

View file

@ -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,
<https://github.com/zeek/spicy-ldap/issues/23>
- 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).

View file

@ -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.