コード例 #1
0
def get_cbt_data(response):
    """
    Create Channel Binding for TLS data

    See:
      - https://tools.ietf.org/html/rfc5929
      - https://github.com/jborean93/ntlm-auth#ntlmv2
      - https://github.com/requests/requests-ntlm/pull/116#discussion_r325961121
      - https://support.microsoft.com/en-za/help/976918/authentication-failure-from-non-windows-ntlm-or-kerberos-servers  # noqa

    :param response: HTTP Response object
    """

    cert_hash_bytes = get_server_cert(response)
    if not cert_hash_bytes:
        logger.debug("server cert not found, channel binding tokens (CBT) wont be used")
        return None

    channel_binding_type = b"tls-server-end-point"  # https://tools.ietf.org/html/rfc5929#section-4
    data_type = GssChannelBindingsStruct.APPLICATION_DATA

    cbt_data = GssChannelBindingsStruct()
    cbt_data[data_type] = b":".join([channel_binding_type, cert_hash_bytes])
    logger.debug("cbt data: %s", cbt_data.get_data())
    return cbt_data
コード例 #2
0
    def _get_channel_bindings_value(server_certificate_hash):
        """
        Get's the MD5 hash of the gss_channel_bindings_struct to add to the
        AV_PAIR MSV_AV_CHANNEL_BINDINGS. This method takes in the SHA256 hash
        (Hash of the DER encoded certificate of the server we are connecting
        to) and add's it to the gss_channel_bindings_struct. It then gets the
        MD5 hash and converts this to a byte array in preparation of adding it
        to the AV_PAIR structure.

        :param server_certificate_hash: The SHA256 hash of the server
            certificate (DER encoded) NTLM is authenticated to
        :return channel_bindings: An MD5 hash of the
            gss_channel_bindings_struct to add to the AV_PAIR
            MsvChannelBindings
        """
        # Channel Binding Tokens support, used for NTLMv2
        # Decode the SHA256 certificate hash
        certificate_digest = base64.b16decode(server_certificate_hash)

        # Initialise the GssChannelBindingsStruct and add the
        # certificate_digest to the application_data field
        gss_channel_bindings = GssChannelBindingsStruct()
        gss_channel_bindings[gss_channel_bindings.APPLICATION_DATA] = \
            b'tls-server-end-point:' + certificate_digest

        # Get the gss_channel_bindings_struct and create an MD5 hash
        channel_bindings_struct_data = gss_channel_bindings.get_data()
        channel_bindings = hashlib.md5(channel_bindings_struct_data).digest()

        return channel_bindings
コード例 #3
0
    def _get_channel_bindings_value(server_certificate_hash):
        """
        https://msdn.microsoft.com/en-us/library/windows/desktop/dd919963%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
        https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/

        Get's the MD5 hash of the gss_channel_bindings_struct to add to the AV_PAIR MSV_AV_CHANNEL_BINDINGS.
        This method takes in the SHA256 hash (Hash of the DER encoded certificate of the server we are connecting to)
        and add's it to the gss_channel_bindings_struct. It then gets the MD5 hash and converts this to a
        byte array in preparation of adding it to the AV_PAIR structure.

        :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to
        :return channel_bindings: An MD5 hash of the gss_channel_bindings_struct to add to the AV_PAIR MsvChannelBindings
        """
        # Channel Binding Tokens support, used for NTLMv2
        # Decode the SHA256 certificate hash
        certificate_digest = base64.b16decode(server_certificate_hash)

        # Initialise the GssChannelBindingsStruct and add the certificate_digest to the application_data field
        gss_channel_bindings = GssChannelBindingsStruct()
        gss_channel_bindings[gss_channel_bindings.APPLICATION_DATA] = 'tls-server-end-point:'.encode() + certificate_digest

        # Get the gss_channel_bindings_struct and create an MD5 hash
        channel_bindings_struct_data = gss_channel_bindings.get_data()
        channel_bindings_hash = hashlib.md5(channel_bindings_struct_data).hexdigest()

        try:
            cbt_value = bytearray.fromhex(channel_bindings_hash)
        except TypeError:
            # Work-around for Python 2.6 bug
            cbt_value = bytearray.fromhex(unicode(channel_bindings_hash))

        channel_bindings = bytes(cbt_value)
        return channel_bindings
コード例 #4
0
 def test_application_data(self):
     struct = GssChannelBindingsStruct()
     struct[GssChannelBindingsStruct.APPLICATION_DATA] = b"abc"
     expected = b"\x00\x00\x00\x00" \
                b"\x00\x00\x00\x00" \
                b"\x00\x00\x00\x00" \
                b"\x00\x00\x00\x00" \
                b"\x03\x00\x00\x00" \
                b"\x61\x62\x63"
     actual = struct.get_data()
     assert actual == expected
コード例 #5
0
 def test_full_data(self):
     struct = GssChannelBindingsStruct()
     struct[GssChannelBindingsStruct.INITIATOR_ADDTYPE] = 2
     struct[GssChannelBindingsStruct.INITIATOR_ADDRESS] = b"abc"
     struct[GssChannelBindingsStruct.ACCEPTOR_ADDRTYPE] = 4
     struct[GssChannelBindingsStruct.ACCEPTOR_ADDRESS] = b"def"
     struct[GssChannelBindingsStruct.APPLICATION_DATA] = b"ghi"
     expected = b"\x02\x00\x00\x00" \
                b"\x03\x00\x00\x00" \
                b"\x61\x62\x63" \
                b"\x04\x00\x00\x00" \
                b"\x03\x00\x00\x00" \
                b"\x64\x65\x66" \
                b"\x03\x00\x00\x00" \
                b"\x67\x68\x69"
     actual = struct.get_data()
     assert actual == expected
コード例 #6
0
    def _get_channel_bindings_value(server_certificate_hash):
        """
        https://msdn.microsoft.com/en-us/library/windows/desktop/dd919963%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
        https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/

        Get's the MD5 hash of the gss_channel_bindings_struct to add to the AV_PAIR MSV_AV_CHANNEL_BINDINGS.
        This method takes in the SHA256 hash (Hash of the DER encoded certificate of the server we are connecting to)
        and add's it to the gss_channel_bindings_struct. It then gets the MD5 hash and converts this to a
        byte array in preparation of adding it to the AV_PAIR structure.

        :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to
        :return channel_bindings: An MD5 hash of the gss_channel_bindings_struct to add to the AV_PAIR MsvChannelBindings
        """
        # Channel Binding Tokens support, used for NTLMv2
        # Decode the SHA256 certificate hash
        certificate_digest = base64.b16decode(server_certificate_hash)

        # Initialise the GssChannelBindingsStruct and add the certificate_digest to the application_data field
        gss_channel_bindings = GssChannelBindingsStruct()
        gss_channel_bindings[
            gss_channel_bindings.
            APPLICATION_DATA] = 'tls-server-end-point:'.encode(
            ) + certificate_digest

        # Get the gss_channel_bindings_struct and create an MD5 hash
        channel_bindings_struct_data = gss_channel_bindings.get_data()
        channel_bindings_hash = hashlib.md5(
            channel_bindings_struct_data).hexdigest()

        try:
            cbt_value = bytearray.fromhex(channel_bindings_hash)
        except TypeError:
            # Work-around for Python 2.6 bug
            cbt_value = bytearray.fromhex(unicode(channel_bindings_hash))

        channel_bindings = bytes(cbt_value)
        return channel_bindings
コード例 #7
0
    def get_nt_challenge_response(self,
                                  lm_challenge_response,
                                  server_certificate_hash=None,
                                  cbt_data=None):
        """
        [MS-NLMP] v28.0 2016-07-14

        3.3.1 - NTLM v1 Authentication
        3.3.2 - NTLM v2 Authentication

        This method returns the NtChallengeResponse key based on the
        ntlm_compatibility chosen and the target_info supplied by the
        CHALLENGE_MESSAGE. It is quite different from what is set in the
        document as it combines the NTLMv1, NTLM2 and NTLMv2 methods into one
        and calls separate methods based on the ntlm_compatibility value
        chosen.

        :param lm_challenge_response: The LmChallengeResponse calculated
            beforehand, used to get the key_exchange_key value
        :param server_certificate_hash: This is deprecated and will be removed
            in a future version, use cbt_data instead
        :param cbt_data: The GssChannelBindingsStruct to bind in the NTLM
            response
        :return response: (NtChallengeResponse) - The NT response to the server
            challenge. Computed by the client
        :return session_base_key: (SessionBaseKey) - A session key calculated
            from the user password challenge
        :return target_info: (AV_PAIR) - The AV_PAIR structure used in the
            nt_challenge calculations
        """
        if self._negotiate_flags & \
                NegotiateFlags.NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and \
                self._ntlm_compatibility < 3:
            # The compatibility level is less than 3 which means it doesn't
            # support NTLMv2 but we want extended security so use NTLM2 which
            # is different from NTLMv2
            # [MS-NLMP] - 3.3.1 NTLMv1 Authentication
            response, session_base_key = \
                self._get_NTLM2_response(self._password,
                                         self._server_challenge,
                                         self._client_challenge)
            lm_hash = comphash._lmowfv1(self._password)
            key_exchange_key = \
                compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags,
                                                   session_base_key,
                                                   self._server_challenge,
                                                   lm_challenge_response,
                                                   lm_hash)
            target_info = None

        elif 0 <= self._ntlm_compatibility < 3:
            response, session_base_key = \
                self._get_NTLMv1_response(self._password,
                                          self._server_challenge)

            lm_hash = comphash._lmowfv1(self._password)
            key_exchange_key = \
                compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags,
                                                   session_base_key,
                                                   self._server_challenge,
                                                   lm_challenge_response,
                                                   lm_hash)
            target_info = None

        else:
            if self._server_target_info is None:
                target_info = ntlm_auth.messages.TargetInfo()
            else:
                target_info = self._server_target_info

            if target_info[AvId.MSV_AV_TIMESTAMP] is None:
                timestamp = get_windows_timestamp()
            else:
                timestamp = target_info[AvId.MSV_AV_TIMESTAMP]

                # [MS-NLMP] If the CHALLENGE_MESSAGE TargetInfo field has an
                # MsvAvTimestamp present, the client SHOULD provide a MIC
                target_info[AvId.MSV_AV_FLAGS] = \
                    struct.pack("<L", AvFlags.MIC_PROVIDED)

            if server_certificate_hash is not None and cbt_data is None:
                warnings.warn(
                    "Manually creating the cbt stuct from the cert "
                    "hash will be removed in a newer version of "
                    "ntlm-auth. Send the actual CBT struct using "
                    "cbt_data instead", DeprecationWarning)
                certificate_digest = base64.b16decode(server_certificate_hash)

                cbt_data = GssChannelBindingsStruct()
                cbt_data[cbt_data.APPLICATION_DATA] = \
                    b'tls-server-end-point:' + certificate_digest

            if cbt_data is not None:
                cbt_bytes = cbt_data.get_data()
                cbt_hash = hashlib.md5(cbt_bytes).digest()
                target_info[AvId.MSV_AV_CHANNEL_BINDINGS] = cbt_hash

            response, session_base_key = \
                self._get_NTLMv2_response(self._user_name, self._password,
                                          self._domain_name,
                                          self._server_challenge,
                                          self._client_challenge,
                                          timestamp, target_info)

            key_exchange_key = \
                compkeys._get_exchange_key_ntlm_v2(session_base_key)

        return response, key_exchange_key, target_info