From ad17e9ed2a1169fdcb9fdc5414d867fedbda1935 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Fri, 19 Nov 2010 14:56:20 +0000 Subject: [PATCH] Added new switch --union-char to be able to provide the character used in union-test and exploit (default is still NULL, but can be any) --- doc/THANKS | 2 +- lib/core/agent.py | 5 ++++- lib/core/option.py | 11 +++++++++-- lib/core/optiondict.py | 3 ++- lib/parse/cmdline.py | 5 ++++- lib/techniques/inband/union/test.py | 12 +++++++----- lib/techniques/inband/union/use.py | 2 +- sqlmap.conf | 5 +++++ 8 files changed, 33 insertions(+), 12 deletions(-) diff --git a/doc/THANKS b/doc/THANKS index 65bd4f694..687563e2f 100644 --- a/doc/THANKS +++ b/doc/THANKS @@ -246,7 +246,7 @@ Anastasios Monachos Alejo Murillo Moya for reporting a minor bug - for suggesting a feature + for suggesting a few features Roberto Nemirovsky for pointing me out some enhancements diff --git a/lib/core/agent.py b/lib/core/agent.py index 6fda4f72d..7fe382c58 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -425,7 +425,7 @@ class Agent: return concatenatedQuery - def forgeInbandQuery(self, query, exprPosition=None, nullChar="NULL", count=None, comment=None): + def forgeInbandQuery(self, query, exprPosition=None, nullChar=None, count=None, comment=None): """ Take in input an query (pseudo query) string and return its processed UNION ALL SELECT query. @@ -456,6 +456,9 @@ class Agent: @rtype: C{str} """ + if nullChar is None: + nullChar = conf.uChar + if count is None: count = kb.unionCount diff --git a/lib/core/option.py b/lib/core/option.py index 0fe951c91..edb5628d2 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -487,7 +487,14 @@ def __setWriteFile(): conf.wFileType = getFileType(conf.wFile) -def __setUnionTech(): +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 + logger.debug(debugMsg) + + conf.uChar = "'%s'" % conf.uChar + if conf.uTech is None: conf.uTech = "NULL" @@ -1341,7 +1348,7 @@ def init(inputOptions=advancedDict()): __setHTTPAuthentication() __setHTTPProxy() __setSafeUrl() - __setUnionTech() + __setUnion() __setGoogleDorking() __urllib2Opener() __findPageForms() diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 7eb5ad968..3a3378a1d 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -79,7 +79,8 @@ optDict = { "timeSec": "integer", "unionTest": "boolean", "uTech": "string", - "uCols": "integer" + "uCols": "integer", + "uChar": "string" }, "Fingerprint": { diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index 56b3f6682..562cfc557 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -243,9 +243,12 @@ 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, + techniques.add_option("--union-cols", dest="uCols", type="int", default=20, help="Maximum number of columns to test for") + techniques.add_option("--union-char", dest="uChar", default="NULL", + help="Character to use to bruteforce number of columns") + # Fingerprint options fingerprint = OptionGroup(parser, "Fingerprint") diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 6db976e38..032e19724 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -90,21 +90,21 @@ def __unionConfirm(count=None, comment=None): return validPayload -def __unionTestByNULLBruteforce(comment): +def __unionTestByCharBruteforce(comment): """ This method tests if the target url is affected by an inband SQL injection vulnerability. The test is done up to 50 columns on the target database table """ - query = agent.prefixQuery("UNION ALL SELECT NULL") + query = agent.prefixQuery("UNION ALL SELECT %s" % conf.uChar) for count in range(1, conf.uCols+1): if kb.dbms == DBMS.ORACLE and query.endswith(" FROM DUAL"): query = query[:-len(" FROM DUAL")] if count: - query += ", NULL" + query += ", %s" % conf.uChar if kb.dbms == DBMS.ORACLE: query += " FROM DUAL" @@ -151,8 +151,10 @@ def unionTest(): if conf.uTech == "orderby": technique = "ORDER BY clause bruteforcing" - else: + elif conf.uChar == "NULL": technique = "NULL bruteforcing" + else: + technique = "char (%s) bruteforcing" % conf.uChar infoMsg = "testing inband sql injection on parameter " infoMsg += "'%s' with %s technique" % (kb.injParameter, technique) @@ -164,7 +166,7 @@ def unionTest(): if conf.uTech == "orderby": validPayload = __unionTestByOrderBy(comment) else: - validPayload = __unionTestByNULLBruteforce(comment) + validPayload = __unionTestByCharBruteforce(comment) if validPayload: setUnion(comment=comment) diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 8bfc3ed4d..a3d0ec97c 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -26,7 +26,7 @@ from lib.utils.resume import resume reqCount = 0 -def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar="NULL", unpack=True, dump=False): +def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullChar=None, unpack=True, dump=False): """ This function tests for an inband SQL injection on the target url then call its subsidiary function to effectively perform an diff --git a/sqlmap.conf b/sqlmap.conf index b8e88d88c..14309b73a 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -265,6 +265,11 @@ uTech = NULL # Default: 20 uCols = 20 +# Character to use to bruteforce number of columns +# Valid: string +# Default: NULL +uChar = NULL + [Fingerprint]