Exemple #1
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
Exemple #2
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
Exemple #3
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
Exemple #4
0
    def from_buffer(buff):
        t = PKU2U_TOKEN()
        t_hdr = buff.tell()
        buff.read(1)  # 0x60
        total_length = cl_buff(buff)
        buff.read(1)  # 0x06
        total_length += buff.tell() - t_hdr - 1
        oid_length = cl_buff(buff)
        t_oid = buff.read(oid_length)
        t.tok_id = PKU2U_TOKEN_TYPE(buff.read(2))
        t_data = buff.read(total_length - buff.tell())
        #t.inner_token_raw = t_data

        if t.tok_id == PKU2U_TOKEN_TYPE.KRB_AS_REQ:
            t.inner_token = AS_REQ.load(t_data)
        elif t.tok_id == PKU2U_TOKEN_TYPE.KRB_AS_REP:
            t.inner_token = AS_REP.load(t_data)
        elif t.tok_id == PKU2U_TOKEN_TYPE.KRB_AP_REQ:
            t.inner_token = AP_REQ.load(t_data)
        elif t.tok_id == PKU2U_TOKEN_TYPE.KRB_AP_REP:
            t.inner_token = AP_REP.load(t_data)
        else:
            t.inner_token = t_data
        return t
Exemple #5
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
Exemple #6
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
Exemple #7
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
Exemple #8
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
Exemple #9
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