Esempio n. 1
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
Esempio n. 2
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
Esempio n. 3
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
Esempio n. 4
0
    async 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
        ]):
        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','forwarded','renewable','renewable-ok', 'canonicalize']))
        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)

        reply = await self.ksoc.sendrecv(req.dump())
        if reply.name == 'KRB_ERROR':
            if reply.native['error-code'] == 16:
                logger.error(
                    'S4U2proxy: Failed to get S4U2proxy! Error code (16) indicates that delegation is not enabled for this account!'
                )

            raise Exception('S4U2proxy failed! %s' % str(reply))