166 lines
5.5 KiB
Python
166 lines
5.5 KiB
Python
"""
|
|
|
|
Credential handling functionality for Empire.
|
|
|
|
"""
|
|
|
|
import helpers
|
|
import os
|
|
# import sqlite3
|
|
|
|
class Credentials:
|
|
"""
|
|
Class that handles interaction with the backend credential model
|
|
(adding creds, displaying, etc.).
|
|
"""
|
|
def __init__(self, MainMenu, args=None):
|
|
|
|
# pull out the controller objects
|
|
self.mainMenu = MainMenu
|
|
self.conn = MainMenu.conn
|
|
self.installPath = self.mainMenu.installPath
|
|
self.args = args
|
|
|
|
# credential database schema:
|
|
# (ID, credtype, domain, username, password, host, OS, notes, sid)
|
|
# credtype = hash or plaintext
|
|
# sid is stored for krbtgt
|
|
|
|
|
|
def is_credential_valid(self, credentialID):
|
|
"""
|
|
Check if this credential ID is valid.
|
|
"""
|
|
|
|
cur = self.conn.cursor()
|
|
cur.execute('SELECT * FROM credentials WHERE id=? limit 1', [credentialID])
|
|
results = cur.fetchall()
|
|
cur.close()
|
|
return len(results) > 0
|
|
|
|
|
|
def get_credentials(self, filterTerm=None, credtype=None, note=None, os=None):
|
|
"""
|
|
Return credentials from the database.
|
|
|
|
'credtype' can be specified to return creds of a specific type.
|
|
Values are: hash, plaintext, and token.
|
|
"""
|
|
|
|
cur = self.conn.cursor()
|
|
|
|
# if we're returning a single credential by ID
|
|
if self.is_credential_valid(filterTerm):
|
|
cur.execute("SELECT * FROM credentials WHERE id=? limit 1", [filterTerm])
|
|
|
|
# if we're filtering by host/username
|
|
elif filterTerm and filterTerm != '':
|
|
filterTerm = filterTerm.replace('*', '%')
|
|
cur.execute("SELECT * FROM credentials WHERE LOWER(domain) LIKE LOWER(?) or LOWER(username) like LOWER(?) or LOWER(host) like LOWER(?) or LOWER(password) like LOWER(?)", [filterTerm, filterTerm, filterTerm, filterTerm])
|
|
|
|
# if we're filtering by credential type (hash, plaintext, token)
|
|
elif credtype and credtype != "":
|
|
cur.execute("SELECT * FROM credentials WHERE LOWER(credtype) LIKE LOWER(?)", [credtype])
|
|
|
|
# if we're filtering by content in the note field
|
|
elif note and note != "":
|
|
cur.execute("SELECT * FROM credentials WHERE LOWER(note) LIKE LOWER(%?%)", [note])
|
|
|
|
# if we're filtering by content in the OS field
|
|
elif os and os != "":
|
|
cur.execute("SELECT * FROM credentials WHERE LOWER(os) LIKE LOWER(%?%)", [os])
|
|
|
|
# otherwise return all credentials
|
|
else:
|
|
cur.execute("SELECT * FROM credentials")
|
|
|
|
results = cur.fetchall()
|
|
cur.close()
|
|
return results
|
|
|
|
|
|
def get_krbtgt(self):
|
|
"""
|
|
Return all krbtgt credentials from the database.
|
|
"""
|
|
return self.get_credentials(credtype="hash", filterTerm="krbtgt")
|
|
|
|
|
|
def add_credential(self, credtype, domain, username, password, host, os='', sid='', notes=''):
|
|
"""
|
|
Add a credential with the specified information to the database.
|
|
"""
|
|
cur = self.conn.cursor()
|
|
|
|
cur.execute("SELECT * FROM credentials WHERE LOWER(credtype) LIKE LOWER(?) AND LOWER(domain) LIKE LOWER(?) AND LOWER(username) LIKE LOWER(?) AND password LIKE ?", [credtype, domain, username, password])
|
|
results = cur.fetchall()
|
|
|
|
if results == []:
|
|
# only add the credential if the (credtype, domain, username, password) tuple doesn't already exist
|
|
cur.execute("INSERT INTO credentials (credtype, domain, username, password, host, os, sid, notes) VALUES (?,?,?,?,?,?,?,?)", [credtype, domain, username, password, host, os, sid, notes])
|
|
|
|
cur.close()
|
|
|
|
|
|
def add_credential_note(self, credentialID, note):
|
|
"""
|
|
Update a note to a credential in the database.
|
|
"""
|
|
cur = self.conn.cursor()
|
|
cur.execute("UPDATE credentials SET note = ? WHERE id=?", [note, credentialID])
|
|
cur.close()
|
|
|
|
|
|
def remove_credentials(self, credIDs):
|
|
"""
|
|
Removes a list of IDs from the database
|
|
"""
|
|
for credID in credIDs:
|
|
cur = self.conn.cursor()
|
|
cur.execute("DELETE FROM credentials WHERE id=?", [credID])
|
|
cur.close()
|
|
|
|
|
|
def remove_all_credentials(self):
|
|
"""
|
|
Remove all credentials from the database.
|
|
"""
|
|
cur = self.conn.cursor()
|
|
cur.execute("DELETE FROM credentials")
|
|
cur.close()
|
|
|
|
|
|
def export_credentials(self, export_path=''):
|
|
"""
|
|
Export the credentials in the database to an output file.
|
|
"""
|
|
|
|
if export_path == '':
|
|
print helpers.color("[!] Export path cannot be ''")
|
|
|
|
export_path += ".csv"
|
|
|
|
if os.path.exists(export_path):
|
|
try:
|
|
choice = raw_input(helpers.color("\n[>] File %s already exists, overwrite? [y/N] " % (export_path), "red"))
|
|
if choice.lower() != "" and choice.lower()[0] == "y":
|
|
pass
|
|
else:
|
|
return
|
|
except KeyboardInterrupt:
|
|
return
|
|
|
|
creds = self.get_credentials()
|
|
|
|
if len(creds) == 0:
|
|
print helpers.color("[!] No credentials in the database.")
|
|
return
|
|
|
|
output_file = open(export_path, 'w')
|
|
output_file.write("CredID,CredType,Domain,Username,Password,Host,OS,SID,Notes\n")
|
|
for cred in creds:
|
|
output_file.write("\"%s\"\n" % ('","'.join([str(x) for x in cred])))
|
|
|
|
print "\n" + helpers.color("[*] Credentials exported to %s\n" % (export_path))
|
|
output_file.close()
|