Пример #1
0
    def tgs_from_ccache(self, spn_user, override_etype):
        try:
            if self.ccache is None:
                raise Exception('No CCACHE file found')

            for tgs, keystruct in self.ccache.get_all_tgs():
                ticket_for = ('/'.join(tgs['ticket']['sname']['name-string'])
                              ) + '@' + tgs['ticket']['realm']
                if self.usercreds.ccache_spn_strict_check is True:
                    if ticket_for.upper() == str(spn_user).upper():
                        logger.debug('Found TGS for user %s' % ticket_for)
                        key = Key(keystruct['keytype'], keystruct['keyvalue'])
                        tgs = TGS_REP(tgs).native
                        return tgs, tgs['enc-part'], key, None
                else:
                    # I hope you know what you are doing at this point...
                    key = Key(keystruct['keytype'], keystruct['keyvalue'])
                    tgs = TGS_REP(tgs).native
                    return tgs, tgs['enc-part'], key, None

            logger.debug('No TGS found for user %s' % ticket_for)
            raise Exception('No TGS found for user %s' % ticket_for)

        except Exception as e:
            return None, None, None, e
Пример #2
0
    def decrypt_asrep(self, as_rep):
        def truncate_key(value, keysize):
            output = b''
            currentNum = 0
            while len(output) < keysize:
                currentDigest = hashlib.sha1(bytes([currentNum]) +
                                             value).digest()
                if len(output) + len(currentDigest) > keysize:
                    output += currentDigest[:keysize - len(output)]
                    break
                output += currentDigest
                currentNum += 1

            return output

        for pa in as_rep['padata']:
            if pa['padata-type'] == 17:
                pkasrep = PA_PK_AS_REP.load(pa['padata-value']).native
                break
        else:
            raise Exception('PA_PK_AS_REP not found!')

        sd = cms.SignedData.load(pkasrep['dhSignedData']).native
        keyinfo = sd['encap_content_info']
        if keyinfo['content_type'] != '1.3.6.1.5.2.3.2':
            raise Exception('Keyinfo content type unexpected value')
        authdata = KDCDHKeyInfo.load(keyinfo['content']).native
        pubkey = int(
            ''.join(['1'] + [str(x) for x in authdata['subjectPublicKey']]), 2)

        pubkey = int.from_bytes(core.BitString(
            authdata['subjectPublicKey']).dump()[7:],
                                'big',
                                signed=False)
        shared_key = self.diffie.exchange(pubkey)

        server_nonce = pkasrep['serverDHNonce']
        fullKey = shared_key + self.diffie.dh_nonce + server_nonce

        etype = as_rep['enc-part']['etype']
        cipher = _enctype_table[etype]
        if etype == Enctype.AES256:
            t_key = truncate_key(fullKey, 32)
        elif etype == Enctype.AES128:
            t_key = truncate_key(fullKey, 16)
        elif etype == Enctype.RC4:
            raise NotImplementedError(
                'RC4 key truncation documentation missing. it is different from AES'
            )
            #t_key = truncate_key(fullKey, 16)

        key = Key(cipher.enctype, t_key)
        enc_data = as_rep['enc-part']['cipher']
        dec_data = cipher.decrypt(key, 3, enc_data)
        encasrep = EncASRepPart.load(dec_data).native
        cipher = _enctype_table[int(encasrep['key']['keytype'])]
        session_key = Key(cipher.enctype, encasrep['key']['keyvalue'])
        return encasrep, session_key, cipher
Пример #3
0
def decrypt_fast_as_rep(armor_key_bytes, computer_subkey_bytes):
    asrep_data = bytes.fromhex(
        '6b8207333082072fa003020105a10302010ba282015b3082015730820153a10402020088a282014904820145a08201413082013da082013930820135a003020112a282012c04820128b481f8034f43c667939a3a0a8459c05163929b8d3e7e95f5ac52a285766281a4e5fa9c8961cd4588b651b8ca518203b326049e8ee73faa619bd06473d98fe22f6f0ae2e3adf4a40794ed83d9b4821d3268352e0a1ff24624bbdb58f91f71230b3cdf26a69b4219791343eef6c8473ea6263531ddf54256537bdde322b0fc18838f4a5399cd812fbd972595c75db02e078dc2a2f53335b7d824176d96d0abc5a1f26559667b6dcc180c0321d68222dfdc0dc15d325c33d1536f97e6c8a53e1b7d421884cc6ea64e2f4689621179121394e9e97fda6072cfd34d9f32025672d8f0ecce9bf7ec9e2144dea29673cd2cba5491c47c8603ba05a894fa92ffa1d758109d60f05b2c984a918d4d0830a732eb3aaddb967483588d918794f6a9f38da74b0415d3866e1abd94a30b1b09544553542e434f5250a4133011a003020101a10a30081b0676696374696da58204306182042c30820428a003020105a10b1b09544553542e434f5250a21e301ca003020102a11530131b066b72627467741b09544553542e434f5250a38203f2308203eea003020112a103020102a28203e0048203dce5f6db8e3c92a1f857ed0002a7ed9a30f85ef0aa9e08560e0128b17508ca36eda097ac98266da80129d578bd8af033b8378db62d256a50e665f0cdcf8175eb5fcf9a37fe101ecf816c6206595ac612b52680cf2a29aed78b68b56aae12c3367a79d5f3dd973d8cefb6ebc53ed9e1768ebb71e11f980ee75818bd86cdcd8213c1b12314b592429ea0975adc70cff2e871e12f60ecf8c1a05b95c280be491eb61bf5bab8603e9e60a8eafd16650deaac640a4f26de115d2837e1078a758129bc2d479c63534b44dfebbbdbfc8e5002017c46a1d1bd6066d7d28e902bb4b59800f9dcac9dd3a39d47d413daaf5f97e19ae125a9e547122b04abb7b05d4d72bafbd154c5407d7caa8d861e2ea64ee0fdcc8f1d777734f32cdad37898049bcc23c84968101738e887678238099d21ab14e10562d6c11933ff288394a4e3f501a078faff41eea0567262f304842796a913a6d3e4c845cd7f919da7702ea4077a71acac00778ce2994a10acc38bc9a1f88dc86f8646a08877af8708404d5bebf180986a9518d40e3f8bbffd324372617531f9a541b1f12c25fe680e29d5e6ea7cf4efca55848c9719f880099bfda9d8363db1847ad570cc9d110cce8fbd1073adea8a1d000482930c07e91e9e1791dc85caf267ea9a6dd69151ad8d542aca85ed3cb106eed8f173acddb7313b71a99f9cb490ec98cbd38e18504db29ae0f3b5d14602593730e9e5acacc49b892e7257dcf01cf68d08f921e9ae2c8ebbe790887a2038505f00f8fd9281581415096450a591af4f993b10f11dbf74598614e706664ba398b065f9263f0fd92e210575c647b3571147e207f3af51cd990a6bdfb501de55a15e6be55c63435bfc8336dfb367a7ea9b0673bfaafe9eeb67fd3e78aa5fd57f662449ce2be1032693504b3277da419a2dc20c28d3481bd4e2a02a3a23bfd690634cd596b22a34af1514c9a28ae8daa5757ad25a8d9f871ea5b9ea613171e1949f322045309877fa930cf5cb39c144e960b7e2a27d5a1dac8e7857c0cdc5548502b9352c0d3d71ba7a24a1fb3bc8dcf5786750abf8b57caeca7e9854e84c3fd85fe561c78568879191e29388d246185d4e9fd9e85907a71830bbe63a7270ad68523f940507ae322a7750c5f3aeda561b1bb3aed043557fc5023b1eba66db649753bb3099a9fde06be697c743a0954825c5ae4b3eab89ba86893365b65a9267f3b0c52a0198952512d12d044f47db039b0feba44f0d4cdc2c2aaab9dd86c568c73afa48d518e3e22b208d48d712554f11eedc5af8df587352d521dcb1c7bc52533f4752b477f922021777c014648853090202df6c7bcdd15329e83eb0688e0dafd0e7f4dcd5a5c27c9f2c1ea2d84d952a46c63398400b2d84ca322ea9b5a682016c30820168a003020112a103020103a282015a048201560efd8839a038e5399968a534391f82ce15d602d3195d26c7bcc6d954980c1fe80cb83d220610553a87e352899542077e4cd431b2cb0e4944eae0c8c85c3e7214a479220c84da70c4a48d8b4dc3ea8c9da34ee36c775b7b30a227c311f2a5ed8046a98d87d2ae113fbc37c0283a46ea50ba9bc0f33d902f7649350b6120ff794e3f6a4608f3ec482fe45001b442958bed6da03a5518a701180f49c215edd8a1c38865a33cff928bb1b82819986326bb572122cc9f7bdab019175a73c0b3aa85df44e1ca2c1d516eeeba17443ea28d019136bef31d6b14a600db9d8211ba9827ba54fc1df68286060dff2a89bd4653c0b18a135d15dd922bc390cadd0c5fe7592ad97bdd1387c5269351bcaa4f6043cd3cad3fbbd577648ee2d9e32711c24d1739e004b1241b9d7caa1007c3d81999a01238362a7d680153301c6562aa523b8673afc5571d96c3afad8e01f390ef14d48dc2843182eab9'
    )
    asrep = AS_REP.load(asrep_data).native

    encfastrep = None
    for padata in asrep['padata']:
        if padata['padata-type'] == 136:
            armoreddata = PA_FX_FAST_REPLY.load(padata['padata-value']).native
            encfastrep = armoreddata['enc-fast-rep']

    cipherText = encfastrep['cipher']
    armor_key = Key(_enctype_table[encfastrep['etype']].enctype,
                    armor_key_bytes)
    krbfastrep_dec_data = _enctype_table[encfastrep['etype']].decrypt(
        armor_key, 52, cipherText)
    krbfastrep_dec = KrbFastResponse.load(krbfastrep_dec_data).native

    pprint(krbfastrep_dec)
    print('krbfastrep_dec sucsess dec')
    strengthen_key = Key(
        _enctype_table[krbfastrep_dec['strengthen-key']['keytype']].enctype,
        krbfastrep_dec['strengthen-key']['keyvalue'])
    computer_subkey = Key(
        _enctype_table[krbfastrep_dec['strengthen-key']['keytype']].enctype,
        computer_subkey_bytes)
    #dunno_key = cf2(krbfastrep_dec['strengthen-key']['keytype'], strengthen_key, computer_subkey, b"strengthenkey", b"replykey")

    cipherText = asrep['enc-part']['cipher']
    ku = None
    for i in range(100):
        try:
            armor_key = Key(_enctype_table[encfastrep['etype']].enctype,
                            armor_key)
            tgt_encpart = _enctype_table[encfastrep['etype']].decrypt(
                strengthen_key, i, cipherText)
            tgt_encpart_dec = EncTGSRepPart.load(tgt_encpart).native
            ku = i
            pprint(tgt_encpart_dec)
            input()
        except:
            continue

    input(ku)

    return krbfastrep_dec['strengthen-key'][
        'keyvalue'], krbfastrep_dec, armor_key
Пример #4
0
    def tgt_from_ccache(self, override_etype=None):
        try:
            if self.ccache is None:
                raise Exception('No CCACHE file found')

            our_user = str(
                self.usercreds.username) + '@' + self.usercreds.domain
            for tgt, keystruct in self.ccache.get_all_tgt():
                ticket_for = tgt['cname']['name-string'][0] + '@' + tgt[
                    'crealm']
                if ticket_for.upper() == our_user.upper():
                    logger.debug('Found TGT for user %s' % our_user)
                    self.kerberos_TGT = tgt
                    self.kerberos_TGT_encpart = tgt['enc-part']
                    self.kerberos_session_key = Key(keystruct['keytype'],
                                                    keystruct['keyvalue'])
                    self.kerberos_cipher = _enctype_table[keystruct['keytype']]
                    self.kerberos_cipher_type = keystruct['keytype']

                    return True, None

            logger.debug('No TGT found for user %s' % our_user)
            raise Exception('No TGT found for user %s' % our_user)

        except Exception as e:
            return None, e
Пример #5
0
def decrypt_fast_as_req(session_key):
    #### trying to decrpyt the AS-REQ with user's password + tgt subkey key from the machine account
    client_as_req = bytes.fromhex(
        '6a8207903082078ca103020105a20302010aa38206d3308206cf308206cba10402020088a28206c1048206bda08206b9308206b5a08205323082052ea003020101a1820525048205216e82051d30820519a003020105a10302010ea20703050000000000a38204586182045430820450a003020105a10b1b09544553542e434f5250a21e301ca003020102a11530131b066b72627467741b09544553542e434f5250a382041a30820416a003020112a103020102a2820408048204048c76c7670f689ef1742dedd3c16c0043521cf2a3ca5f6fef84b760e97a452ef70ad69d028cd0c0aa1d0692421b74f7c102d338e35ebcba3d96554bc013a3f23d841cc570506d457acd7a519e79c32fc3ac443b687599be74ce59346aba831983d8da4a24e5c1d8d0758bae89cc34ecdd1754e51bb527c7171086897faa611b6f5f501eebf0a488cd4b07e0c7859c67cc000dce6b9c8945c3ead8d6786663ab585b30e86f51935e6ac5a0c813c567d03d2d9a6ad7b67d2f77098582bd80e0c81c1367f865f41a027d628ac4874036e0face8362c2375fedabcbf6ca98a02dd693cfa96d840367b15a02a3582abbee29d70a55d785f50370fc0e1b6ba349dc3c79d498fbc46ce4f3947ae94c4d9f5c2791ec4824835c55f34983aa30cb22d892b4764f4746c8e9231ada10c9eb3dfdb3ad21c89102d009539164e5f64b79490605954f5298bcf7eaedb1498620a5f06f075be7f1d6ca22a4a788a9af7e4f8ee4202951a5511d62b99177893102c5654b7cdd3d402b44105fe4daaca98429cac4eb51fa7879512427a813db032a610724ea8648263f592c2f4dd934f2b7e53419c75b371e6a7dc9636d2538a8cd74e36041e8755c018eb9d51b1f4e5ea25db3c576c8a9db7b6c019f9ae550f0704b2eaaae489bf42274217982063fc6498fe638698feab668a8f4a189dc7b762bc79eda23be1afbee6717930dca827d270d220a265d7dc25d31ca54b24e518c5f6a95ed3b53adc4512838d63c75d037b75049fc604f92620e46f1a9ba49fae3015c0431c57e7981bb7a97f3115ea865206ada7300e2ff1c87728c587fb64f6d31ef746623d454bafb54fb451eb5bdae84ef445483a255f20eb28a345afc245f8fea7eefca583379c2935b9f6b31c759a2ca1b1d7df33c86b187e56aa8dd6edb139bc4d26a53cce1d236a18276e32c135d05fbc36e3d9c310cb36892fc2c9d7716bb3fae2b788986869d92af5379d5e5e334b00b31bbc0f7f1957051c144b45f297a0bb2ce07c1f65d57931662cc3aea530bc4f0228c6653effde024e0a4096ba5e0ad5b8964a2042733ce290c36e604820a6f9be00aa4652f119a0972763ed264d45675b10cc025633fcf873d10bc2855086e8beaf428c6ee9f16e93718477f21b643eb2459b5222587395e8d5da9f6d31ffee7088295e65de747823e74da93df9a35eabbf93f7267ea79f0557fb8896f9004af99f42aed55510d169bbabd3e0bd4c517fa30bb396e31182685479ef96b78146a40597927d62d9fc044d257b63e7db6977598871f755ef36b5b9ff4b9ef1e6cb2255a51c57f408f89df9ad50b7ef2d243ca86b0fe0376c47813e305463d6aa081e70ee9f4f677934f74018b8d0a701e4d4c080ae61b698d78b3a5bb116035b52c0575878bb29b4b91848e84844b6e7118086e639ace845bc028cac48c8765fcf0970ee045a2a481a73081a4a003020112a2819c048199f363e352e88f51743ffa449016a24aeab84f4be14dc24216bfa48837cc4c0c3327580a0caa498e8674d283711bae53eceb367b03e39b3975fb76b820f053f5c2830bdc2fc672d30be07fce88a7bfad85ad5f1470594db2c61b725223103eb3a08de787d3eabbc9a395eb4fabe3062dde554fa8825629fd395903377a095e64c58e22d114aea20741d1717c394353f8696888b4b9308bd1f4e1a1173015a003020110a10e040c5783dcf20fb734229e49def5a28201623082015ea003020112a282015504820151883af50c6bc8bd5ba10a4ed6688ad248057271a5b06405639631c7ca00311f005f6932155536d5e80ed9ef398589703a24c6093415d8c7e1b5a6bd0c47f501b290e6ca0d9f0d8dd3d61fc04090dae610e4e92cbfd9b1568dfb80058a76897065a262ffca403c62b7442ce419936a3b7a8581cbb3f61e09fa0d5dc1f0d9444fb65f3090013d1377a8438e0de04a8c81805131e882985e112204639bcc24ef66624a31b8121fdc3c357b2c389f98523d1ffbeae85a38a3b461cdd6160f518faf86b9f83f95cfe8217dcae43c062405328791368d84674eea1c3d32801e38e96fde33fbb8cff068149b3d668b0720ec3bd90a69fb77965f6b092c4d93f7bc341a1abef7c1bda73680251ddc7f58643a92108ce7fdcfe07e0ae4f12f751b1a1d01b1d450699df65a2fcfb9144ca25ad45bf5eec2402166978114526ff97d5e05b5f0487a612bab979d00cfe08ee5e3e5ea7b5aa481a83081a5a00703050040810010a1133011a003020101a10a30081b0676696374696da2061b0454455354a3193017a003020102a110300e1b066b72627467741b0454455354a511180f32303337303931333032343830355aa611180f32303337303931333032343830355aa706020461d2923ea81530130201120201110201170201180202ff79020103a91d301b3019a003020114a11204104f56455250524f544543544544202020'
    )
    client_as_req_native = AS_REQ.load(client_as_req).native

    encfastreq = None
    armor_native = None  # at this point this is a AS_REP ticket which was obtained using the machine account. This ticket is used here to identify the correct sub-key to be used.
    for padata in client_as_req_native['padata']:
        if padata['padata-type'] == 136:
            armoreddata = PA_FX_FAST_REQUEST.load(
                padata['padata-value']).native
            encfastreq = armoreddata['enc-fast-req']
            armortype = armoreddata['armor']['armor-type']
            if armortype != 1:
                raise Exception('AS_REQ must have armortype = 1')
            armor_native = AP_REQ.load(
                armoreddata['armor']['armor-value']).native

    #### First we need to obtain the subkey from the 'armor' part of the PA-FX-FAST PADATA section. This is actually an AP_REQ structure that holds the Authenticator (encrypted with the TGT session key recieved using the machine account) which holds the subkey. This subkey is used together with the machine account session key to form the armorkey.

    authenticator = decrypt_authenticator(
        armor_native['authenticator']['etype'],
        armor_native['authenticator']['cipher'], session_key)
    computer_subkey_type = authenticator['subkey']['keytype']
    computer_subkey_bytes = authenticator['subkey']['keyvalue']

    #### now that we have the subkey, we can create the armor-key and using it we can decrypt the KrbFastReq structure which will contain the (normal) AS_REQ with the encrypted timestamp used for preauth
    cipherText = encfastreq['cipher']
    computer_session_key = Key(_enctype_table[encfastreq['etype']].enctype,
                               session_key)
    client_authenticator_subkey = Key(
        _enctype_table[encfastreq['etype']].enctype, computer_subkey_bytes)

    armor_key = cf2(encfastreq['etype'], client_authenticator_subkey,
                    computer_session_key, b"subkeyarmor", b"ticketarmor")

    krbfastreq_dec_data = _enctype_table[encfastreq['etype']].decrypt(
        armor_key, 51, cipherText)
    krbfastreq_dec = KrbFastReq.load(krbfastreq_dec_data).native

    pprint(krbfastreq_dec)
    print('krbfastreq_dec sucsess dec')

    return armor_key.contents, decrypt_fast_as_req
Пример #6
0
	async def authenticate(self, authData = None, flags = ISC_REQ.CONNECTION, seq_number = 0, is_rpc = False):
		try:
			if is_rpc == True:
				if self.iterations == 0:
					flags = ISC_REQ.CONFIDENTIALITY | \
							ISC_REQ.INTEGRITY | \
							ISC_REQ.MUTUAL_AUTH | \
							ISC_REQ.REPLAY_DETECT | \
							ISC_REQ.SEQUENCE_DETECT|\
							ISC_REQ.USE_DCE_STYLE
					
					
					status, ctxattr, apreq, err = await self.ksspi.authenticate('KERBEROS', '', 'cifs/%s' % self.settings.target, 3, flags.value, authdata = b'')
					if err is not None:
						raise err
					self.iterations += 1
					return apreq, True, None
				
				elif self.iterations == 1:
					status, ctxattr, data, err = await self.ksspi.authenticate('KERBEROS', '','cifs/%s' % self.settings.target, 3, flags.value, authdata = authData)
					if err is not None:
						return None, None, err
					self.session_key, err = await self.ksspi.get_sessionkey()
					if err is not None:
						return None, None, err
						
					aprep = AP_REP.load(data).native
					subkey = Key(aprep['enc-part']['etype'], self.session_key)
					self.gssapi = get_gssapi(subkey)

					if aprep['enc-part']['etype'] != 23: #no need for seq number in rc4
						raw_seq_data, err = await self.ksspi.get_sequenceno()
						if err is not None:
							return None, None, err
						self.seq_number = GSSWrapToken.from_bytes(raw_seq_data[16:]).SND_SEQ
					
					self.iterations += 1
					await self.ksspi.disconnect()
					return data, False, None
					
				else:
					raise Exception('SSPI Kerberos -RPC - auth encountered too many calls for authenticate.')
			
				
			else:
				status, ctxattr, apreq, err = await self.ksspi.authenticate('KERBEROS', '','cifs/%s' % self.settings.target, 3, flags.value, authdata = b'')
				if err is not None:
					return None, None, err
				
				self.session_key, err = await self.ksspi.get_sessionkey()
				if err is not None:
					raise err
				await self.ksspi.disconnect()

				return apreq, False, None
		except Exception as e:
			return None, None, e
Пример #7
0
    def get_tgt(self, target=None):
        if target is None:
            logon = get_logon_info()
            if logon['logonserver'] is None:
                raise Exception(
                    'Failed to get logonserver and no target was specified! This wont work.'
                )
            target = 'cifs/%s' % logon['logonserver']

        ctx = AcquireCredentialsHandle(None, 'kerberos', target,
                                       SECPKG_CRED.OUTBOUND)
        res, ctx, data, outputflags, expiry = InitializeSecurityContext(
            ctx,
            target,
            token=None,
            ctx=ctx,
            flags=ISC_REQ.DELEGATE | ISC_REQ.MUTUAL_AUTH
            | ISC_REQ.ALLOCATE_MEMORY)

        if res == SEC_E.OK or res == SEC_E.CONTINUE_NEEDED:
            #key_data = sspi._get_session_key()
            raw_ticket = self.export_ticketdata_target(0, target)
            key = Key(raw_ticket['Key']['KeyType'], raw_ticket['Key']['Key'])
            token = InitialContextToken.load(data[0][1])
            ticket = AP_REQ(token.native['innerContextToken']).native
            cipher = _enctype_table[ticket['authenticator']['etype']]
            dec_authenticator = cipher.decrypt(
                key, 11, ticket['authenticator']['cipher'])
            authenticator = Authenticator.load(dec_authenticator).native
            if authenticator['cksum']['cksumtype'] != 0x8003:
                raise Exception('Checksum not good :(')

            checksum_data = AuthenticatorChecksum.from_bytes(
                authenticator['cksum']['checksum'])
            if ChecksumFlags.GSS_C_DELEG_FLAG not in checksum_data.flags:
                raise Exception('delegation flag not set!')

            cred_orig = KRB_CRED.load(checksum_data.delegation_data).native
            dec_authenticator = cipher.decrypt(key, 14,
                                               cred_orig['enc-part']['cipher'])
            #info = EncKrbCredPart.load(dec_authenticator).native

            #reconstructing kirbi with the unencrypted data
            te = {}
            te['etype'] = 0
            te['cipher'] = dec_authenticator
            ten = EncryptedData(te)

            t = {}
            t['pvno'] = cred_orig['pvno']
            t['msg-type'] = cred_orig['msg-type']
            t['tickets'] = cred_orig['tickets']
            t['enc-part'] = ten

            cred = KRB_CRED(t)
            return cred.dump()
Пример #8
0
	async def authenticate(self, authData = None, flags = None, seq_number = 0, is_rpc = False):
		#authdata is only for api compatibility reasons
		if self.ksspi is None:
			await self.start_remote_kerberos()
		try:
			if is_rpc == True:
				if self.iterations == 0:
					flags = ISC_REQ.CONFIDENTIALITY | \
							ISC_REQ.INTEGRITY | \
							ISC_REQ.MUTUAL_AUTH | \
							ISC_REQ.REPLAY_DETECT | \
							ISC_REQ.SEQUENCE_DETECT|\
							ISC_REQ.USE_DCE_STYLE
					
					apreq, res = await self.ksspi.authenticate('cifs/%s' % self.settings.target, flags = str(flags.value))

					self.iterations += 1
					return apreq, True, None
				
				elif self.iterations == 1:
					data, err = await self.ksspi.authenticate('cifs/%s' % self.settings.target, flags = str(flags.value), token_data = authData)
					if err is not None:
						return None, None, err
					self.session_key, err = await self.ksspi.get_session_key()
					if err is not None:
						return None, None, err
						
					aprep = AP_REP.load(data).native
					subkey = Key(aprep['enc-part']['etype'], self.session_key)
					self.gssapi = get_gssapi(subkey)

					if aprep['enc-part']['etype'] != 23: #no need for seq number in rc4
						raw_seq_data, err = await self.ksspi.get_seq_number()
						if err is not None:
							return None, None, err
						self.seq_number = GSSWrapToken.from_bytes(raw_seq_data[16:]).SND_SEQ
					
					self.iterations += 1
					await self.ksspi.disconnect()
					return data, False, None
					
				else:
					raise Exception('SSPI Kerberos -RPC - auth encountered too many calls for authenticate.')
			
				
			else:
				apreq, res = await self.ksspi.authenticate('cifs/%s' % self.settings.target)
				#print('MULTIPLEXOR KERBEROS SSPI, APREQ: %s ERROR: %s' % (apreq, res))
				if res is None:
					self.session_key, res = await self.ksspi.get_session_key()
					await self.ksspi.disconnect()

				return apreq, res, None
		except Exception as e:
			return None, None, err
Пример #9
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        #authdata is only for api compatibility reasons
        if is_rpc == True:
            if self.iterations == 0:
                flags = ISC_REQ.CONFIDENTIALITY | \
                  ISC_REQ.INTEGRITY | \
                  ISC_REQ.MUTUAL_AUTH | \
                  ISC_REQ.REPLAY_DETECT | \
                  ISC_REQ.SEQUENCE_DETECT|\
                  ISC_REQ.USE_DCE_STYLE

                token = self.ksspi.get_ticket_for_spn(self.target,
                                                      flags=flags,
                                                      is_rpc=True,
                                                      token_data=authData)
                #print(token.hex())
                self.iterations += 1
                return token, True

            elif self.iterations == 1:
                flags = ISC_REQ.USE_DCE_STYLE

                token = self.ksspi.get_ticket_for_spn(self.target,
                                                      flags=flags,
                                                      is_rpc=True,
                                                      token_data=authData)
                #print(token.hex())

                aprep = AP_REP.load(token).native

                subkey = Key(aprep['enc-part']['etype'],
                             self.get_session_key())

                cipher_text = aprep['enc-part']['cipher']
                cipher = _enctype_table[aprep['enc-part']['etype']]()

                plaintext = cipher.decrypt(subkey, 12, cipher_text)

                self.gssapi = get_gssapi(subkey)

                self.iterations += 1
                return token, False

            else:
                raise Exception(
                    'SSPI Kerberos -RPC - auth encountered too many calls for authenticate.'
                )

        else:
            apreq = self.ksspi.get_ticket_for_spn(self.target)
            return apreq, False
Пример #10
0
	def from_tgt(target, tgt, key):
		"""
		Sets up the kerberos object from tgt and the session key.
		Use this function when pulling the TGT from ccache file.
		"""
		kc = KerbrosClient(None, target)
		kc.kerberos_TGT = tgt
		
		kc.kerberos_cipher_type = key['keytype']
		kc.kerberos_session_key = Key(kc.kerberos_cipher_type, key['keyvalue']) 
		kc.kerberos_cipher = _enctype_table[kc.kerberos_cipher_type]
		return kc
Пример #11
0
def decrypt_authenticator(authenticator_enc_type,
                          authenticator_enc_data,
                          key_bytes,
                          key_usage=11):
    cipherText = authenticator_enc_data
    kerberos_key = Key(_enctype_table[authenticator_enc_type].enctype,
                       key_bytes)
    authenticator_data_dec = _enctype_table[authenticator_enc_type].decrypt(
        kerberos_key, key_usage, cipherText)
    authenticator_dec_native = Authenticator.load(
        authenticator_data_dec).native
    return authenticator_dec_native
Пример #12
0
	def build_asreq_lts(self, supported_encryption_method, kdcopts = ['forwardable','renewable','proxiable']):
		logger.debug('Constructing TGT request with auth data')
		#now to create an AS_REQ with encrypted timestamp for authentication
		pa_data_1 = {}
		pa_data_1['padata-type'] = int(PADATA_TYPE('PA-PAC-REQUEST'))
		pa_data_1['padata-value'] = PA_PAC_REQUEST({'include-pac': True}).dump()
		
		now = datetime.datetime.now(datetime.timezone.utc)
		#creating timestamp asn1
		timestamp = PA_ENC_TS_ENC({'patimestamp': now.replace(microsecond=0), 'pausec': now.microsecond}).dump()
		
		
		logger.debug('Selecting common encryption type: %s' % supported_encryption_method.name)
		self.kerberos_cipher = _enctype_table[supported_encryption_method.value]
		self.kerberos_cipher_type = supported_encryption_method.value
		self.kerberos_key = Key(self.kerberos_cipher.enctype, self.usercreds.get_key_for_enctype(supported_encryption_method, salt = self.server_salt))
		enc_timestamp = self.kerberos_cipher.encrypt(self.kerberos_key, 1, timestamp, None)
		
		
		pa_data_2 = {}
		pa_data_2['padata-type'] = int(PADATA_TYPE('ENC-TIMESTAMP'))
		pa_data_2['padata-value'] = EncryptedData({'etype': supported_encryption_method.value, 'cipher': enc_timestamp}).dump()
		
		kdc_req_body = {}
		kdc_req_body['kdc-options'] = KDCOptions(set(kdcopts))
		kdc_req_body['cname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': [self.usercreds.username]})
		kdc_req_body['realm'] = self.usercreds.domain.upper()
		kdc_req_body['sname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': ['krbtgt', self.usercreds.domain.upper()]})
		kdc_req_body['till'] = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['rtime'] = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['nonce'] = secrets.randbits(31)
		kdc_req_body['etype'] = [supported_encryption_method.value] #selecting according to server's preferences
		
		kdc_req = {}
		kdc_req['pvno'] = krb5_pvno
		kdc_req['msg-type'] = MESSAGE_TYPE.KRB_AS_REQ.value
		kdc_req['padata'] = [pa_data_2,pa_data_1]
		kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)
		
		return AS_REQ(kdc_req)
Пример #13
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           cb_data=None):
        #authdata is only for api compatibility reasons
        if self.ksspi is None:
            await self.start_remote_kerberos()
        try:
            apreq, res = await self.ksspi.authenticate(
                self.settings.target.to_target_string(),
                flags=str(self.flags.value))
            #print('MULTIPLEXOR KERBEROS SSPI, APREQ: %s ERROR: %s' % (apreq, res))
            if res is not None:
                return None, None, res

            # here it seems like we get the full token not just the apreq data...
            # so we need to discard the layers

            self.session_key, err = await self.ksspi.get_session_key()
            if err is not None:
                return None, None, err

            unwrap = KRB5_MECH_INDEP_TOKEN.from_bytes(apreq)
            aprep = AP_REQ.load(unwrap.data[2:]).native
            subkey = Key(aprep['ticket']['enc-part']['etype'],
                         self.session_key)
            self.gssapi = get_gssapi(subkey)

            if aprep['ticket']['enc-part']['etype'] != 23:
                raw_seq_data, err = await self.ksspi.get_seq_number()
                if err is not None:
                    return None, None, err
                self.seq_number = GSSWrapToken.from_bytes(
                    raw_seq_data[16:]).SND_SEQ

            return unwrap.data[2:], False, res
        except Exception as e:
            return None, None, e
Пример #14
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           cb_data=None):
        try:
            status, ctxattr, apreq, err = await self.sspi.authenticate(
                'KERBEROS',
                '',
                self.settings.target.to_target_string(),
                3,
                self.flags.value,
                authdata=b'')
            if err is not None:
                raise err

            self.flags = ISC_REQ(ctxattr)

            self.session_key, err = await self.sspi.get_sessionkey()
            if err is not None:
                return None, None, err

            unwrap = KRB5_MECH_INDEP_TOKEN.from_bytes(apreq)
            aprep = AP_REQ.load(unwrap.data[2:]).native
            subkey = Key(aprep['ticket']['enc-part']['etype'],
                         self.session_key)
            self.gssapi = get_gssapi(subkey)

            if aprep['ticket']['enc-part']['etype'] != 23:
                if ISC_REQ.CONFIDENTIALITY in self.flags:
                    raw_seq_data, err = await self.sspi.get_sequenceno()
                    if err is not None:
                        return None, None, err
                    self.seq_number = GSSWrapToken.from_bytes(
                        raw_seq_data[16:]).SND_SEQ

            return unwrap.data[2:], False, None
        except Exception as e:
            return None, None, e
Пример #15
0
    async def authenticate(self,
                           authData,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        try:

            if self.kc is None:
                _, err = await self.setup_kc()
                if err is not None:
                    return None, None, err

            if self.iterations == 0:
                try:
                    #check TGS first, maybe ccache already has what we need
                    for target in self.ccred.ccache.list_targets():
                        # just printing this to debug...
                        logger.debug('CCACHE target SPN record: %s' % target)
                    tgs, encpart, self.session_key = await self.kc.get_TGS(
                        self.spn)

                    self.from_ccache = True
                except Exception as e:
                    # this is normal when no credentials stored in ccache
                    #tgt = await self.kc.get_TGT(override_etype=[18])
                    tgt = await self.kc.get_TGT()
                    tgs, encpart, self.session_key = await self.kc.get_TGS(
                        self.spn)

            ap_opts = []
            if is_rpc == True:
                if self.iterations == 0:
                    ap_opts.append('mutual-required')
                    flags = ChecksumFlags.GSS_C_CONF_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG | ChecksumFlags.GSS_C_SEQUENCE_FLAG|\
                      ChecksumFlags.GSS_C_REPLAY_FLAG | ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_DCE_STYLE

                    if self.from_ccache is False:
                        apreq = self.kc.construct_apreq(tgs,
                                                        encpart,
                                                        self.session_key,
                                                        flags=flags,
                                                        seq_number=seq_number,
                                                        ap_opts=ap_opts)
                    else:
                        apreq = self.kc.construct_apreq_from_ticket(
                            Ticket(tgs['ticket']).dump(),
                            self.session_key,
                            tgs['crealm'],
                            tgs['cname']['name-string'][0],
                            flags=flags,
                            seq_number=seq_number,
                            ap_opts=ap_opts,
                            cb_data=None)

                    self.iterations += 1
                    return apreq, False, None

                else:
                    #mutual authentication part here
                    self.seq_number = seq_number

                    aprep = AP_REP.load(authData).native
                    cipher = _enctype_table[int(aprep['enc-part']['etype'])]()
                    cipher_text = aprep['enc-part']['cipher']
                    temp = cipher.decrypt(self.session_key, 12, cipher_text)

                    enc_part = EncAPRepPart.load(temp).native
                    cipher = _enctype_table[int(
                        enc_part['subkey']['keytype'])]()

                    now = datetime.datetime.now(datetime.timezone.utc)
                    apreppart_data = {}
                    apreppart_data['cusec'] = now.microsecond
                    apreppart_data['ctime'] = now.replace(microsecond=0)
                    apreppart_data['seq-number'] = enc_part['seq-number']
                    #print('seq %s' % enc_part['seq-number'])

                    apreppart_data_enc = cipher.encrypt(
                        self.session_key, 12,
                        EncAPRepPart(apreppart_data).dump(), None)

                    #overriding current session key
                    self.session_key = Key(cipher.enctype,
                                           enc_part['subkey']['keyvalue'])

                    ap_rep = {}
                    ap_rep['pvno'] = 5
                    ap_rep['msg-type'] = MESSAGE_TYPE.KRB_AP_REP.value
                    ap_rep['enc-part'] = EncryptedData({
                        'etype':
                        self.session_key.enctype,
                        'cipher':
                        apreppart_data_enc
                    })

                    token = AP_REP(ap_rep).dump()
                    self.gssapi = get_gssapi(self.session_key)
                    self.iterations += 1

                    return token, False, None
            else:
                if self.from_ccache is False:
                    apreq = self.kc.construct_apreq(tgs,
                                                    encpart,
                                                    self.session_key,
                                                    flags=flags,
                                                    seq_number=seq_number,
                                                    ap_opts=ap_opts)
                else:
                    apreq = self.kc.construct_apreq_from_ticket(
                        Ticket(tgs['ticket']).dump(),
                        self.session_key,
                        tgs['crealm'],
                        tgs['cname']['name-string'][0],
                        flags=flags,
                        seq_number=seq_number,
                        ap_opts=ap_opts,
                        cb_data=None)
                return apreq, False, None

        except Exception as e:
            return None, None, e
Пример #16
0
	def get_TGT(self, override_etype = None, decrypt_tgt = True):
		"""
		decrypt_tgt: used for asreproast attacks
		Steps performed:
			1. Send and empty (no encrypted timestamp) AS_REQ with all the encryption types we support
			2. Depending on the response (either error or AS_REP with TGT) we either send another AS_REQ with the encrypted data or return the TGT (or fail miserably)
			3. PROFIT
		"""
		logger.debug('[getTGT] Generating initial TGT without authentication data')
		now = datetime.datetime.now(datetime.timezone.utc)
		kdc_req_body = {}
		kdc_req_body['kdc-options'] = KDCOptions(set(['forwardable','renewable','proxiable']))
		kdc_req_body['cname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': [self.usercreds.username]})
		kdc_req_body['realm'] = self.usercreds.domain.upper()
		kdc_req_body['sname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': ['krbtgt', self.usercreds.domain.upper()]})
		kdc_req_body['till']  = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['rtime'] = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['nonce'] = secrets.randbits(31)
		if override_etype is None:
			kdc_req_body['etype'] = self.usercreds.get_supported_enctypes()
		else:
			kdc_req_body['etype'] = override_etype

		pa_data_1 = {}
		pa_data_1['padata-type'] = int(PADATA_TYPE('PA-PAC-REQUEST'))
		pa_data_1['padata-value'] = PA_PAC_REQUEST({'include-pac': True}).dump()
		
		kdc_req = {}
		kdc_req['pvno'] = krb5_pvno
		kdc_req['msg-type'] = MESSAGE_TYPE.KRB_AS_REQ.value
		kdc_req['padata'] = [pa_data_1]
		kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)

		req = AS_REQ(kdc_req)	
		
		logger.debug('[getTGT] Sending initial TGT to %s' % self.ksoc.get_addr_str())
		rep = self.ksoc.sendrecv(req.dump(), throw = False)

		if rep.name != 'KRB_ERROR':
			#user can do kerberos auth without preauthentication!
			self.kerberos_TGT = rep.native

			etype = self.kerberos_TGT['enc-part']['etype']

			#if we want to roast the asrep (tgt rep) part then we dont even have the proper keys to decrypt
			#so we just return, the asrep can be extracted from this object anyhow
			if decrypt_tgt == False:
				return

			self.kerberos_cipher = _enctype_table[etype]
			self.kerberos_cipher_type = etype
			encryption_type = EncryptionType(self.kerberos_cipher.enctype)
			enctype = self.usercreds.get_key_for_enctype(encryption_type)
			self.kerberos_key = Key(self.kerberos_cipher.enctype, enctype)
			
		else:
			if rep.native['error-code'] != KerberosErrorCode.KDC_ERR_PREAUTH_REQUIRED.value:
				raise KerberosError(rep)
			rep = rep.native
			logger.debug('[getTGT] Got reply from server, asking to provide auth data')
			
			rep = self.do_preauth(rep)
			logger.debug('[getTGT] Got valid response from server')
			rep = rep.native
			self.kerberos_TGT = rep

		cipherText = self.kerberos_TGT['enc-part']['cipher']
		temp = self.kerberos_cipher.decrypt(self.kerberos_key, 3, cipherText)
		try:
			self.kerberos_TGT_encpart = EncASRepPart.load(temp).native
		except Exception as e:
			logger.debug('[getTGT] EncAsRepPart load failed, is this linux?')
			try:
				self.kerberos_TGT_encpart = EncTGSRepPart.load(temp).native
			except Exception as e:
				logger.error('[getTGT] Failed to load decrypted part of the reply!')
				raise e
				
		self.kerberos_session_key = Key(self.kerberos_cipher.enctype, self.kerberos_TGT_encpart['key']['keyvalue'])
		self.ccache.add_tgt(self.kerberos_TGT, self.kerberos_TGT_encpart, override_pp = True)
		logger.debug('[getTGT] Got valid TGT')
		
		return 
Пример #17
0
	def do_preauth(self, rep):
		#now getting server's supported encryption methods
		
		supp_enc_methods = collections.OrderedDict()
		for enc_method in METHOD_DATA.load(rep['e-data']).native:					
			data_type = PaDataType(enc_method['padata-type'])
			
			if data_type == PaDataType.ETYPE_INFO or data_type == PaDataType.ETYPE_INFO2:
				if data_type == PaDataType.ETYPE_INFO:
					enc_info_list = ETYPE_INFO.load(enc_method['padata-value'])
					
				elif data_type == PaDataType.ETYPE_INFO2:
					enc_info_list = ETYPE_INFO2.load(enc_method['padata-value'])
		
				for enc_info in enc_info_list.native:
					supp_enc_methods[EncryptionType(enc_info['etype'])] = enc_info['salt']
					logger.debug('Server supports encryption type %s with salt %s' % (EncryptionType(enc_info['etype']).name, enc_info['salt']))
		
		logger.debug('Constructing TGT request with auth data')
		#now to create an AS_REQ with encrypted timestamp for authentication
		pa_data_1 = {}
		pa_data_1['padata-type'] = int(PADATA_TYPE('PA-PAC-REQUEST'))
		pa_data_1['padata-value'] = PA_PAC_REQUEST({'include-pac': True}).dump()
		
		now = datetime.datetime.now(datetime.timezone.utc)
		#creating timestamp asn1
		timestamp = PA_ENC_TS_ENC({'patimestamp': now.replace(microsecond=0), 'pausec': now.microsecond}).dump()
		
		supp_enc = self.usercreds.get_preferred_enctype(supp_enc_methods)
		logger.debug('Selecting common encryption type: %s' % supp_enc.name)
		self.kerberos_cipher = _enctype_table[supp_enc.value]
		self.kerberos_cipher_type = supp_enc.value
		if 'salt' in enc_info and enc_info['salt'] is not None:
			self.server_salt = enc_info['salt'].encode() 
		self.kerberos_key = Key(self.kerberos_cipher.enctype, self.usercreds.get_key_for_enctype(supp_enc, salt = self.server_salt))
		enc_timestamp = self.kerberos_cipher.encrypt(self.kerberos_key, 1, timestamp, None)
		
		pa_data_2 = {}
		pa_data_2['padata-type'] = int(PADATA_TYPE('ENC-TIMESTAMP'))
		pa_data_2['padata-value'] = EncryptedData({'etype': supp_enc.value, 'cipher': enc_timestamp}).dump()
		
		kdc_req_body = {}
		kdc_req_body['kdc-options'] = KDCOptions(set(['forwardable','renewable','proxiable']))
		kdc_req_body['cname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': [self.usercreds.username]})
		kdc_req_body['realm'] = self.usercreds.domain.upper()
		kdc_req_body['sname'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': ['krbtgt', self.usercreds.domain.upper()]})
		kdc_req_body['till']  = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['rtime'] = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['nonce'] = secrets.randbits(31)
		kdc_req_body['etype'] = [supp_enc.value]

		kdc_req = {}
		kdc_req['pvno'] = krb5_pvno
		kdc_req['msg-type'] = MESSAGE_TYPE.KRB_AS_REQ.value
		kdc_req['padata'] = [pa_data_2,pa_data_1]
		kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)
		
		req = AS_REQ(kdc_req)
		
		logger.debug('Sending TGT request to server')
		return self.ksoc.sendrecv(req.dump())
Пример #18
0
    async def authenticate(self,
                           authData,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):

        if self.iterations == 0:
            #tgt = await self.kc.get_TGT(override_etype=[18])
            tgt = await self.kc.get_TGT()
            tgs, encpart, self.session_key = await self.kc.get_TGS(self.spn)
        ap_opts = []
        if is_rpc == True:
            if self.iterations == 0:
                ap_opts.append('mutual-required')
                flags = ChecksumFlags.GSS_C_CONF_FLAG | ChecksumFlags.GSS_C_INTEG_FLAG | ChecksumFlags.GSS_C_SEQUENCE_FLAG|\
                  ChecksumFlags.GSS_C_REPLAY_FLAG | ChecksumFlags.GSS_C_MUTUAL_FLAG | ChecksumFlags.GSS_C_DCE_STYLE

                apreq = self.kc.construct_apreq(tgs,
                                                encpart,
                                                self.session_key,
                                                flags=flags,
                                                seq_number=seq_number,
                                                ap_opts=ap_opts)
                self.iterations += 1
                return apreq, False

            else:
                #mutual authentication part here
                aprep = AP_REP.load(authData).native
                cipher = _enctype_table[int(aprep['enc-part']['etype'])]()
                cipher_text = aprep['enc-part']['cipher']
                temp = cipher.decrypt(self.session_key, 12, cipher_text)

                enc_part = EncAPRepPart.load(temp).native
                cipher = _enctype_table[int(enc_part['subkey']['keytype'])]()

                now = datetime.datetime.now(datetime.timezone.utc)
                apreppart_data = {}
                apreppart_data['cusec'] = now.microsecond
                apreppart_data['ctime'] = now.replace(microsecond=0)
                apreppart_data['seq-number'] = enc_part['seq-number']

                apreppart_data_enc = cipher.encrypt(
                    self.session_key, 12,
                    EncAPRepPart(apreppart_data).dump(), None)

                #overriding current session key
                self.session_key = Key(cipher.enctype,
                                       enc_part['subkey']['keyvalue'])

                ap_rep = {}
                ap_rep['pvno'] = 5
                ap_rep['msg-type'] = MESSAGE_TYPE.KRB_AP_REP.value
                ap_rep['enc-part'] = EncryptedData({
                    'etype': self.session_key.enctype,
                    'cipher': apreppart_data_enc
                })

                token = AP_REP(ap_rep).dump()
                self.gssapi = get_gssapi(self.session_key)
                self.iterations += 1

                return token, False
        else:
            apreq = self.kc.construct_apreq(tgs,
                                            encpart,
                                            self.session_key,
                                            flags=flags,
                                            seq_number=seq_number,
                                            ap_opts=ap_opts)
            return apreq, False
Пример #19
0
	def S4U2proxy(self, s4uself_ticket, spn_user, supp_enc_methods = [EncryptionType.DES_CBC_CRC,EncryptionType.DES_CBC_MD4,EncryptionType.DES_CBC_MD5,EncryptionType.DES3_CBC_SHA1,EncryptionType.ARCFOUR_HMAC_MD5,EncryptionType.AES256_CTS_HMAC_SHA1_96,EncryptionType.AES128_CTS_HMAC_SHA1_96]):
		logger.debug('[S4U2proxy] Impersonating %s' % '/'.join(spn_user.get_principalname()))
		now = datetime.datetime.now(datetime.timezone.utc)
		supp_enc = self.usercreds.get_preferred_enctype(supp_enc_methods)
		
		pa_pac_opts = {}
		pa_pac_opts['padata-type'] = int(PADATA_TYPE('PA-PAC-OPTIONS'))
		pa_pac_opts['padata-value'] = PA_PAC_OPTIONS({'value' : PA_PAC_OPTIONSTypes(set(['resource-based constrained delegation']))}).dump()

		
		authenticator_data = {}
		authenticator_data['authenticator-vno'] = krb5_pvno
		authenticator_data['crealm'] = Realm(self.kerberos_TGT['crealm'])
		authenticator_data['cname'] = self.kerberos_TGT['cname']
		authenticator_data['cusec'] = now.microsecond
		authenticator_data['ctime'] = now.replace(microsecond=0)
		
		authenticator_data_enc = self.kerberos_cipher.encrypt(self.kerberos_session_key, 7, Authenticator(authenticator_data).dump(), None)
		
		ap_req = {}
		ap_req['pvno'] = krb5_pvno
		ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
		ap_req['ap-options'] = APOptions(set())
		ap_req['ticket'] = Ticket(self.kerberos_TGT['ticket'])
		ap_req['authenticator'] = EncryptedData({'etype': self.kerberos_cipher_type, 'cipher': authenticator_data_enc})
		
		pa_tgs_req = {}
		pa_tgs_req['padata-type'] = PaDataType.TGS_REQ.value
		pa_tgs_req['padata-value'] = AP_REQ(ap_req).dump()
		
		
		krb_tgs_body = {}
		krb_tgs_body['kdc-options'] = KDCOptions(set(['forwardable','renewable','constrained-delegation', 'canonicalize']))
		krb_tgs_body['sname'] = PrincipalName({'name-type': NAME_TYPE.SRV_INST.value, 'name-string': spn_user.get_principalname()})
		krb_tgs_body['realm'] = self.usercreds.domain.upper()
		krb_tgs_body['till']  = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		krb_tgs_body['nonce'] = secrets.randbits(31)
		krb_tgs_body['etype'] = [supp_enc.value] #selecting according to server's preferences
		krb_tgs_body['additional-tickets'] = [s4uself_ticket]
		
		
		krb_tgs_req = {}
		krb_tgs_req['pvno'] = krb5_pvno
		krb_tgs_req['msg-type'] = MESSAGE_TYPE.KRB_TGS_REQ.value
		krb_tgs_req['padata'] = [pa_tgs_req, pa_pac_opts]
		krb_tgs_req['req-body'] = KDC_REQ_BODY(krb_tgs_body)
		
		req = TGS_REQ(krb_tgs_req)
		logger.debug('[S4U2proxy] Sending request to server')
		try:
			reply = self.ksoc.sendrecv(req.dump())
		except KerberosError as e:
			if e.errorcode.value == 16:
				logger.error('S4U2proxy: Failed to get S4U2proxy! Error code (16) indicates that delegation is not enabled for this account! Full error: %s' % e)
			
			raise e
		logger.debug('[S4U2proxy] Got server reply, decrypting...')
		tgs = reply.native
		
		encTGSRepPart = EncTGSRepPart.load(self.kerberos_cipher.decrypt(self.kerberos_session_key, 8, tgs['enc-part']['cipher'])).native
		key = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue'])
		
		self.ccache.add_tgs(tgs, encTGSRepPart)
		logger.debug('[S4U2proxy] Got valid TGS reply')

		return tgs, encTGSRepPart, key
Пример #20
0
asrep_4_native = KerberosResponse.load(asrep_4).native
pprint(asrep_4_native)

cred = KerberosCredential()
cred.username = '******'
cred.domain = 'TEST.corp'
#cred.password = '******'
cred.kerberos_key_aes_256 = '7289306c73ca8909cf89bc01afe3e29f26211f89d922fb317cc5d81cfdf8465d'

supp_enc = EncryptionType.AES256_CTS_HMAC_SHA1_96

cipherText = asrep_4_native['enc-part']['cipher']
print(cipherText.hex())
key_bytes = cred.get_key_for_enctype(supp_enc, None)
kerberos_key = Key(_enctype_table[asrep_4_native['enc-part']['etype']].enctype, key_bytes)
temp = _enctype_table[asrep_4_native['enc-part']['etype']].decrypt(kerberos_key, 3, cipherText)

temp_dec = EncASRepPart.load(temp).native
pprint(temp_dec)

computer_session_key_bytes = temp_dec['key']['keyvalue']



#### decrypting authenticator (it's in the second AP_REQ message FAST data's armor section that is for the user)
#### includes a ticket with an authenticator



data = bytes.fromhex('6e82051d30820519a003020105a10302010ea20703050000000000a38204586182045430820450a003020105a10b1b09544553542e434f5250a21e301ca003020102a11530131b066b72627467741b09544553542e434f5250a382041a30820416a003020112a103020102a2820408048204048c76c7670f689ef1742dedd3c16c0043521cf2a3ca5f6fef84b760e97a452ef70ad69d028cd0c0aa1d0692421b74f7c102d338e35ebcba3d96554bc013a3f23d841cc570506d457acd7a519e79c32fc3ac443b687599be74ce59346aba831983d8da4a24e5c1d8d0758bae89cc34ecdd1754e51bb527c7171086897faa611b6f5f501eebf0a488cd4b07e0c7859c67cc000dce6b9c8945c3ead8d6786663ab585b30e86f51935e6ac5a0c813c567d03d2d9a6ad7b67d2f77098582bd80e0c81c1367f865f41a027d628ac4874036e0face8362c2375fedabcbf6ca98a02dd693cfa96d840367b15a02a3582abbee29d70a55d785f50370fc0e1b6ba349dc3c79d498fbc46ce4f3947ae94c4d9f5c2791ec4824835c55f34983aa30cb22d892b4764f4746c8e9231ada10c9eb3dfdb3ad21c89102d009539164e5f64b79490605954f5298bcf7eaedb1498620a5f06f075be7f1d6ca22a4a788a9af7e4f8ee4202951a5511d62b99177893102c5654b7cdd3d402b44105fe4daaca98429cac4eb51fa7879512427a813db032a610724ea8648263f592c2f4dd934f2b7e53419c75b371e6a7dc9636d2538a8cd74e36041e8755c018eb9d51b1f4e5ea25db3c576c8a9db7b6c019f9ae550f0704b2eaaae489bf42274217982063fc6498fe638698feab668a8f4a189dc7b762bc79eda23be1afbee6717930dca827d270d220a265d7dc25d31ca54b24e518c5f6a95ed3b53adc4512838d63c75d037b75049fc604f92620e46f1a9ba49fae3015c0431c57e7981bb7a97f3115ea865206ada7300e2ff1c87728c587fb64f6d31ef746623d454bafb54fb451eb5bdae84ef445483a255f20eb28a345afc245f8fea7eefca583379c2935b9f6b31c759a2ca1b1d7df33c86b187e56aa8dd6edb139bc4d26a53cce1d236a18276e32c135d05fbc36e3d9c310cb36892fc2c9d7716bb3fae2b788986869d92af5379d5e5e334b00b31bbc0f7f1957051c144b45f297a0bb2ce07c1f65d57931662cc3aea530bc4f0228c6653effde024e0a4096ba5e0ad5b8964a2042733ce290c36e604820a6f9be00aa4652f119a0972763ed264d45675b10cc025633fcf873d10bc2855086e8beaf428c6ee9f16e93718477f21b643eb2459b5222587395e8d5da9f6d31ffee7088295e65de747823e74da93df9a35eabbf93f7267ea79f0557fb8896f9004af99f42aed55510d169bbabd3e0bd4c517fa30bb396e31182685479ef96b78146a40597927d62d9fc044d257b63e7db6977598871f755ef36b5b9ff4b9ef1e6cb2255a51c57f408f89df9ad50b7ef2d243ca86b0fe0376c47813e305463d6aa081e70ee9f4f677934f74018b8d0a701e4d4c080ae61b698d78b3a5bb116035b52c0575878bb29b4b91848e84844b6e7118086e639ace845bc028cac48c8765fcf0970ee045a2a481a73081a4a003020112a2819c048199f363e352e88f51743ffa449016a24aeab84f4be14dc24216bfa48837cc4c0c3327580a0caa498e8674d283711bae53eceb367b03e39b3975fb76b820f053f5c2830bdc2fc672d30be07fce88a7bfad85ad5f1470594db2c61b725223103eb3a08de787d3eabbc9a395eb4fabe3062dde554fa8825629fd395903377a095e64c58e22d114aea20741d1717c394353f8696888b4b9308bd1f4e1')
Пример #21
0
	def S4U2self(self, user_to_impersonate, supp_enc_methods = [EncryptionType.DES_CBC_CRC,EncryptionType.DES_CBC_MD4,EncryptionType.DES_CBC_MD5,EncryptionType.DES3_CBC_SHA1,EncryptionType.ARCFOUR_HMAC_MD5,EncryptionType.AES256_CTS_HMAC_SHA1_96,EncryptionType.AES128_CTS_HMAC_SHA1_96]):
		"""
		user_to_impersonate : KerberosTarget class
		"""
		
		if not self.kerberos_TGT:
			logger.debug('[S4U2self] TGT is not available! Fetching TGT...')
			self.get_TGT()
		
		supp_enc = self.usercreds.get_preferred_enctype(supp_enc_methods)
		auth_package_name = 'Kerberos'
		now = datetime.datetime.now(datetime.timezone.utc)
		
		
		###### Calculating authenticator data
		authenticator_data = {}
		authenticator_data['authenticator-vno'] = krb5_pvno
		authenticator_data['crealm'] = Realm(self.kerberos_TGT['crealm'])
		authenticator_data['cname'] = self.kerberos_TGT['cname']
		authenticator_data['cusec'] = now.microsecond
		authenticator_data['ctime'] = now.replace(microsecond=0)
		
		authenticator_data_enc = self.kerberos_cipher.encrypt(self.kerberos_session_key, 7, Authenticator(authenticator_data).dump(), None)
		
		ap_req = {}
		ap_req['pvno'] = krb5_pvno
		ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
		ap_req['ap-options'] = APOptions(set())
		ap_req['ticket'] = Ticket(self.kerberos_TGT['ticket'])
		ap_req['authenticator'] = EncryptedData({'etype': self.kerberos_cipher_type, 'cipher': authenticator_data_enc})
		
		pa_data_auth = {}
		pa_data_auth['padata-type'] = PaDataType.TGS_REQ.value
		pa_data_auth['padata-value'] = AP_REQ(ap_req).dump()
		
		###### Calculating checksum data
		
		S4UByteArray = NAME_TYPE.PRINCIPAL.value.to_bytes(4, 'little', signed = False)
		S4UByteArray += user_to_impersonate.username.encode()
		S4UByteArray += user_to_impersonate.domain.encode()
		S4UByteArray += auth_package_name.encode()
		logger.debug('[S4U2self] S4UByteArray: %s' % S4UByteArray.hex())
		logger.debug('[S4U2self] S4UByteArray: %s' % S4UByteArray)
		
		chksum_data = _HMACMD5.checksum(self.kerberos_session_key, 17, S4UByteArray)
		logger.debug('[S4U2self] chksum_data: %s' % chksum_data.hex())
		
		
		chksum = {}
		chksum['cksumtype'] = int(CKSUMTYPE('HMAC_MD5'))
		chksum['checksum'] = chksum_data

		
		###### Filling out PA-FOR-USER data for impersonation
		pa_for_user_enc = {}
		pa_for_user_enc['userName'] = PrincipalName({'name-type': NAME_TYPE.PRINCIPAL.value, 'name-string': user_to_impersonate.get_principalname()})
		pa_for_user_enc['userRealm'] = user_to_impersonate.domain
		pa_for_user_enc['cksum'] = Checksum(chksum)
		pa_for_user_enc['auth-package'] = auth_package_name
		
		pa_for_user = {}
		pa_for_user['padata-type'] = int(PADATA_TYPE('PA-FOR-USER'))
		pa_for_user['padata-value'] = PA_FOR_USER_ENC(pa_for_user_enc).dump()
	
		###### Constructing body
		
		krb_tgs_body = {}
		krb_tgs_body['kdc-options'] = KDCOptions(set(['forwardable','renewable','canonicalize']))
		krb_tgs_body['sname'] = PrincipalName({'name-type': NAME_TYPE.UNKNOWN.value, 'name-string': [self.usercreds.username]})
		krb_tgs_body['realm'] = self.usercreds.domain.upper()
		krb_tgs_body['till']  = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		krb_tgs_body['nonce'] = secrets.randbits(31)
		krb_tgs_body['etype'] = [supp_enc.value] #selecting according to server's preferences
		
		
		krb_tgs_req = {}
		krb_tgs_req['pvno'] = krb5_pvno
		krb_tgs_req['msg-type'] = MESSAGE_TYPE.KRB_TGS_REQ.value
		krb_tgs_req['padata'] = [pa_data_auth, pa_for_user]
		krb_tgs_req['req-body'] = KDC_REQ_BODY(krb_tgs_body)
		
		req = TGS_REQ(krb_tgs_req)
		
		logger.debug('[S4U2self] Sending request to server')
		try:
			reply = self.ksoc.sendrecv(req.dump())
		except KerberosError as e:
			if e.errorcode.value == 16:
				logger.error('[S4U2self] Failed to get S4U2self! Error code (16) indicates that delegation is not enabled for this account! Full error: %s' % e)
			
			raise e
		
		logger.debug('[S4U2self] Got reply, decrypting...')
		tgs = reply.native
		
		encTGSRepPart = EncTGSRepPart.load(self.kerberos_cipher.decrypt(self.kerberos_session_key, 8, tgs['enc-part']['cipher'])).native
		key = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue'])
		
		self.ccache.add_tgs(tgs, encTGSRepPart)
		logger.debug('[S4U2self] Got valid TGS reply')
		self.kerberos_TGS = tgs
		return tgs, encTGSRepPart, key
Пример #22
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           is_rpc=False):
        #authdata is only for api compatibility reasons
        if self.operator is None:
            self.operator = MPNOPerator(self.settings.get_url())
            asyncio.create_task(self.operator.run())
            await asyncio.wait_for(self.operator.connected_evt.wait(),
                                   timeout=self.settings.timeout)
        if self.ksspi is None:
            self.ksspi, err = await self.operator.create_sspi(self.agent_id)
            if err is not None:
                return None, None, err
        try:
            if is_rpc == True:
                if self.iterations == 0:
                    flags = ISC_REQ.CONFIDENTIALITY | \
                      ISC_REQ.INTEGRITY | \
                      ISC_REQ.MUTUAL_AUTH | \
                      ISC_REQ.REPLAY_DETECT | \
                      ISC_REQ.SEQUENCE_DETECT|\
                      ISC_REQ.USE_DCE_STYLE

                    context_attributes, apreq, err = await self.ksspi.kerberos(
                        'cifs/%s' % self.settings.target,
                        context_attributes=flags.value)
                    if err is not None:
                        raise err

                    self.iterations += 1
                    return apreq, True, None

                elif self.iterations == 1:
                    context_attributes, data, err = await self.ksspi.kerberos(
                        target_name='cifs/%s' % self.settings.target,
                        context_attributes=flags.value,
                        token_data=authData)
                    if err is not None:
                        return None, None, err
                    self.session_key, err = await self.ksspi.get_sessionkey()
                    if err is not None:
                        return None, None, err

                    aprep = AP_REP.load(data).native
                    subkey = Key(aprep['enc-part']['etype'], self.session_key)
                    self.gssapi = get_gssapi(subkey)

                    if aprep['enc-part'][
                            'etype'] != 23:  #no need for seq number in rc4
                        raw_seq_data, err = await self.ksspi.get_sequenceno()
                        if err is not None:
                            return None, None, err
                        self.seq_number = GSSWrapToken.from_bytes(
                            raw_seq_data[16:]).SND_SEQ

                    self.iterations += 1
                    await self.ksspi.disconnect()
                    return data, False, None

                else:
                    raise Exception(
                        'SSPI Kerberos -RPC - auth encountered too many calls for authenticate.'
                    )

            else:
                context_attributes, apreq, err = await self.ksspi.kerberos(
                    target_name='cifs/%s' % self.settings.target)
                #print('MULTIPLEXOR KERBEROS SSPI, APREQ: %s ERROR: %s' % (apreq, res))
                if err is not None:
                    raise err

                self.session_key, err = await self.ksspi.get_sessionkey()
                if err is not None:
                    raise err
                await self.ksspi.disconnect()

                return apreq, False, None
        except Exception as e:
            return None, None, err
Пример #23
0
    async def authenticate(self,
                           authData=None,
                           flags=None,
                           seq_number=0,
                           cb_data=None):
        """
		This function is called (multiple times depending on the flags) to perform authentication. 
		"""
        try:
            if self.iterations == 0:
                self.ksspi = KerberosMSLDAPSSPI(domain=self.domain,
                                                username=self.username,
                                                password=self.password)
                token, self.actual_ctx_flags = self.ksspi.get_ticket_for_spn(
                    self.spn, ctx_flags=self.flags)
                self.iterations += 1

                if ISC_REQ.MUTUAL_AUTH in self.actual_ctx_flags or ISC_REQ.USE_DCE_STYLE in self.actual_ctx_flags:
                    #in these cases continuation is needed
                    return token, True, None

                else:
                    #no mutual or dce auth will take one step only
                    _, err = self.get_session_key()
                    if err is not None:
                        return None, None, err
                    apreq = AP_REQ.load(token).native
                    subkey = Key(apreq['ticket']['enc-part']['etype'],
                                 self.session_key)
                    self.gssapi = get_gssapi(subkey)
                    self.get_seq_number()

                    return token, False, None

            else:
                adata = authData[16:]
                if ISC_REQ.USE_DCE_STYLE in self.actual_ctx_flags:
                    adata = authData
                token, self.actual_ctx_flags = self.ksspi.get_ticket_for_spn(
                    self.spn,
                    ctx_flags=self.actual_ctx_flags,
                    token_data=adata)

                if ISC_REQ.USE_DCE_STYLE in self.actual_ctx_flags:
                    #Using DCE style 3-legged auth
                    aprep = AP_REP.load(token).native
                else:
                    aprep = AP_REP.load(adata).native
                    subkey = Key(aprep['enc-part']['etype'],
                                 self.get_session_key())

                _, err = self.get_session_key()
                if err is not None:
                    return None, None, err

                _, err = self.get_seq_number()
                if err is not None:
                    return None, None, err

                subkey = Key(token['enc-part']['etype'], self.session_key)
                self.gssapi = get_gssapi(subkey)

                self.iterations += 1
                return token, False, None

        except Exception as e:
            return None, None, e
Пример #24
0
    async def authenticate(self,
                           authData,
                           flags=None,
                           seq_number=0,
                           cb_data=None):
        """
		This function is called (multiple times depending on the flags) to perform authentication. 
		"""
        try:
            if self.kc is None:
                _, err = await self.setup_kc()
                if err is not None:
                    return None, None, err

            if self.iterations == 0:
                self.seq_number = 0  #int.from_bytes(os.urandom(4), byteorder='big', signed=False)
                self.iterations += 1

                #tgt = await self.kc.get_TGT()
                tgt = await self.kc.get_TGT(
                    override_etype=self.preferred_etypes)
                tgs, encpart, self.session_key = await self.kc.get_TGS(
                    self.spn)  #, override_etype = self.preferred_etypes)

                #self.expected_server_seq_number = encpart.get('nonce', seq_number)

                ap_opts = []
                if ChecksumFlags.GSS_C_MUTUAL_FLAG in self.flags or ChecksumFlags.GSS_C_DCE_STYLE in self.flags:
                    if ChecksumFlags.GSS_C_MUTUAL_FLAG in self.flags:
                        ap_opts.append('mutual-required')
                    apreq = self.kc.construct_apreq(tgs,
                                                    encpart,
                                                    self.session_key,
                                                    flags=self.flags,
                                                    seq_number=self.seq_number,
                                                    ap_opts=ap_opts,
                                                    cb_data=cb_data)
                    return apreq, True, None

                else:
                    #no mutual or dce auth will take one step only
                    apreq = self.kc.construct_apreq(tgs,
                                                    encpart,
                                                    self.session_key,
                                                    flags=self.flags,
                                                    seq_number=self.seq_number,
                                                    ap_opts=[],
                                                    cb_data=cb_data)
                    self.gssapi = get_gssapi(self.session_key)
                    return apreq, False, None

            else:
                self.iterations += 1
                #raise Exception('Not implemented!')
                if ChecksumFlags.GSS_C_DCE_STYLE in self.flags:
                    # adata = authData[16:]
                    # if ChecksumFlags.GSS_C_DCE_STYLE in self.flags:
                    #	adata = authData
                    raise Exception('DCE auth Not implemented!')

                # at this point we are dealing with mutual authentication
                # This means that the server sent back an AP-rep wrapped in a token
                # The APREP contains a new session key we'd need to update and a seq-number
                # that is expected the server will use for future communication.
                # For mutual auth we dont need to reply anything after this step,
                # but for DCE auth a reply is expected. TODO

                # converting the token to aprep
                token = KRB5_MECH_INDEP_TOKEN.from_bytes(authData)
                if token.data[:2] != b'\x02\x00':
                    raise Exception('Unexpected token type! %s' %
                                    token.data[:2].hex())
                aprep = AP_REP.load(token.data[2:]).native

                # decrypting aprep
                cipher = _enctype_table[int(aprep['enc-part']['etype'])]()
                cipher_text = aprep['enc-part']['cipher']
                temp = cipher.decrypt(self.session_key, 12, cipher_text)
                enc_part = EncAPRepPart.load(temp).native

                #updating session key, gssapi
                self.session_key = Key(int(enc_part['subkey']['keytype']),
                                       enc_part['subkey']['keyvalue'])
                #self.seq_number = enc_part.get('seq-number', 0)
                self.gssapi = get_gssapi(self.session_key)

                return b'', False, None

        except Exception as e:
            return None, None, e
Пример #25
0
	async def authenticate(self, authData, flags = None, seq_number = 0, is_rpc = False):
		if self.iteractions == 0:
			self.setup()
			self.iteractions += 1
			#authdata should be 0 at this point

			if self.is_azure is True:
				# kerberos service is on the same ip
				asreq = self.pkinit.build_asreq(target = self.target.get_hostname_or_ip(), kdcopts = ['forwardable','renewable','proxiable', 'canonicalize'])
			else:
				if self.target.dc_ip is None:
					raise Exception('DC IP must be set for kerberos auth!')
				asreq = self.pkinit.build_asreq(kdcopts = ['forwardable','renewable','proxiable', 'canonicalize'])

			negodata = generate_init_nego(self._msgctr, self._convid)
			self._msgctr += 1
			metadata = self.__get_metadata()
			self._msgctr += 1
			ap_req, token_raw = generate_ap_req(self._msgctr, self._convid, asreq, PKU2U_TOKEN_TYPE.KRB_AS_REQ)
			self._krb_finished_data += token_raw # for the checksum calc...
			self._msgctr += 1
			msg = negodata + metadata + ap_req
			self._msgs += msg

			return msg, True, None

		elif self.iteractions == 1:
			from minikerberos.protocol.encryption import Enctype, _checksum_table, _enctype_table, Key
			self.iteractions += 1
			
			self._msgs += authData
			msgs = negoexts_parse_bytes(authData)
			self._msgctr += len(msgs)
			#print(msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native)
			as_rep = msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native
			self._krb_finished_data += msgs[MESSAGE_TYPE.CHALLENGE].exchange_data_raw # for the checksum calc...
			encasrep, session_key, cipher = self.pkinit.decrypt_asrep(as_rep)

			self.xxxxx = session_key

			self.session_key_data = {}
			self.session_key_data['keytype'] = Enctype.AES256
			self.session_key_data['keyvalue'] = os.urandom(32)
			subkey_cipher = _enctype_table[self.session_key_data['keytype']]
			subkey_key = Key(subkey_cipher.enctype, self.session_key_data['keyvalue'])
			subkey_checksum = _checksum_table[16] # ChecksumTypes.hmac_sha1_96_aes256

			ap_req = self.pkinit.build_apreq(as_rep, session_key, cipher, self.session_key_data, self._krb_finished_data)

			ap_req_msg, _ = generate_ap_req(self._msgctr, self._convid, ap_req, PKU2U_TOKEN_TYPE.KRB_AP_REQ)
			#print(ap_req_msg.hex())
			self._msgctr += 1
			checksum_final = subkey_checksum.checksum(subkey_key, 25, self._msgs + ap_req_msg )
			verify_msg = generate_verify(self._msgctr, self._convid, checksum_final,  16)
			self._msgctr += 1

			ret_msg = ap_req_msg + verify_msg
			self._msgs += ret_msg

			return ret_msg, True, None


		elif self.iteractions == 2:
			from minikerberos.protocol.encryption import Enctype, _checksum_table, _enctype_table, Key
			from minikerberos.protocol.asn1_structs import EncAPRepPart

			#input('aaaaaaaaaaaaaa')
			self.iteractions += 1
			self._msgs += authData
			msgs = negoexts_parse_bytes(authData)
			self._msgctr += len(msgs)
			ap_rep = msgs[MESSAGE_TYPE.CHALLENGE].Exchange.inner_token.native
			#print(ap_rep)

			#self.xxxxx

			cipher = _enctype_table[int(ap_rep['enc-part']['etype'])]()
			cipher_text = ap_rep['enc-part']['cipher']
			subkey_key = Key(cipher.enctype, self.xxxxx.contents)
			temp = cipher.decrypt(subkey_key, 12, cipher_text)
			enc_part = EncAPRepPart.load(temp).native
			#print(enc_part)
			
			cipher = _enctype_table[int(enc_part['subkey']['keytype'])]()
			self.session_key = Key(cipher.enctype, enc_part['subkey']['keyvalue'])
			self.gssapi = get_gssapi(self.session_key)

			return None, False, None
Пример #26
0
    def build_apreq(self,
                    asrep,
                    session_key,
                    cipher,
                    subkey_data,
                    krb_finished_data,
                    flags=GSSAPIFlags.GSS_C_MUTUAL_FLAG
                    | GSSAPIFlags.GSS_C_INTEG_FLAG
                    | GSSAPIFlags.GSS_C_EXTENDED_ERROR_FLAG):

        # TODO: https://www.ietf.org/rfc/rfc4757.txt
        #subkey_data = {}
        #subkey_data['keytype'] = Enctype.AES256
        #subkey_data['keyvalue'] = os.urandom(32)

        subkey_cipher = _enctype_table[subkey_data['keytype']]
        subkey_key = Key(subkey_cipher.enctype, subkey_data['keyvalue'])
        subkey_checksum = _checksum_table[
            16]  # ChecksumTypes.hmac_sha1_96_aes256

        krb_finished_checksum_data = {}
        krb_finished_checksum_data['cksumtype'] = 16
        krb_finished_checksum_data['checksum'] = subkey_checksum.checksum(
            subkey_key, 41, krb_finished_data)

        krb_finished_data = {}
        krb_finished_data['gss-mic'] = Checksum(krb_finished_checksum_data)

        krb_finished = KRB_FINISHED(krb_finished_data).dump()

        a = 2
        extensions_data = a.to_bytes(
            4, byteorder='big', signed=True) + len(krb_finished).to_bytes(
                4, byteorder='big', signed=True) + krb_finished

        ac = AuthenticatorChecksum()
        ac.flags = flags
        ac.channel_binding = b'\x00' * 16
        chksum = {}
        chksum['cksumtype'] = 0x8003
        chksum['checksum'] = ac.to_bytes() + extensions_data

        tii = LSAP_TOKEN_INFO_INTEGRITY()
        tii.Flags = 1
        tii.TokenIL = 0x00002000  # Medium integrity
        tii.MachineID = bytes.fromhex(
            '7e303fffe6bff25146addca4fbddf1b94f1634178eb4528fb2731c669ca23cde')

        restriction_data = {}
        restriction_data['restriction-type'] = 0
        restriction_data['restriction'] = tii.to_bytes()
        restriction_data = KERB_AD_RESTRICTION_ENTRY(restriction_data)

        x = KERB_AD_RESTRICTION_ENTRYS([restriction_data]).dump()
        restrictions = AuthorizationData([{
            'ad-type': 141,
            'ad-data': x
        }]).dump()

        now = datetime.datetime.now(datetime.timezone.utc)
        authenticator_data = {}
        authenticator_data['authenticator-vno'] = krb5_pvno
        authenticator_data['crealm'] = Realm(asrep['crealm'])
        authenticator_data['cname'] = asrep['cname']
        authenticator_data['cusec'] = now.microsecond
        authenticator_data['ctime'] = now.replace(microsecond=0)
        authenticator_data['subkey'] = EncryptionKey(subkey_data)
        authenticator_data['seq-number'] = 682437742  #??? TODO: check this!
        authenticator_data['authorization-data'] = AuthorizationData([{
            'ad-type':
            1,
            'ad-data':
            restrictions
        }])
        authenticator_data['cksum'] = Checksum(chksum)

        #print('Authenticator(authenticator_data).dump()')
        #print(Authenticator(authenticator_data).dump().hex())

        authenticator_data_enc = cipher.encrypt(
            session_key, 11,
            Authenticator(authenticator_data).dump(), None)

        ap_opts = ['mutual-required']

        ap_req = {}
        ap_req['pvno'] = krb5_pvno
        ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
        ap_req['ticket'] = Ticket(asrep['ticket'])
        ap_req['ap-options'] = APOptions(set(ap_opts))
        ap_req['authenticator'] = EncryptedData({
            'etype':
            session_key.enctype,
            'cipher':
            authenticator_data_enc
        })

        #pprint('AP_REQ \r\n%s' % AP_REQ(ap_req).native)

        #print(AP_REQ(ap_req).dump().hex())
        #input()

        return AP_REQ(ap_req).dump()
Пример #27
0
	def get_TGS(self, spn_user, override_etype = None, is_linux = False):
		"""
		Requests a TGS ticket for the specified user.
		Returns the TGS ticket, end the decrpyted encTGSRepPart.

		spn_user: KerberosTarget: the service user you want to get TGS for.
		override_etype: None or list of etype values (int) Used mostly for kerberoasting, will override the AP_REQ supported etype values (which is derived from the TGT) to be able to recieve whatever tgs tiecket 
		"""

		logger.debug('[getTGS] Constructing request for user %s' % spn_user.get_formatted_pname())
		now = datetime.datetime.now(datetime.timezone.utc)
		kdc_req_body = {}
		kdc_req_body['kdc-options'] = KDCOptions(set(['forwardable','renewable','renewable_ok', 'canonicalize']))
		kdc_req_body['realm'] = spn_user.domain.upper()
		kdc_req_body['sname'] = PrincipalName({'name-type': NAME_TYPE.SRV_INST.value, 'name-string': spn_user.get_principalname()})
		kdc_req_body['till'] = (now + datetime.timedelta(days=1)).replace(microsecond=0)
		kdc_req_body['nonce'] = secrets.randbits(31)
		if override_etype:
			kdc_req_body['etype'] = override_etype
		else:
			kdc_req_body['etype'] = [self.kerberos_cipher_type]

		authenticator_data = {}
		authenticator_data['authenticator-vno'] = krb5_pvno
		authenticator_data['crealm'] = Realm(self.kerberos_TGT['crealm'])
		authenticator_data['cname'] = self.kerberos_TGT['cname']
		authenticator_data['cusec'] = now.microsecond
		authenticator_data['ctime'] = now.replace(microsecond=0)
		
		if is_linux:
			ac = AuthenticatorChecksum()
			ac.flags = 0
			ac.channel_binding = b'\x00'*16
			
			chksum = {}
			chksum['cksumtype'] = 0x8003
			chksum['checksum'] = ac.to_bytes()
			
			authenticator_data['cksum'] = Checksum(chksum)
			authenticator_data['seq-number'] = 0
		
		authenticator_data_enc = self.kerberos_cipher.encrypt(self.kerberos_session_key, 7, Authenticator(authenticator_data).dump(), None)
		
		ap_req = {}
		ap_req['pvno'] = krb5_pvno
		ap_req['msg-type'] = MESSAGE_TYPE.KRB_AP_REQ.value
		ap_req['ap-options'] = APOptions(set())
		ap_req['ticket'] = Ticket(self.kerberos_TGT['ticket'])
		ap_req['authenticator'] = EncryptedData({'etype': self.kerberos_cipher_type, 'cipher': authenticator_data_enc})
		
		pa_data_1 = {}
		pa_data_1['padata-type'] = PaDataType.TGS_REQ.value
		pa_data_1['padata-value'] = AP_REQ(ap_req).dump()
		
		
		kdc_req = {}
		kdc_req['pvno'] = krb5_pvno
		kdc_req['msg-type'] = MESSAGE_TYPE.KRB_TGS_REQ.value
		kdc_req['padata'] = [pa_data_1]
		kdc_req['req-body'] = KDC_REQ_BODY(kdc_req_body)
		
		req = TGS_REQ(kdc_req)
		logger.debug('[getTGS] Constructing request to server')
		rep = self.ksoc.sendrecv(req.dump())
		logger.debug('[getTGS] Got reply, decrypting...')
		tgs = rep.native
		
		encTGSRepPart = EncTGSRepPart.load(self.kerberos_cipher.decrypt(self.kerberos_session_key, 8, tgs['enc-part']['cipher'])).native
		key = Key(encTGSRepPart['key']['keytype'], encTGSRepPart['key']['keyvalue'])
		
		self.ccache.add_tgs(tgs, encTGSRepPart)
		logger.debug('[getTGS] Got valid reply')
		self.kerberos_TGS = tgs
		return tgs, encTGSRepPart, key