Exemplo n.º 1
0
    def get_nt_challenge_response(self, lm_challenge_response, server_certificate_hash):
        """
        [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 beforeand, used to get the key_exchange_key value
        :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to.
                                        Used in Channel Binding Tokens if present, default value is None. See
                                        AuthenticateMessage in messages.py for more details
        :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 = ComputeResponse._get_NTLM2_response(self._password, self._server_challenge, self._client_challenge)
            key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key,
                                                                  self._server_challenge, lm_challenge_response,
                                                                  comphash._lmowfv1(self._password))
            target_info = None

        elif 0 <= self._ntlm_compatibility < 3:
            response, session_base_key = ComputeResponse._get_NTLMv1_response(self._password, self._server_challenge)
            key_exchange_key = compkeys._get_exchange_key_ntlm_v1(self._negotiate_flags, session_base_key,
                                                                  self._server_challenge, lm_challenge_response,
                                                                  comphash._lmowfv1(self._password))
            target_info = None
        else:
            if self._server_target_info is None:
                target_info = TargetInfo()
            else:
                target_info = self._server_target_info

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

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

            if server_certificate_hash != None:
                channel_bindings_hash = ComputeResponse._get_channel_bindings_value(server_certificate_hash)
                target_info[TargetInfo.MSV_AV_CHANNEL_BINDINGS] = channel_bindings_hash

            response, session_base_key = ComputeResponse._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
Exemplo n.º 2
0
 def test_lmofv1_hash(self):
     # 4.2.2.1.1 - LMOWFv1()
     expected = b"\xe5\x2c\xac\x67\x41\x9a\x9a\x22" \
                b"\x4a\x3b\x10\x8f\x3f\xa6\xcb\x6d"
     password_hash = "e52cac67419a9a224a3b108f3fa6cb6d:" \
                     "a4f49c406510bdcab6824ee7c30fd852"
     actual = compute_hash._lmowfv1(password_hash)
     assert actual == expected
Exemplo n.º 3
0
    def _get_LMv1_response(password, server_challenge):
        """
        [MS-NLMP] v28.0 2016-07-14

        2.2.2.3 LM_RESPONSE
        The LM_RESPONSE structure defines the NTLM v1 authentication LmChallengeResponse
        in the AUTHENTICATE_MESSAGE. This response is used only when NTLM v1
        authentication is configured.

        :param password: The password of the user we are trying to authenticate with
        :param server_challenge: A random 8-byte response generated by the server in the CHALLENGE_MESSAGE
        :return response: LmChallengeResponse to the server challenge
        """
        lm_hash = comphash._lmowfv1(password)
        response = ComputeResponse._calc_resp(lm_hash, server_challenge)

        return response
Exemplo n.º 4
0
    def _get_LMv1_response(password, server_challenge):
        """
        [MS-NLMP] v28.0 2016-07-14

        2.2.2.3 LM_RESPONSE
        The LM_RESPONSE structure defines the NTLM v1 authentication LmChallengeResponse
        in the AUTHENTICATE_MESSAGE. This response is used only when NTLM v1
        authentication is configured.

        :param password: The password of the user we are trying to authenticate with
        :param server_challenge: A random 8-byte response generated by the server in the CHALLENGE_MESSAGE
        :return response: LmChallengeResponse to the server challenge
        """
        lm_hash = comphash._lmowfv1(password)
        response = ComputeResponse._calc_resp(lm_hash, server_challenge)

        return response
Exemplo n.º 5
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
Exemplo n.º 6
0
 def test_lmowfv1(self):
     # 4.2.2.1.1 - LMOWFv1()
     expected = b"\xe5\x2c\xac\x67\x41\x9a\x9a\x22" \
                b"\x4a\x3b\x10\x8f\x3f\xa6\xcb\x6d"
     actual = compute_hash._lmowfv1("Password")
     assert actual == expected
Exemplo n.º 7
0
    def test_lmowfv1(self):
        expected = ntlmv1_lmowfv1

        actual = comphash._lmowfv1(password)

        assert actual == expected
Exemplo n.º 8
0
    def get_nt_challenge_response(self, lm_challenge_response,
                                  server_certificate_hash):
        """
        [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 beforeand, used to get the key_exchange_key value
        :param server_certificate_hash: The SHA256 hash of the server certificate (DER encoded) NTLM is authenticated to.
                                        Used in Channel Binding Tokens if present, default value is None. See
                                        AuthenticateMessage in messages.py for more details
        :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 = ComputeResponse._get_NTLM2_response(
                self._password, self._server_challenge, self._client_challenge)
            key_exchange_key = compkeys._get_exchange_key_ntlm_v1(
                self._negotiate_flags, session_base_key,
                self._server_challenge, lm_challenge_response,
                comphash._lmowfv1(self._password))
            target_info = None

        elif 0 <= self._ntlm_compatibility < 3:
            response, session_base_key = ComputeResponse._get_NTLMv1_response(
                self._password, self._server_challenge)
            key_exchange_key = compkeys._get_exchange_key_ntlm_v1(
                self._negotiate_flags, session_base_key,
                self._server_challenge, lm_challenge_response,
                comphash._lmowfv1(self._password))
            target_info = None
        else:
            if self._server_target_info is None:
                target_info = TargetInfo()
            else:
                target_info = self._server_target_info

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

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

            if server_certificate_hash != None:
                channel_bindings_hash = ComputeResponse._get_channel_bindings_value(
                    server_certificate_hash)
                target_info[
                    TargetInfo.MSV_AV_CHANNEL_BINDINGS] = channel_bindings_hash

            response, session_base_key = ComputeResponse._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