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