parent
c3c9b2f04a
commit
1308bc30c8
|
@ -47,6 +47,7 @@ def gen_cli_args():
|
|||
std_parser.add_argument('-id', metavar="CRED_ID", nargs='+', default=[], type=str, dest='cred_id', help='database credential ID(s) to use for authentication')
|
||||
std_parser.add_argument("-u", metavar="USERNAME", dest='username', nargs='+', default=[], help="username(s) or file(s) containing usernames")
|
||||
std_parser.add_argument("-p", metavar="PASSWORD", dest='password', nargs='+', default=[], help="password(s) or file(s) containing passwords")
|
||||
std_parser.add_argument("-k", "--kerberos", action='store_true', help="Use Kerberos authentication from ccache file (KRB5CCNAME)")
|
||||
fail_group = std_parser.add_mutually_exclusive_group()
|
||||
fail_group.add_argument("--gfail-limit", metavar='LIMIT', type=int, help='max number of global failed login attempts')
|
||||
fail_group.add_argument("--ufail-limit", metavar='LIMIT', type=int, help='max number of failed login attempts per username')
|
||||
|
|
|
@ -28,13 +28,18 @@ class connection(object):
|
|||
self.conn = None
|
||||
self.admin_privs = False
|
||||
self.logger = None
|
||||
self.password = None
|
||||
self.username = None
|
||||
self.password = ''
|
||||
self.username = ''
|
||||
self.kerberos = True if self.args.kerberos else False
|
||||
self.aesKey = None
|
||||
self.dc_ip = None
|
||||
self.failed_logins = 0
|
||||
self.local_ip = None
|
||||
|
||||
try:
|
||||
self.host = gethostbyname(self.hostname)
|
||||
if self.args.kerberos:
|
||||
self.host = self.hostname
|
||||
except Exception as e:
|
||||
logging.debug('Error resolving hostname {}: {}'.format(self.hostname, e))
|
||||
return
|
||||
|
@ -60,6 +65,9 @@ class connection(object):
|
|||
def check_if_admin(self):
|
||||
return
|
||||
|
||||
def kerberos_login(self):
|
||||
return
|
||||
|
||||
def plaintext_login(self, domain, username, password):
|
||||
return
|
||||
|
||||
|
@ -133,110 +141,113 @@ class connection(object):
|
|||
return False
|
||||
|
||||
def login(self):
|
||||
for cred_id in self.args.cred_id:
|
||||
with sem:
|
||||
if cred_id.lower() == 'all':
|
||||
creds = self.db.get_credentials()
|
||||
else:
|
||||
creds = self.db.get_credentials(filterTerm=int(cred_id))
|
||||
if self.args.kerberos:
|
||||
if self.kerberos_login(): return True
|
||||
else:
|
||||
for cred_id in self.args.cred_id:
|
||||
with sem:
|
||||
if cred_id.lower() == 'all':
|
||||
creds = self.db.get_credentials()
|
||||
else:
|
||||
creds = self.db.get_credentials(filterTerm=int(cred_id))
|
||||
|
||||
for cred in creds:
|
||||
logging.debug(cred)
|
||||
try:
|
||||
c_id, domain, username, password, credtype, pillaged_from = cred
|
||||
for cred in creds:
|
||||
logging.debug(cred)
|
||||
try:
|
||||
c_id, domain, username, password, credtype, pillaged_from = cred
|
||||
|
||||
if credtype and password:
|
||||
if credtype and password:
|
||||
|
||||
if not domain: domain = self.domain
|
||||
if not domain: domain = self.domain
|
||||
|
||||
if self.args.local_auth:
|
||||
domain = self.domain
|
||||
elif self.args.domain:
|
||||
domain = self.args.domain
|
||||
if self.args.local_auth:
|
||||
domain = self.domain
|
||||
elif self.args.domain:
|
||||
domain = self.args.domain
|
||||
|
||||
if credtype == 'hash' and not self.over_fail_limit(username):
|
||||
if self.hash_login(domain, username, password): return True
|
||||
if credtype == 'hash' and not self.over_fail_limit(username):
|
||||
if self.hash_login(domain, username, password): return True
|
||||
|
||||
elif credtype == 'plaintext' and not self.over_fail_limit(username):
|
||||
if self.plaintext_login(domain, username, password): return True
|
||||
elif credtype == 'plaintext' and not self.over_fail_limit(username):
|
||||
if self.plaintext_login(domain, username, password): return True
|
||||
|
||||
except IndexError:
|
||||
self.logger.error("Invalid database credential ID!")
|
||||
except IndexError:
|
||||
self.logger.error("Invalid database credential ID!")
|
||||
|
||||
for user in self.args.username:
|
||||
if not isinstance(user, str) and isfile(user.name):
|
||||
for usr in user:
|
||||
if "\\" in usr:
|
||||
tmp = usr
|
||||
usr = tmp.split('\\')[1].strip()
|
||||
self.domain = tmp.split('\\')[0]
|
||||
if self.args.hash:
|
||||
with sem:
|
||||
for ntlm_hash in self.args.hash:
|
||||
if isinstance(ntlm_hash, str):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.hash_login(self.domain, usr.strip(), ntlm_hash): return True
|
||||
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name) and self.args.no_bruteforce == False:
|
||||
for f_hash in ntlm_hash:
|
||||
for user in self.args.username:
|
||||
if not isinstance(user, str) and isfile(user.name):
|
||||
for usr in user:
|
||||
if "\\" in usr:
|
||||
tmp = usr
|
||||
usr = tmp.split('\\')[1].strip()
|
||||
self.domain = tmp.split('\\')[0]
|
||||
if self.args.hash:
|
||||
with sem:
|
||||
for ntlm_hash in self.args.hash:
|
||||
if isinstance(ntlm_hash, str):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.hash_login(self.domain, usr.strip(), f_hash.strip()): return True
|
||||
ntlm_hash.seek(0)
|
||||
if self.hash_login(self.domain, usr.strip(), ntlm_hash): return True
|
||||
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name) and self.args.no_bruteforce == True:
|
||||
user.seek(0)
|
||||
for usr, f_pass in zip(user, ntlm_hash):
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name) and self.args.no_bruteforce == False:
|
||||
for f_hash in ntlm_hash:
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.hash_login(self.domain, usr.strip(), f_hash.strip()): return True
|
||||
ntlm_hash.seek(0)
|
||||
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name) and self.args.no_bruteforce == True:
|
||||
user.seek(0)
|
||||
for usr, f_pass in zip(user, ntlm_hash):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_hash.strip()): return True
|
||||
|
||||
elif self.args.password:
|
||||
with sem:
|
||||
for password in self.args.password:
|
||||
if isinstance(password, str):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_hash.strip()): return True
|
||||
if self.plaintext_login(self.domain, usr.strip(), password): return True
|
||||
|
||||
elif self.args.password:
|
||||
with sem:
|
||||
for password in self.args.password:
|
||||
if isinstance(password, str):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), password): return True
|
||||
elif not isinstance(password, str) and isfile(password.name) and self.args.no_bruteforce == False:
|
||||
for f_pass in password:
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return True
|
||||
password.seek(0)
|
||||
|
||||
elif not isinstance(password, str) and isfile(password.name) and self.args.no_bruteforce == False:
|
||||
for f_pass in password:
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return True
|
||||
password.seek(0)
|
||||
elif not isinstance(password, str) and isfile(password.name) and self.args.no_bruteforce == True:
|
||||
user.seek(0)
|
||||
for usr, f_pass in zip(user, password):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return True
|
||||
|
||||
elif not isinstance(password, str) and isfile(password.name) and self.args.no_bruteforce == True:
|
||||
user.seek(0)
|
||||
for usr, f_pass in zip(user, password):
|
||||
if not self.over_fail_limit(usr.strip()):
|
||||
if self.plaintext_login(self.domain, usr.strip(), f_pass.strip()): return True
|
||||
|
||||
elif isinstance(user, str):
|
||||
if hasattr(self.args, 'hash') and self.args.hash:
|
||||
with sem:
|
||||
for ntlm_hash in self.args.hash:
|
||||
if isinstance(ntlm_hash, str):
|
||||
if not self.over_fail_limit(user):
|
||||
if self.hash_login(self.domain, user, ntlm_hash): return True
|
||||
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name):
|
||||
for f_hash in ntlm_hash:
|
||||
elif isinstance(user, str):
|
||||
if hasattr(self.args, 'hash') and self.args.hash:
|
||||
with sem:
|
||||
for ntlm_hash in self.args.hash:
|
||||
if isinstance(ntlm_hash, str):
|
||||
if not self.over_fail_limit(user):
|
||||
if self.hash_login(self.domain, user, f_hash.strip()): return True
|
||||
ntlm_hash.seek(0)
|
||||
if self.hash_login(self.domain, user, ntlm_hash): return True
|
||||
|
||||
elif self.args.password:
|
||||
with sem:
|
||||
for password in self.args.password:
|
||||
if isinstance(password, str):
|
||||
if not self.over_fail_limit(user):
|
||||
if hasattr(self.args, 'domain'):
|
||||
if self.plaintext_login(self.domain, user, password): return True
|
||||
else:
|
||||
if self.plaintext_login(user, password): return True
|
||||
elif not isinstance(ntlm_hash, str) and isfile(ntlm_hash.name):
|
||||
for f_hash in ntlm_hash:
|
||||
if not self.over_fail_limit(user):
|
||||
if self.hash_login(self.domain, user, f_hash.strip()): return True
|
||||
ntlm_hash.seek(0)
|
||||
|
||||
elif not isinstance(password, str) and isfile(password.name):
|
||||
for f_pass in password:
|
||||
elif self.args.password:
|
||||
with sem:
|
||||
for password in self.args.password:
|
||||
if isinstance(password, str):
|
||||
if not self.over_fail_limit(user):
|
||||
if hasattr(self.args, 'domain'):
|
||||
if self.plaintext_login(self.domain, user, f_pass.strip()): return True
|
||||
if self.plaintext_login(self.domain, user, password): return True
|
||||
else:
|
||||
if self.plaintext_login(user, f_pass.strip()): return True
|
||||
password.seek(0)
|
||||
if self.plaintext_login(user, password): return True
|
||||
|
||||
elif not isinstance(password, str) and isfile(password.name):
|
||||
for f_pass in password:
|
||||
if not self.over_fail_limit(user):
|
||||
if hasattr(self.args, 'domain'):
|
||||
if self.plaintext_login(self.domain, user, f_pass.strip()): return True
|
||||
else:
|
||||
if self.plaintext_login(user, f_pass.strip()): return True
|
||||
password.seek(0)
|
||||
|
|
|
@ -33,7 +33,7 @@ def called_from_cmd_args():
|
|||
for stack in inspect.stack():
|
||||
if stack[3] == 'print_host_info':
|
||||
return True
|
||||
if stack[3] == 'plaintext_login' or stack[3] == 'hash_login':
|
||||
if stack[3] == 'plaintext_login' or stack[3] == 'hash_login' or stack[3] == 'kerberos_login':
|
||||
return True
|
||||
if stack[3] == 'call_cmd_args':
|
||||
return True
|
||||
|
|
|
@ -11,6 +11,7 @@ from impacket.nmb import NetBIOSError
|
|||
from impacket.dcerpc.v5 import transport, lsat, lsad
|
||||
from impacket.dcerpc.v5.rpcrt import DCERPCException
|
||||
from impacket.dcerpc.v5.transport import DCERPCTransportFactory
|
||||
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
||||
from impacket.dcerpc.v5.epm import MSRPC_UUID_PORTMAP
|
||||
from impacket.dcerpc.v5.dcom.wmi import WBEM_FLAG_FORWARD_ONLY
|
||||
from impacket.dcerpc.v5.samr import SID_NAME_USE
|
||||
|
@ -185,6 +186,8 @@ class smb(connection):
|
|||
transport = DCERPCTransportFactory(stringBinding)
|
||||
transport.set_connect_timeout(5)
|
||||
dce = transport.get_dce_rpc()
|
||||
if self._conn.kerberos:
|
||||
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
||||
dce.connect()
|
||||
try:
|
||||
dce.bind(MSRPC_UUID_PORTMAP, transfer_syntax=('71710533-BEBA-4937-8319-B5DBEF9CCC36', '1.0'))
|
||||
|
@ -221,6 +224,9 @@ class smb(connection):
|
|||
if not self.domain:
|
||||
self.domain = self.hostname
|
||||
|
||||
if self.args.kerberos:
|
||||
self.domain = self.conn.getServerDNSDomainName()
|
||||
|
||||
self.db.add_computer(self.host, self.hostname, self.domain, self.server_os)
|
||||
|
||||
try:
|
||||
|
@ -248,6 +254,15 @@ class smb(connection):
|
|||
self.domain,
|
||||
self.signing,
|
||||
self.smbv1))
|
||||
def kerberos_login(self):
|
||||
self.conn.kerberosLogin('', '', self.domain, self.lmhash, self.nthash, self.aesKey, self.dc_ip)
|
||||
# self.check_if_admin() # currently not working with kerberos so we set admin_privs to True
|
||||
self.admin_privs = True
|
||||
out = u'{}\\{} {}'.format(self.domain,
|
||||
self.conn.getCredentials()[0],
|
||||
highlight('({})'.format(self.config.get('CME', 'pwn3d_label')) if self.admin_privs else ''))
|
||||
self.logger.success(out)
|
||||
return True
|
||||
|
||||
def plaintext_login(self, domain, username, password):
|
||||
try:
|
||||
|
@ -395,7 +410,7 @@ class smb(connection):
|
|||
|
||||
if method == 'wmiexec':
|
||||
try:
|
||||
exec_method = WMIEXEC(self.host, self.smb_share_name, self.username, self.password, self.domain, self.conn, self.hash, self.args.share)
|
||||
exec_method = WMIEXEC(self.host, self.smb_share_name, self.username, self.password, self.domain, self.conn, self.kerberos, self.hash, self.args.share)
|
||||
logging.debug('Executed command via wmiexec')
|
||||
break
|
||||
except:
|
||||
|
@ -415,7 +430,7 @@ class smb(connection):
|
|||
|
||||
elif method == 'atexec':
|
||||
try:
|
||||
exec_method = TSCH_EXEC(self.host, self.smb_share_name, self.username, self.password, self.domain, self.hash) #self.args.share)
|
||||
exec_method = TSCH_EXEC(self.host, self.smb_share_name, self.username, self.password, self.domain, self.kerberos, self.hash) #self.args.share)
|
||||
logging.debug('Executed command via atexec')
|
||||
break
|
||||
except:
|
||||
|
@ -425,7 +440,7 @@ class smb(connection):
|
|||
|
||||
elif method == 'smbexec':
|
||||
try:
|
||||
exec_method = SMBEXEC(self.host, self.smb_share_name, self.args.port, self.username, self.password, self.domain, self.hash, self.args.share)
|
||||
exec_method = SMBEXEC(self.host, self.smb_share_name, self.args.port, self.username, self.password, self.domain, self.kerberos, self.hash, self.args.share)
|
||||
logging.debug('Executed command via smbexec')
|
||||
break
|
||||
except:
|
||||
|
|
|
@ -2,11 +2,12 @@ import os
|
|||
import logging
|
||||
from impacket.dcerpc.v5 import tsch, transport
|
||||
from impacket.dcerpc.v5.dtypes import NULL
|
||||
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
||||
from cme.helpers.misc import gen_random_string
|
||||
from gevent import sleep
|
||||
|
||||
class TSCH_EXEC:
|
||||
def __init__(self, target, share_name, username, password, domain, hashes=None):
|
||||
def __init__(self, target, share_name, username, password, domain, doKerberos=False, hashes=None):
|
||||
self.__target = target
|
||||
self.__username = username
|
||||
self.__password = password
|
||||
|
@ -16,8 +17,9 @@ class TSCH_EXEC:
|
|||
self.__nthash = ''
|
||||
self.__outputBuffer = b''
|
||||
self.__retOutput = False
|
||||
#self.__aesKey = aesKey
|
||||
#self.__doKerberos = doKerberos
|
||||
# self.__aesKey = aesKey
|
||||
self.__doKerberos = doKerberos
|
||||
self.__kdcHost = None
|
||||
|
||||
if hashes is not None:
|
||||
#This checks to see if we didn't provide the LM Hash
|
||||
|
@ -35,7 +37,7 @@ class TSCH_EXEC:
|
|||
if hasattr(self.__rpctransport, 'set_credentials'):
|
||||
# This method exists only for selected protocol sequences.
|
||||
self.__rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
||||
#rpctransport.set_kerberos(self.__doKerberos)
|
||||
self.__rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
|
||||
|
||||
def execute(self, command, output=False):
|
||||
self.__retOutput = output
|
||||
|
@ -124,6 +126,8 @@ class TSCH_EXEC:
|
|||
def doStuff(self, command, fileless=False):
|
||||
|
||||
dce = self.__rpctransport.get_dce_rpc()
|
||||
if self.__doKerberos:
|
||||
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
||||
|
||||
dce.set_credentials(*self.__rpctransport.get_credentials())
|
||||
dce.connect()
|
||||
|
|
|
@ -4,10 +4,11 @@ from gevent import sleep
|
|||
from impacket.dcerpc.v5 import transport, scmr
|
||||
from impacket.smbconnection import *
|
||||
from cme.helpers.misc import gen_random_string
|
||||
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
|
||||
|
||||
class SMBEXEC:
|
||||
|
||||
def __init__(self, host, share_name, protocol, username = '', password = '', domain = '', hashes = None, share = None, port=445):
|
||||
def __init__(self, host, share_name, protocol, username = '', password = '', domain = '', doKerberos=False, hashes = None, share = None, port=445):
|
||||
self.__host = host
|
||||
self.__share_name = share_name
|
||||
self.__port = port
|
||||
|
@ -26,9 +27,10 @@ class SMBEXEC:
|
|||
self.__rpctransport = None
|
||||
self.__scmr = None
|
||||
self.__conn = None
|
||||
#self.__mode = mode
|
||||
#self.__aesKey = aesKey
|
||||
#self.__doKerberos = doKerberos
|
||||
# self.__mode = mode
|
||||
# self.__aesKey = aesKey
|
||||
self.__doKerberos = doKerberos
|
||||
self.__kdcHost = None
|
||||
|
||||
if hashes is not None:
|
||||
#This checks to see if we didn't provide the LM Hash
|
||||
|
@ -50,9 +52,11 @@ class SMBEXEC:
|
|||
if hasattr(self.__rpctransport, 'set_credentials'):
|
||||
# This method exists only for selected protocol sequences.
|
||||
self.__rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash)
|
||||
#rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
|
||||
self.__rpctransport.set_kerberos(self.__doKerberos, self.__kdcHost)
|
||||
|
||||
self.__scmr = self.__rpctransport.get_dce_rpc()
|
||||
if self.__doKerberos:
|
||||
self.__scmr.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
|
||||
self.__scmr.connect()
|
||||
s = self.__rpctransport.get_smb_connection()
|
||||
# We don't wanna deal with timeouts from now on.
|
||||
|
|
|
@ -8,7 +8,7 @@ from impacket.dcerpc.v5.dcom import wmi
|
|||
from impacket.dcerpc.v5.dtypes import NULL
|
||||
|
||||
class WMIEXEC:
|
||||
def __init__(self, target, share_name, username, password, domain, smbconnection, hashes=None, share=None):
|
||||
def __init__(self, target, share_name, username, password, domain, smbconnection, doKerberos=False, hashes=None, share=None):
|
||||
self.__target = target
|
||||
self.__username = username
|
||||
self.__password = password
|
||||
|
@ -23,7 +23,7 @@ class WMIEXEC:
|
|||
self.__shell = 'cmd.exe /Q /c '
|
||||
self.__pwd = 'C:\\'
|
||||
self.__aesKey = None
|
||||
self.__doKerberos = False
|
||||
self.__doKerberos = doKerberos
|
||||
self.__retOutput = True
|
||||
|
||||
if hashes is not None:
|
||||
|
@ -35,8 +35,7 @@ class WMIEXEC:
|
|||
|
||||
if self.__password is None:
|
||||
self.__password = ''
|
||||
|
||||
self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver = True, doKerberos=self.__doKerberos)
|
||||
self.__dcom = DCOMConnection(self.__target, self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey, oxidResolver=True, doKerberos=self.__doKerberos)
|
||||
iInterface = self.__dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login,wmi.IID_IWbemLevel1Login)
|
||||
iWbemLevel1Login = wmi.IWbemLevel1Login(iInterface)
|
||||
iWbemServices= iWbemLevel1Login.NTLMLogin('//./root/cimv2', NULL, NULL)
|
||||
|
|
Loading…
Reference in New Issue