Exemplo n.º 1
0
def test_compute_response_v2():
    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/946f54bd-76b5-4b18-ace8-6e8c992d5847
    time = FileTime.unpack(TEST_TIME)
    av_pairs = TargetInfo.unpack(
        b"\x02\x00\x0C\x00\x44\x00\x6F\x00\x6D\x00\x61\x00\x69\x00\x6E\x00"
        b"\x01\x00\x0C\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00"
        b"\x00\x00\x00\x00")

    actual_nt, actual_lm, actual_kek = crypto.compute_response_v2(
        crypto.ntowfv2(TEST_USER, crypto.ntowfv1(TEST_PASSWD), TEST_USER_DOM),
        TEST_SERVER_CHALLENGE, TEST_CLIENT_CHALLENGE, time, av_pairs)

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/946f54bd-76b5-4b18-ace8-6e8c992d5847
    temp = b"\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
           b"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\x00\x00\x00\x00\x02\x00\x0C\x00" \
           b"\x44\x00\x6F\x00\x6D\x00\x61\x00\x69\x00\x6E\x00\x01\x00\x0C\x00" \
           b"\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x00\x00\x00\x00" \
           b"\x00\x00\x00\x00"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/fa2bc0f0-9efa-40d7-a165-adfccd7f6da7
    assert actual_nt == b"\x68\xCD\x0A\xB8\x51\xE5\x1C\x96\xAA\xBC\x92\x7B\xEB\xEF\x6A\x1C" + temp

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/7e2b35f9-fe90-49fb-8c9d-30639a899160
    assert actual_lm == b"\x86\xC3\x50\x97\xAC\x9C\xEC\x10\x25\x54\x76\x4A\x57\xCC\xCC\x19" \
                        b"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/54973495-20d2-49e8-9925-c399a403ed4a
    assert actual_kek == b"\x8D\xE4\x0C\xCA\xDB\xC1\x4A\x82\xF1\x5C\xB0\xAD\x0D\xE9\x5C\xA3"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/4a84eb20-870a-421e-984f-29a842cd6504
    actual_enc_key = crypto.rc4k(actual_kek, TEST_RANDOM_SESSION_KEY)
    assert actual_enc_key == b"\xC5\xDA\xD2\x54\x4F\xC9\x79\x90\x94\xCE\x1C\xE9\x0B\xC9\xD0\x3E"
Exemplo n.º 2
0
    def _step_initiate(self, in_token=None):
        if not self._temp_msg['negotiate']:
            negotiate_msg = Negotiate(self._context_req)
            self._temp_msg['negotiate'] = negotiate_msg
            return negotiate_msg.pack()

        challenge = Challenge.unpack(in_token)

        auth_kwargs = {
            'domain_name': self._credential.domain,
            'username': self._credential.username,
        }

        if challenge.flags & NegotiateFlags.version:
            auth_kwargs['version'] = Version.get_current()
            auth_kwargs['workstation'] = _get_workstation()

        nt_challenge, lm_challenge, key_exchange_key = self._compute_response(
            challenge, self._credential)

        if challenge.flags & NegotiateFlags.key_exch:
            # This is only documented on the server side for MS-NLMP but is also valid for the client. The actual
            # session key is the KeyExchangeKey like normal unless sign or seal is negotiated.

            if challenge.flags & NegotiateFlags.sign or challenge.flags & NegotiateFlags.seal:
                self._session_key = os.urandom(16)
                auth_kwargs['encrypted_session_key'] = rc4k(
                    key_exchange_key, self._session_key)

            else:
                self._session_key = key_exchange_key
                auth_kwargs[
                    'encrypted_session_key'] = b"\x00"  # Must be set to some value but this can be anything.

        else:
            self._session_key = key_exchange_key

        authenticate = Authenticate(challenge.flags, lm_challenge,
                                    nt_challenge, **auth_kwargs)

        if self._mic_required:
            authenticate.mic = self._calculate_mic(
                self._temp_msg['negotiate'].pack(), in_token,
                authenticate.pack())

        self._context_attr = authenticate.flags
        self._complete = True

        return authenticate.pack()
Exemplo n.º 3
0
def test_compute_response_v1_no_session_security():
    actual_nt, actual_lm, actual_kek = crypto.compute_response_v1(
        TEST_NTLMV1_FLAGS, crypto.ntowfv1(TEST_PASSWD),
        crypto.lmowfv1(TEST_PASSWD), TEST_SERVER_CHALLENGE,
        TEST_CLIENT_CHALLENGE)

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/a9dc740e-e12f-4fdd-8f2b-61a471731a14
    assert actual_nt == b"\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C" \
                        b"\x44\xBD\xBE\xD9\x27\x84\x1F\x94"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/859a18d1-d7b2-4e98-a261-5b38cdf4b11d
    assert actual_lm == actual_nt

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/0b344a44-7cd8-4ab5-b07c-ff2b3d8c15f4
    assert actual_kek == b"\xD8\x72\x62\xB0\xCD\xE4\xB1\xCB\x74\x99\xBE\xCC\xCD\xF1\x07\x84"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/2d7f9599-f849-4550-9579-91aeea8078b0
    actual_enc_key = crypto.rc4k(actual_kek, TEST_RANDOM_SESSION_KEY)
    assert actual_enc_key == b"\x51\x88\x22\xB1\xB3\xF3\x50\xC8\x95\x86\x82\xEC\xBB\x3E\x3C\xB7"
Exemplo n.º 4
0
def test_compute_response_v1_no_session_security_lm_key():
    flags = TEST_NTLMV1_FLAGS | NegotiateFlags.lm_key
    actual_nt, actual_lm, actual_kek = crypto.compute_response_v1(
        flags,
        crypto.ntowfv1(TEST_PASSWD),
        crypto.lmowfv1(TEST_PASSWD),
        TEST_SERVER_CHALLENGE,
        TEST_CLIENT_CHALLENGE,
        no_lm_response=False)

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/a9dc740e-e12f-4fdd-8f2b-61a471731a14
    assert actual_nt == b"\x67\xC4\x30\x11\xF3\x02\x98\xA2\xAD\x35\xEC\xE6\x4F\x16\x33\x1C" \
                        b"\x44\xBD\xBE\xD9\x27\x84\x1F\x94"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/859a18d1-d7b2-4e98-a261-5b38cdf4b11d
    assert actual_lm == b"\x98\xDE\xF7\xB8\x7F\x88\xAA\x5D\xAF\xE2\xDF\x77\x96\x88\xA1\x72" \
                        b"\xDE\xF1\x1C\x7D\x5C\xCD\xEF\x13"
    assert actual_kek == b"\xB0\x9E\x37\x9F\x7F\xBE\xCB\x1E\xAF\x0A\xFD\xCB\x03\x83\xC8\xA0"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/2d7f9599-f849-4550-9579-91aeea8078b0
    actual_enc_key = crypto.rc4k(actual_kek, TEST_RANDOM_SESSION_KEY)
    assert actual_enc_key == b"\x4C\xD7\xBB\x57\xD6\x97\xEF\x9B\x54\x9F\x02\xB8\xF9\xB3\x78\x64"
Exemplo n.º 5
0
    def _step_accept_authenticate(self, token):  # type: (bytes) -> None
        """ Process the Authenticate message from the initiator. """
        challenge = self._temp_msg['challenge']
        server_challenge = challenge.server_challenge
        auth = Authenticate.unpack(token)

        # TODO: Add anonymous user support.
        if not auth.user_name or (not auth.nt_challenge_response and
                                  (not auth.lm_challenge_response
                                   or auth.lm_challenge_response == b"\x00")):
            raise OperationNotAvailableError(
                context_msg="Anonymous user authentication not implemented")

        self._credential = _NTLMCredential(domain=auth.domain_name,
                                           username=auth.user_name)
        expected_mic = None

        if auth.nt_challenge_response and len(auth.nt_challenge_response) > 24:
            nt_hash = ntowfv2(self._credential.username,
                              self._credential.nt_hash,
                              self._credential.domain)

            nt_challenge = NTClientChallengeV2.unpack(
                auth.nt_challenge_response[16:])
            time = nt_challenge.time_stamp
            client_challenge = nt_challenge.challenge_from_client
            target_info = nt_challenge.av_pairs

            expected_nt, expected_lm, key_exchange_key = compute_response_v2(
                nt_hash, server_challenge, client_challenge, time, target_info)

            if self.channel_bindings:
                if AvId.channel_bindings not in target_info:
                    raise BadBindingsError(
                        context_msg=
                        "Acceptor bindings specified but not present in initiator "
                        "response")

                expected_bindings = target_info[AvId.channel_bindings]
                actual_bindings = md5(self.channel_bindings.pack())
                if expected_bindings not in [actual_bindings, b"\x00" * 16]:
                    raise BadBindingsError(
                        context_msg=
                        "Acceptor bindings do not match initiator bindings")

            if target_info.get(AvId.flags, 0) & AvFlags.mic:
                expected_mic = auth.mic

        else:
            if not self._nt_v1:
                raise InvalidTokenError(
                    context_msg=
                    "Acceptor settings are set to reject NTv1 responses")

            elif not auth.nt_challenge_response and not self._lm:
                raise InvalidTokenError(
                    context_msg=
                    "Acceptor settings are set to reject LM responses")

            client_challenge = None
            if auth.flags & NegotiateFlags.extended_session_security:
                client_challenge = auth.lm_challenge_response[:8]

            expected_nt, expected_lm, key_exchange_key = compute_response_v1(
                auth.flags,
                self._credential.nt_hash,
                self._credential.lm_hash,
                server_challenge,
                client_challenge,
                no_lm_response=not self._lm)

        auth_success = False

        if auth.nt_challenge_response:
            auth_success = auth.nt_challenge_response == expected_nt

        elif auth.lm_challenge_response:
            auth_success = auth.lm_challenge_response == expected_lm

        if not auth_success:
            raise InvalidTokenError(
                context_msg="Invalid NTLM response from initiator")

        if auth.flags & NegotiateFlags.key_exch and \
                (auth.flags & NegotiateFlags.sign or auth.flags & NegotiateFlags.seal):
            self._session_key = rc4k(key_exchange_key,
                                     auth.encrypted_random_session_key)

        else:
            self._session_key = key_exchange_key

        if expected_mic:
            auth.mic = b"\x00" * 16
            actual_mic = self._calculate_mic(
                self._temp_msg['negotiate'].pack(), challenge.pack(),
                auth.pack())

            if actual_mic != expected_mic:
                raise InvalidTokenError(
                    context_msg="Invalid MIC in NTLM authentication message")

        self._context_attr = auth.flags
        self._complete = True