diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 3a4aff047..f2be2112b 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -78,7 +78,8 @@ optDict = { "timeTest": "boolean", "timeSec": "integer", "unionTest": "boolean", - "uTech": "string" + "uTech": "string", + "uCols": "integer" }, "Fingerprint": { @@ -115,7 +116,7 @@ optDict = { "Brute": { "commonTables": "boolean", - "commonColumns": "boolean", + "commonColumns": "boolean" }, "User-defined function": { diff --git a/lib/core/session.py b/lib/core/session.py index ec92146b2..25c02ea8b 100644 --- a/lib/core/session.py +++ b/lib/core/session.py @@ -207,7 +207,7 @@ def setError(): if condition: dataToSessionFile("[%s][%s][%s][Error based injection][Yes]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]))) -def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False): +def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False, payload=None): """ @param comment: union comment to save in session file @type comment: C{str} @@ -270,6 +270,18 @@ def setUnion(comment=None, count=None, position=None, negative=False, falseCond= kb.unionFalseCond = True + if payload: + condition = ( + not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and + ( not kb.resumedQueries[conf.url].has_key("Union payload") + ) ) + ) + + if condition: + dataToSessionFile("[%s][%s][%s][Union payload][%s]\n" % (conf.url, kb.injPlace, safeFormatString(conf.parameters[kb.injPlace]), payload)) + + kb.unionTest = payload + def setRemoteTempPath(): condition = ( not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and @@ -483,6 +495,13 @@ def resumeConfKb(expression, url, value): logMsg += "%s from session file" % kb.unionPosition logger.info(logMsg) + elif expression == "Union payload" and url == conf.url: + kb.unionTest = value[:-1] + + logMsg = "resuming union payload " + logMsg += "%s from session file" % kb.unionTest + logger.info(logMsg) + elif expression == "Remote temp path" and url == conf.url: conf.tmpPath = unSafeFormatString(value[:-1]) diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 8daf6948b..33da1f328 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -243,6 +243,9 @@ def cmdLineParser(): techniques.add_option("--union-tech", dest="uTech", help="Technique to test for UNION query SQL injection") + techniques.add_option("--union-cols", dest="uCols", type="int", default=50, + help="Maximum number of columns to test for") + # Fingerprint options fingerprint = OptionGroup(parser, "Fingerprint") diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 3ab4fe6ab..c22a94c03 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -124,7 +124,7 @@ def __unionTestByNULLBruteforce(comment, negative=False, falseCond=False): columns = None query = agent.prefixQuery("UNION ALL SELECT NULL") - for count in range(0, 50): + for count in range(0, conf.uCols+1): if kb.dbms == DBMS.ORACLE and query.endswith(" FROM DUAL"): query = query[:-len(" FROM DUAL")] @@ -149,7 +149,7 @@ def __unionTestByOrderBy(comment, negative=False, falseCond=False): columns = None prevPayload = "" - for count in range(1, 51): + for count in range(1, conf.uCols+2): query = agent.prefixQuery("ORDER BY %d" % count) orderByQuery = agent.postfixQuery(query, comment) payload = agent.payload(newValue=orderByQuery, negative=negative, falseCond=falseCond) @@ -224,9 +224,7 @@ def unionTest(): warnMsg += "inband sql injection vulnerability" logger.warn(warnMsg) - if validPayload is None: - validPayload = "" - elif isinstance(validPayload, basestring): - kb.unionTest = agent.removePayloadDelimiters(validPayload, False) + validPayload = agent.removePayloadDelimiters(validPayload, False) + setUnion(payload=validPayload) return kb.unionTest diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index c0cf85003..8bfc3ed4d 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -46,7 +46,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh if resetCounter: reqCount = 0 - if not kb.unionCount: + if not kb.unionTest: unionTest() if not kb.unionCount: diff --git a/sqlmap.conf b/sqlmap.conf index 0c15cc649..085c536bb 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -262,6 +262,11 @@ unionTest = False # Default: NULL uTech = NULL +# Maximum number of columns to test for +# Valid: integer +# Default: 50 +uCols = 50 + [Fingerprint]