@@ -85,6 +85,24 @@ def checkSqlInjection(place, parameter, value):
8585 if kb .endDetection :
8686 break
8787
88+ if conf .dbms is None :
89+ if not injection .dbms and PAYLOAD .TECHNIQUE .BOOLEAN in injection .data :
90+ if not Backend .getIdentifiedDbms () and not kb .heuristicDbms :
91+ kb .heuristicDbms = heuristicCheckDbms (injection ) or UNKNOWN_DBMS
92+
93+ if not conf .testFilter and (Backend .getErrorParsedDBMSes () or kb .heuristicDbms ) not in ([], None , UNKNOWN_DBMS ):
94+ if kb .reduceTests is None and Backend .getErrorParsedDBMSes ():
95+ msg = "heuristic (parsing) test showed that the "
96+ msg += "back-end DBMS could be '%s'. " % (Format .getErrorParsedDBMSes () if Backend .getErrorParsedDBMSes () else kb .heuristicDbms )
97+ msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
98+ kb .reduceTests = [] if readInput (msg , default = 'Y' ).upper () != 'Y' else (Backend .getErrorParsedDBMSes () or [kb .heuristicDbms ])
99+
100+ if kb .extendTests is None :
101+ _ = (Format .getErrorParsedDBMSes () if Backend .getErrorParsedDBMSes () else kb .heuristicDbms )
102+ msg = "do you want to include all tests for '%s' " % _
103+ msg += "ignoring provided level (%d) and risk (%s)? [Y/n]" % (conf .level , conf .risk )
104+ kb .extendTests = [] if readInput (msg , default = 'Y' ).upper () != 'Y' else (Backend .getErrorParsedDBMSes () or [kb .heuristicDbms ])
105+
88106 title = test .title
89107 stype = test .stype
90108 clause = test .clause
@@ -143,15 +161,24 @@ def checkSqlInjection(place, parameter, value):
143161 logger .debug (debugMsg )
144162 continue
145163
164+
165+ # Skip DBMS-specific test if it does not match either the
166+ # previously identified or the user's provided DBMS (either
167+ # from program switch or from parsed error message(s))
168+ if "details" in test and "dbms" in test .details :
169+ dbms = test .details .dbms
170+ else :
171+ dbms = None
172+
146173 # Skip tests if title is not included by the given filter
147174 if conf .testFilter :
148- if not any (re .search (conf .testFilter , str (item ), re .I ) for item in (test .title , test .vector ,\
149- test .details .dbms if "details" in test and "dbms" in test .details else "" )):
175+ if not any (re .search (conf .testFilter , str (item ), re .I ) for item in (test .title , test .vector , dbms )):
150176 debugMsg = "skipping test '%s' because " % title
151177 debugMsg += "its name/vector/dbms is not included by the given filter"
152178 logger .debug (debugMsg )
153179 continue
154- else :
180+
181+ if not (kb .extendTests and intersect (dbms , kb .extendTests )):
155182 # Skip test if the risk is higher than the provided (or default)
156183 # value
157184 # Parse test's <risk>
@@ -170,14 +197,6 @@ def checkSqlInjection(place, parameter, value):
170197 logger .debug (debugMsg )
171198 continue
172199
173- # Skip DBMS-specific test if it does not match either the
174- # previously identified or the user's provided DBMS (either
175- # from program switch or from parsed error message(s))
176- if "details" in test and "dbms" in test .details :
177- dbms = test .details .dbms
178- else :
179- dbms = None
180-
181200 if dbms is not None :
182201 if injection .dbms is not None and not intersect (injection .dbms , dbms ):
183202 debugMsg = "skipping test '%s' because " % title
@@ -192,17 +211,7 @@ def checkSqlInjection(place, parameter, value):
192211 logger .debug (debugMsg )
193212 continue
194213
195- if conf .dbms is None and len (Backend .getErrorParsedDBMSes ()) > 0 and not intersect (dbms , Backend .getErrorParsedDBMSes ()) and kb .skipOthersDbms is None :
196- msg = "parsed error message(s) showed that the "
197- msg += "back-end DBMS could be %s. " % Format .getErrorParsedDBMSes ()
198- msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
199-
200- if readInput (msg , default = "Y" ) in ("y" , "Y" ):
201- kb .skipOthersDbms = Backend .getErrorParsedDBMSes ()
202- else :
203- kb .skipOthersDbms = []
204-
205- if kb .skipOthersDbms and not intersect (dbms , kb .skipOthersDbms ):
214+ if kb .reduceTests and not intersect (dbms , kb .reduceTests ):
206215 debugMsg = "skipping test '%s' because " % title
207216 debugMsg += "the parsed error message(s) showed "
208217 debugMsg += "that the back-end DBMS could be "
@@ -444,10 +453,7 @@ def genCmpPayload():
444453 configUnion (test .request .char , test .request .columns )
445454
446455 if not Backend .getIdentifiedDbms ():
447- if not kb .heuristicDbms :
448- kb .heuristicDbms = heuristicCheckDbms (injection ) or UNKNOWN_DBMS
449-
450- if kb .heuristicDbms == UNKNOWN_DBMS :
456+ if kb .heuristicDbms in (None , UNKNOWN_DBMS ):
451457 warnMsg = "using unescaped version of the test "
452458 warnMsg += "because of zero knowledge of the "
453459 warnMsg += "back-end DBMS. You can try to "
@@ -556,8 +562,8 @@ def genCmpPayload():
556562 warnMsg = "user aborted during detection phase"
557563 logger .warn (warnMsg )
558564
559- message = "How do you want to proceed? [(S)kip current test/(e)nd detection phase/(n)ext parameter/(q)uit]"
560- choice = readInput (message , default = "S" , checkBatch = False )
565+ msg = "How do you want to proceed? [(S)kip current test/(e)nd detection phase/(n)ext parameter/(q)uit]"
566+ choice = readInput (msg , default = "S" , checkBatch = False )
561567
562568 if choice [0 ] in ("s" , "S" ):
563569 pass
@@ -594,24 +600,23 @@ def genCmpPayload():
594600def heuristicCheckDbms (injection ):
595601 retVal = None
596602
597- if not Backend .getIdentifiedDbms () and len (injection .data ) == 1 and PAYLOAD .TECHNIQUE .BOOLEAN in injection .data :
598- pushValue (kb .injection )
599- kb .injection = injection
600- randStr1 , randStr2 = randomStr (), randomStr ()
603+ pushValue (kb .injection )
604+ kb .injection = injection
605+ randStr1 , randStr2 = randomStr (), randomStr ()
601606
602- for dbms in getPublicTypeMembers (DBMS , True ):
603- Backend .forceDbms (dbms )
607+ for dbms in getPublicTypeMembers (DBMS , True ):
608+ Backend .forceDbms (dbms )
604609
605- if checkBooleanExpression ("(SELECT '%s'%s)='%s'" % (randStr1 , FROM_DUMMY_TABLE .get (dbms , "" ), randStr1 )):
606- if not checkBooleanExpression ("(SELECT '%s'%s)='%s'" % (randStr1 , FROM_DUMMY_TABLE .get (dbms , "" ), randStr2 )):
607- retVal = dbms
608- break
610+ if checkBooleanExpression ("(SELECT '%s'%s)='%s'" % (randStr1 , FROM_DUMMY_TABLE .get (dbms , "" ), randStr1 )):
611+ if not checkBooleanExpression ("(SELECT '%s'%s)='%s'" % (randStr1 , FROM_DUMMY_TABLE .get (dbms , "" ), randStr2 )):
612+ retVal = dbms
613+ break
609614
610- Backend .flushForcedDbms ()
611- kb .injection = popValue ()
615+ Backend .flushForcedDbms ()
616+ kb .injection = popValue ()
612617
613618 if retVal :
614- infoMsg = "heuristic test showed that the back-end DBMS "
619+ infoMsg = "heuristic (extended) test shows that the back-end DBMS " # not as important as "parsing" counter-part (because of false-positives)
615620 infoMsg += "could be '%s' " % retVal
616621 logger .info (infoMsg )
617622
@@ -725,7 +730,7 @@ def heuristicCheckSqlInjection(place, parameter):
725730 parseFilePaths (page )
726731 result = wasLastResponseDBMSError ()
727732
728- infoMsg = "heuristic test shows that %s " % place
733+ infoMsg = "heuristic (parsing) test shows that %s " % place
729734 infoMsg += "parameter '%s' might " % parameter
730735
731736 def _ (page ):
@@ -758,7 +763,7 @@ def _(page):
758763 kb .ignoreCasted = readInput (message , default = 'Y' if conf .multipleTargets else 'N' ).upper () != 'N'
759764
760765 elif result :
761- infoMsg += "be injectable (possible DBMS: %s )" % (Format .getErrorParsedDBMSes () or UNKNOWN_DBMS )
766+ infoMsg += "be injectable (possible DBMS: '%s' )" % (Format .getErrorParsedDBMSes () or UNKNOWN_DBMS )
762767 logger .info (infoMsg )
763768
764769 else :
0 commit comments