From c2a358561ffbbb61fbbb4f4e8a78b5c940aa8ebe Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Mon, 17 Jan 2011 22:57:33 +0000 Subject: [PATCH] Proper support for --union-cols --- lib/controller/checks.py | 19 +++++++- lib/techniques/inband/union/use.py | 70 +++++++++++++++--------------- xml/payloads.xml | 41 +++++++++++++++++ 3 files changed, 93 insertions(+), 37 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index f7c145a8a..c9830c6b2 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -55,8 +55,8 @@ from lib.core.threads import getCurrentThreadData from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request from lib.request.templates import getPageTemplate -from lib.techniques.inband.union.use import configUnion from lib.techniques.inband.union.test import unionTest +from lib.techniques.inband.union.use import configUnion def unescape(string, dbms): if string is None: @@ -100,6 +100,14 @@ def checkSqlInjection(place, parameter, value): stype = test.stype clause = test.clause + if stype == 3 and test.request.columns == "[COLSTART]-[COLSTOP]": + if conf.uCols is None: + continue + else: + configUnion() + title = title.replace("[COLSTART]", str(conf.uColsStart)) + title = title.replace("[COLSTOP]", str(conf.uColsStop)) + # Skip test if the user's wants to test only for a specific # technique if conf.technique and isinstance(conf.technique, int) and stype != conf.technique: @@ -383,13 +391,20 @@ def checkSqlInjection(place, parameter, value): # current test settings for proper unescaping kb.misc.forcedDbms = dbms + if conf.uCols is not None and test.request.columns != "[COLSTART]-[COLSTOP]": + debugMsg = "skipping test '%s' because custom " % title + debugMsg += "UNION columns range was provided" + logger.debug(debugMsg) + continue + + configUnion(test.request.char, test.request.columns) + if not getIdentifiedDBMS(): warnMsg = "using unescaped version of the test " warnMsg += "because of zero knowledge of the " warnMsg += "back-end DBMS" logger.warn(warnMsg) - configUnion(test.request.char, test.request.columns) reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix) if isinstance(reqPayload, basestring): diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 1cc04c79a..6d2f5fb4d 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -32,6 +32,41 @@ from lib.utils.resume import resume reqCount = 0 +def __configUnionChar(char): + if char.isdigit() or char == "NULL": + conf.uChar = char + elif not char.startswith("'") or not char.endswith("'"): + conf.uChar = "'%s'" % char + +def __configUnionCols(columns): + if "-" not in columns or len(columns.split("-")) != 2: + raise sqlmapSyntaxException, "--union-cols must be a range with hyphon (e.g. 1-10)" + + columns = columns.replace(" ", "") + conf.uColsStart, conf.uColsStop = columns.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 conf.uColsStart > conf.uColsStop: + errMsg = "--union-cols range has to be from lower to " + errMsg += "higher number of columns" + raise sqlmapSyntaxException, errMsg + +def configUnion(char=None, columns=None): + if isinstance(conf.uChar, basestring): + __configUnionChar(conf.uChar) + elif isinstance(char, basestring): + __configUnionChar(char) + + if isinstance(conf.uCols, basestring): + __configUnionCols(conf.uCols) + elif isinstance(columns, basestring): + __configUnionCols(columns) + def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack=True, dump=False): """ This function tests for an inband SQL injection on the target @@ -236,38 +271,3 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack logger.debug(debugMsg) return value - -def __configUnionChar(char): - if char.isdigit() or char == "NULL": - conf.uChar = char - elif not char.startswith("'") or not char.endswith("'"): - conf.uChar = "'%s'" % char - -def __configUnionCols(columns): - if "-" not in columns or len(columns.split("-")) != 2: - raise sqlmapSyntaxException, "--union-cols must be a range with hyphon (e.g. 1-10)" - - columns = columns.replace(" ", "") - conf.uColsStart, conf.uColsStop = columns.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 conf.uColsStart > conf.uColsStop: - errMsg = "--union-cols range has to be from lower to " - errMsg += "higher number of columns" - raise sqlmapSyntaxException, errMsg - -def configUnion(char, columns): - if isinstance(conf.uChar, basestring): - __configUnionChar(conf.uChar) - elif isinstance(char, basestring): - __configUnionChar(char) - - if isinstance(conf.uCols, basestring): - __configUnionCols(conf.uCols) - elif isinstance(columns, basestring): - __configUnionCols(columns) diff --git a/xml/payloads.xml b/xml/payloads.xml index 372943511..67cf4e5b0 100644 --- a/xml/payloads.xml +++ b/xml/payloads.xml @@ -2082,6 +2082,28 @@ Formats: + + MySQL NULL UNION query - [COLSTART] to [COLSTOP] columns + 3 + 1 + 1 + 1,2,3,4,5 + 1 + [UNION] + + + # + NULL + [COLSTART]-[COLSTOP] + + + + +
+ MySQL +
+
+ MySQL NULL UNION query - 1 to 3 columns 3 @@ -2192,6 +2214,25 @@ Formats: + + Generic NULL UNION query - [COLSTART] to [COLSTOP] columns + 3 + 1 + 1 + 1,2,3,4,5 + 1 + [UNION] + + + -- + NULL + [COLSTART]-[COLSTOP] + + + + + + Generic NULL UNION query - 1 to 3 columns 3