Beispiel #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"
Beispiel #2
0
def test_ntowfv1_hash():
    lm_hash = os.urandom(16)
    nt_hash = os.urandom(16)
    ntlm_hash = to_text(b"%s:%s" %
                        (base64.b16encode(lm_hash), base64.b16encode(nt_hash)))

    actual = crypto.ntowfv1(ntlm_hash)

    assert actual == nt_hash
Beispiel #3
0
    def __init__(self, domain=None, username=None, password=None):
        if password:
            self.domain = domain
            self.username = username
            self.lm_hash = lmowfv1(password)
            self.nt_hash = ntowfv1(password)
            self._store = 'explicit'

        else:
            self._store = _get_credential_file()
            self.domain, self.username, self.lm_hash, self.nt_hash = _get_credential(
                self._store, domain, username)
Beispiel #4
0
def test_compute_response_v1_session_security():
    actual_nt, actual_lm, actual_kek = crypto.compute_response_v1(
        TEST_NTLMV1_CLIENT_CHALLENGE_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/becc1601-9c97-4553-aef7-7053d3db5883
    assert actual_nt == b"\x75\x37\xF8\x03\xAE\x36\x71\x28\xCA\x45\x82\x04\xBD\xE7\xCA\xF8" \
                        b"\x1E\x97\xED\x26\x83\x26\x72\x32"

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/63725b2b-21fc-4977-9b56-2b3e65f7be76
    assert actual_lm == TEST_CLIENT_CHALLENGE + b"\x00" * 16

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/321bb3da-c27a-4a5d-91f9-4f23705e4029
    assert actual_kek == b"\xEB\x93\x42\x9A\x8B\xD9\x52\xF8\xB8\x9C\x55\xB8\x7F\x47\x5E\xDC"
Beispiel #5
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"
Beispiel #6
0
def test_seal_ntlmv1_with_ess():
    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/052aef59-b55b-4800-b4a8-e93eca1600d6
    key_exchange_key = compute_response_v1(TEST_NTLMV1_CLIENT_CHALLENGE_FLAGS,
                                           ntowfv1(TEST_PASSWD),
                                           lmowfv1(TEST_PASSWD),
                                           TEST_SERVER_CHALLENGE,
                                           TEST_CLIENT_CHALLENGE)[2]
    seal_key = sealkey(TEST_NTLMV1_CLIENT_CHALLENGE_FLAGS,
                       key_exchange_key,
                       usage='initiate')
    seal_handle = rc4init(seal_key)
    sign_key = signkey(TEST_NTLMV1_CLIENT_CHALLENGE_FLAGS,
                       key_exchange_key,
                       usage='initiate')

    b_data = to_bytes(u"Plaintext", encoding='utf-16-le')
    actual_msg, actual_signature = seal(TEST_NTLMV1_CLIENT_CHALLENGE_FLAGS,
                                        seal_handle, sign_key, 0, b_data)

    assert actual_msg == b"\xA0\x23\x72\xF6\x53\x02\x73\xF3\xAA\x1E\xB9\x01\x90\xCE\x52\x00" \
                         b"\xC9\x9D"
    assert actual_signature == b"\x01\x00\x00\x00\xFF\x2A\xEB\x52\xF6\x81\x79\x3A\x00\x00\x00\x00"
Beispiel #7
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"
Beispiel #8
0
def test_ntowfv1():
    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/0fb94d19-16d2-481d-9121-112defbaac0b
    actual = crypto.ntowfv1(TEST_PASSWD)

    assert actual == b"\xA4\xF4\x9C\x40\x65\x10\xBD\xCA\xB6\x82\x4E\xE7\xC3\x0F\xD8\x52"
Beispiel #9
0
def test_ntowfv2():
    actual = crypto.ntowfv2(TEST_USER, crypto.ntowfv1(TEST_PASSWD),
                            TEST_USER_DOM)

    # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/7795bd0e-fd5e-43ec-bd9c-994704d8ee26
    assert actual == b"\x0C\x86\x8A\x40\x3B\xFD\x7A\x93\xA3\x00\x1E\xF2\x2E\xF0\x2E\x3F"
Beispiel #10
0
def _get_credential(store, domain=None, username=None):
    # type: (text_type, Optional[text_type], Optional[text_type]) -> Tuple[text_type, text_type, bytes, bytes]
    """Look up NTLM credentials from the common flat file.

    Retrieves the LM and NT hash for use with authentication or validating a credential from an initiator.

    Each line in the store can be in the Heimdal format `DOMAIN:USER:PASSWORD` like::

        testdom:testuser:Password01
        :[email protected]:Password01

    Or it can use the `smbpasswd`_ file format `USERNAME:UID:LM_HASH:NT_HASH:ACCT_FLAGS:TIMESTAMP` like::

        testuser:1000:278623D830DABE161104594F8C2EF12B:C3C6F4FD8A02A6C1268F1A8074B6E7E0:[U]:LCT-1589398321
        TESTDOM\testuser:1000:4588C64B89437893AAD3B435B51404EE:65202355FA01AEF26B89B19E00F52679:[U]:LCT-1589398321
        [email protected]:1000:00000000000000000000000000000000:8ADB9B997580D69E69CAA2BBB68F4697:[U]:LCT-1589398321

    While only the `USERNAME`, `LM_HASH`, and `NT_HASH` fields are used, the colons are still required to differentiate
    between the 2 formats. See `ntlm hash generator`_ for ways to generate the `LM_HASH` and `NT_HASH`.

    The username is case insensitive but the format of the domain and user part must match up with the value used as
    the username specified by the caller.

    While each line can use a different format, it is recommended to stick to 1 throughout the file.

    The same env var and format can also be read with gss-ntlmssp.

    Args:
        store: The credential store to lookup the credential from.
        domain: The domain for the user to get the credentials for. Should be `None` for a user in the UPN form.
        username: The username to get the credentials for. If omitted then the first entry in the store is used.

    Returns:
        Tuple[text_type, text_type, bytes, bytes]: The domain, username, LM, and NT hash of the user specified.

    .. _smbpasswd:
        https://www.samba.org/samba/docs/current/man-html/smbpasswd.5.html

    .. _ntlm hash generator:
        https://asecuritysite.com/encryption/lmhash
    """
    if not store:
        raise OperationNotAvailableError(
            context_msg=
            "Retrieving NTLM store without NTLM_USER_FILE set to a filepath")

    domain = domain or u""

    def store_lines(text):
        for line in text.splitlines():
            line_split = line.split(':')

            if len(line_split) == 3:
                yield line_split[0], line_split[1], line_split[2], None, None

            elif len(line_split) == 6:
                domain_entry, user_entry = split_username(line_split[0])
                lm_entry = base64.b16decode(line_split[2].upper())
                nt_entry = base64.b16decode(line_split[3].upper())

                yield domain_entry or u"", user_entry, None, lm_entry, nt_entry

    with open(store, mode='rb') as fd:
        cred_text = to_text(fd.read())

        for line_domain, line_user, line_password, lm_hash, nt_hash in store_lines(
                cred_text):
            if not username or (username.upper() == line_user.upper()
                                and domain.upper() == line_domain.upper()):
                # The Heimdal format uses the password so if the LM or NT hash isn't set generate it ourselves.
                if not lm_hash:
                    lm_hash = lmowfv1(line_password)
                if not nt_hash:
                    nt_hash = ntowfv1(line_password)

                # Favour the explicit username/password value, otherwise use what was in the credential file.
                if not username:
                    username = line_user

                if not domain:
                    domain = line_domain or None

                return domain, username, lm_hash, nt_hash

        else:
            raise SpnegoError(
                ErrorCode.failure,
                context_msg="Failed to find any matching credential in "
                "NTLM_USER_FILE credential store.")