Sunday 16 February 2020

Analysing LDAP Transport Channel Security via Packet Capture


It can be unexpectedly difficult to discover which security mechanisms are actually protecting an LDAP connection – the security measures that have been programmed or configured might not match what is observed via packet capture and analysis.


An LDAP connection can be protected with TLS, by using the StartTLS extended control on an existing connection or by connecting to an LDAP server listening at TCP port 636 (“ldaps” service). TLS provides sealing (also known as confidentiality or encryption) and signing (also known as integrity) for the connection.


A packet capture of a StartTLS extended operation looks like this:




An Active Directory LDAP servers supports 3 authentication methods (Simple, SASL and Sicily) and all of them can be combined with TLS. There is however a limitation with the TLS and SASL combination: SASL confidentiality and integrity mechanisms cannot be combined with TLS; attempts to combine the two fail with the LDAP unwillingToPerform (53) result code.


Combining information from RFC 2251 (LDAPv3) and [MS-ADTS], the Bind Request is defined as follows:


        BindRequest ::= [APPLICATION 0] SEQUENCE {
                version                 INTEGER (1 .. 127),
                name                    LDAPDN,
                authentication          AuthenticationChoice }



        AuthenticationChoice ::= CHOICE {
                simple                  [0] OCTET STRING,
                sasl                    [3] SaslCredentials

                sicilyPackageDiscovery  [9] OCTET STRING
                sicilyNegotiate         [10] OCTET STRING
                sicilyResponse          [11] OCTET STRING }



        SaslCredentials ::= SEQUENCE {
                mechanism               LDAPString,
                credentials             OCTET STRING OPTIONAL }


The Simple and Sicily authentication methods do not define any mechanism to encode/encapsulate any protection for the data carried on the connection which they authenticated. After authentication (the LDAP Bind operation) is complete, no protection (sealing or signing) is applied and the subsequent LDAP PDUs are carried unaltered over the LDAP connection.


Active Directory LDAP servers support 4 SASL mechanisms: GSS-SPNEGO, GSSAPI, EXTERNAL and DIGEST-MD5; only GSSAPI and GSS-SPNEGO will be described here. GSSAPI uses Kerberos for authentication and GSS-SPNEGO uses Kerberos or NTLM.


The intention to use the SASL security protection measures of “sealing” and/or “signing” is signalled via information in the authentication information; NTLM uses the NegotiateFlags field of the NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE and AUTHENTICATE_MESSAGE messages whereas Kerberos uses the Authenticator Checksum Flags field in the authenticator of a KRB_AP_REQ message.


If a LDAP Bind operation is successful, the first bytes of subsequent LDAP messages reveal, to network analysis tools, whether the connection is protected: if it is protected, the first 4 bytes will be a message length (RFC 4422 (SASL), section 3.7) otherwise the message will start with the encoding of the ASN.1 representation of the LDAP operation.


For the GSSAPI SASL mechanism, the format of the SASL credentials is described in RFC 4121 (Kerberos Version 5 GSS-API) section 4.1 and defined in RFC 2743 (GSS-API) section 3.1. Credentials of the appropriate type are obtained by calling GSS_Acquire_cred (the Windows equivalent is AcquireCredentialsHandle), specifying the “Kerberos” package. The credential information is created by the GSS_Init_sec_context routine; the Windows equivalent for this routine is InitializeSecurityContext. By default (if no particular security context is requested), “signing” (integrity) is implied; to override this default, one must explicitly request no signing/integrity via the ISC_REQ_NO_INTEGRITY flag. The requested security context is conveyed in a part of the credential information that is encrypted with the Kerberos session key, so it is not easy to observe the requested context in a network trace.


If signing or sealing is requested, the data in the body of the LDAP message (after the SASL 4 byte length) is the result of passing the plain LDAP message through the GSS_Wrap routine; the Windows equivalent of this routine is EncryptMessage. GSS_Wrap/EncryptMessage is used for both signing and sealing; if only signing is required then EncryptMessage is invoked with the flag SECQOP_WRAP_NO_ENCRYPT. The format of the wrapped message is defined in RFC 4121 section 4.2.6.2.


The GSS-SPNEGO SASL mechanism is similar to the GSSAPI mechanism with the following differences. The credentials are obtained by calling AcquireCredentialsHandle, specifying the “Negotiate” package. The format of the credentials is defined in RFC 4178 (The GSS-API Negotiation Mechanism), section 4.2.


If Kerberos is negotiated, the format of subsequent LDAP messages is the same as GSSAPI/Kerberos (RFC 4121 section 4.2.6.2). If NTLM is negotiated, the format of subsequent LDAP messages is described in [MS-NLMP] section 3.4. NTLM always negotiates at least signing/integrity – this cannot be disabled with the ISC_REQ_NO_INTEGRITY flag; the NTLM SSPI package also seems to ignore the SECQOP_WRAP_NO_ENCRYPT flag, so sealing/confidentiality/encryption is performed too (regardless of whether it was requested or not).


NTLM signing is either a CRC-32 value or the first 8 bytes of an MD5 hash (depending on whether NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY is negotiated); NTLM sealing uses RC4. Kerberos uses the algorithms associated with the Kerberos session key, which might be as secure as AES-256 and SHA1-96 (first 12 bytes of an SHA-1 hash).