diff --git a/lib/core/option.py b/lib/core/option.py index edb5628d2..89e7efd8b 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -488,36 +488,50 @@ def __setWriteFile(): conf.wFileType = getFileType(conf.wFile) def __setUnion(): - if isinstance(conf.uChar, basestring) and conf.uChar != "NULL" and not conf.uChar.isdigit(): - if not conf.uChar.startswith("'") or not conf.uChar.endswith("'"): - debugMsg = "setting the UNION query SQL injection character to '%s'" % conf.uChar + if isinstance(conf.uTech, basestring): + debugMsg = "setting the UNION query SQL injection detection technique" + logger.debug(debugMsg) + + uTechOriginal = conf.uTech + conf.uTech = conf.uTech.lower() + + if conf.uTech and conf.uTech not in ( "char", "orderby" ): + infoMsg = "resetting the UNION query detection technique to " + infoMsg += "'char', '%s' is not a valid technique" % uTechOriginal + logger.info(infoMsg) + + conf.uTech = "char" + else: + debugMsg = "setting UNION query detection technique to " + debugMsg += "'%s'" % uTechOriginal + logger.debug(debugMsg) + + if isinstance(conf.uCols, basestring) and conf.uChar != "1-20": + debugMsg = "setting the UNION query SQL injection range of columns" + logger.debug(debugMsg) + + if "-" not in conf.uCols: + raise sqlmapSyntaxException, "--union-cols must be a range with hyphon" + + conf.uCols = conf.uCols.replace(" ", "") + conf.uColsStart, conf.uColsStop = conf.uCols.split("-") + + if not conf.uColsStart.isdigit() or not conf.uColsStop.isdigit(): + raise sqlmapSyntaxException, "--union-cols must be a range of integers" + + conf.uColsStart = int(conf.uColsStart) + conf.uColsStop = int(conf.uColsStop) + + if isinstance(conf.uChar, basestring) and conf.uChar != "NULL": + debugMsg = "setting the UNION query SQL injection character to '%s'" % conf.uChar + logger.debug(debugMsg) + + if not conf.uChar.isdigit() and ( not conf.uChar.startswith("'") or not conf.uChar.endswith("'") ): + debugMsg = "forcing the UNION query SQL injection character to '%s'" % conf.uChar logger.debug(debugMsg) conf.uChar = "'%s'" % conf.uChar - if conf.uTech is None: - conf.uTech = "NULL" - - return - - debugMsg = "setting the UNION query SQL injection detection technique" - logger.debug(debugMsg) - - uTechOriginal = conf.uTech - conf.uTech = conf.uTech.lower() - - if conf.uTech and conf.uTech not in ( "null", "orderby" ): - infoMsg = "resetting the UNION query detection technique to " - infoMsg += "'NULL', '%s' is not a valid technique" % uTechOriginal - logger.info(infoMsg) - - conf.uTech = "NULL" - - else: - debugMsg = "setting UNION query detection technique to " - debugMsg += "'%s'" % uTechOriginal - logger.debug(debugMsg) - def __setOS(): """ Force the back-end DBMS operating system option. diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 562cfc557..7d791c79d 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -240,11 +240,11 @@ def cmdLineParser(): action="store_true", default=False, help="Test for and use UNION query (inband) SQL injection") - techniques.add_option("--union-tech", dest="uTech", + techniques.add_option("--union-tech", dest="uTech", default="char", help="Technique to test for UNION query SQL injection") - techniques.add_option("--union-cols", dest="uCols", type="int", default=20, - help="Maximum number of columns to test for") + techniques.add_option("--union-cols", dest="uCols", default="1-20", + help="Range of columns to test for UNION query SQL injection") techniques.add_option("--union-char", dest="uChar", default="NULL", help="Character to use to bruteforce number of columns") diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 032e19724..beee80cf5 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -99,7 +99,7 @@ def __unionTestByCharBruteforce(comment): query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar) - for count in range(1, conf.uCols+1): + for count in range(conf.uColsStart, conf.uColsStop+1): if kb.dbms == DBMS.ORACLE and query.endswith(" FROM DUAL"): query = query[:-len(" FROM DUAL")] @@ -121,7 +121,7 @@ def __unionTestByOrderBy(comment): columns = None prevPayload = "" - for count in range(1, conf.uCols+2): + for count in range(conf.uColsStart, conf.uColsStop+1): query = agent.prefixQuery("ORDER BY %d" % count) orderByQuery = agent.suffixQuery(query, comment) payload = agent.payload(newValue=orderByQuery, negative=negative, falseCond=falseCond) @@ -161,17 +161,15 @@ def unionTest(): logger.info(infoMsg) validPayload = None + comment = queries[kb.dbms].comment.query - for comment in (queries[kb.dbms].comment.query, ""): - if conf.uTech == "orderby": - validPayload = __unionTestByOrderBy(comment) - else: - validPayload = __unionTestByCharBruteforce(comment) + if conf.uTech == "orderby": + validPayload = __unionTestByOrderBy(comment) + else: + validPayload = __unionTestByCharBruteforce(comment) - if validPayload: - setUnion(comment=comment) - - break + if validPayload: + setUnion(comment=comment) if isinstance(kb.unionPosition, int): infoMsg = "the target url is affected by an exploitable " diff --git a/sqlmap.conf b/sqlmap.conf index 14309b73a..8f928ec00 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -256,14 +256,14 @@ unionTest = False # Technique to test for UNION query SQL injection # The possible techniques are by NULL bruteforcing (bf) or by ORDER BY # clause (ob) -# Valid: NULL, OrderBy -# Default: NULL -uTech = NULL +# Valid: char, OrderBy +# Default: char +uTech = char -# Maximum number of columns to test for -# Valid: integer -# Default: 20 -uCols = 20 +# Range of columns to test for +# Valid: range of integers +# Default: 1-20 +uCols = 1-20 # Character to use to bruteforce number of columns # Valid: string