From 5c7c3c76c30acd4d4f95daa6b4adeb191a432aa8 Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Tue, 11 Jan 2011 23:47:32 +0000 Subject: [PATCH] Fixed previous bug in getErrorParsedDBMSes() call in detection phase. Added minor support to escape quotes in UNION payloads during detection phase. --- lib/controller/checks.py | 18 ++++++++++-------- lib/core/option.py | 2 +- lib/core/unescaper.py | 8 ++++++-- lib/techniques/inband/union/test.py | 20 ++++++++++---------- lib/techniques/inband/union/use.py | 4 ---- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 3aba7c579..8a4b26895 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -149,14 +149,15 @@ def checkSqlInjection(place, parameter, value): continue - # NOTE: Leave this commented for the time being - #if getErrorParsedDBMSes() and dbms not in getErrorParsedDBMSes() and kb.skipTests is None: - # msg = "parsed error message(s) showed that the " - # msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted() - # msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]" - # kb.skipTests = conf.realTest or readInput(msg, default="Y") not in ("n", "N") + if getErrorParsedDBMSes() and dbms not in getErrorParsedDBMSes() and kb.skipOthersDbms is None: + msg = "parsed error message(s) showed that the " + msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted() + msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]" - if kb.skipTests: + if conf.realTest or readInput(msg, default="Y") in ("y", "Y"): + kb.skipOthersDbms = getErrorParsedDBMSes() + + if kb.skipOthersDbms and dbms not in kb.skipOthersDbms: debugMsg = "skipping test '%s' because " % title debugMsg += "the parsed error message(s) showed " debugMsg += "that the back-end DBMS could be " @@ -378,7 +379,8 @@ def checkSqlInjection(place, parameter, value): elif method == PAYLOAD.METHOD.UNION: configUnion(test.request.char, test.request.columns) - reqPayload, unionVector = unionTest(comment, place, parameter, value, prefix, suffix) + dbmsToUnescape = dbms if dbms is not None else injection.dbms + reqPayload, unionVector = unionTest(comment, place, parameter, value, prefix, suffix, dbmsToUnescape) if isinstance(reqPayload, basestring): infoMsg = "%s parameter '%s' is '%s' injectable" % (place, parameter, title) diff --git a/lib/core/option.py b/lib/core/option.py index f5113fe97..64f37889c 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1159,7 +1159,7 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.responseTimes = [] kb.resumedQueries = {} kb.retriesCount = 0 - kb.skipTests = None + kb.skipOthersDbms = None kb.suppressSession = False kb.technique = None kb.testMode = False diff --git a/lib/core/unescaper.py b/lib/core/unescaper.py index a9ec6c8ca..33ca55d35 100644 --- a/lib/core/unescaper.py +++ b/lib/core/unescaper.py @@ -11,9 +11,13 @@ from lib.core.data import kb from lib.core.datatype import advancedDict class Unescaper(advancedDict): - def unescape(self, expression, quote=True): + def unescape(self, expression, quote=True, dbms=None): if hasattr(kb, "dbms") and kb.dbms is not None: - return self[kb.dbms if kb.dbms else kb.misc.testedDbms](expression, quote=quote) + return self[kb.dbms](expression, quote=quote) + elif hasattr(kb.misc, "testedDbms") and kb.misc.testedDbms is not None: + return self[kb.misc.testedDbms](expression, quote=quote) + if dbms is not None: + return self[dbms](expression, quote=quote) elif hasattr(kb.misc, "testedDbms") and kb.misc.testedDbms is not None: return self[kb.misc.testedDbms](expression, quote=quote) else: diff --git a/lib/techniques/inband/union/test.py b/lib/techniques/inband/union/test.py index f95d517fd..ca851e3ed 100644 --- a/lib/techniques/inband/union/test.py +++ b/lib/techniques/inband/union/test.py @@ -26,7 +26,7 @@ from lib.core.unescaper import unescaper from lib.parse.html import htmlParser from lib.request.connect import Connect as Request -def __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=1): +def __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, count, where=1): validPayload = None unionVector = None @@ -40,7 +40,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, count, whe # Prepare expression with delimiters randQuery = randomStr() randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery) - randQueryUnescaped = unescaper.unescape(randQueryProcessed) + randQueryUnescaped = unescaper.unescape(randQueryProcessed, dbms=dbms) # Forge the inband SQL injection request query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition, count=count, comment=comment, prefix=prefix, suffix=suffix) @@ -58,7 +58,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, count, whe # Prepare expression with delimiters randQuery2 = randomStr() randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2) - randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2) + randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2, dbms=dbms) # Confirm that it is a full inband SQL injection query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition, count=count, comment=comment, prefix=prefix, suffix=suffix, multipleUnions=randQueryUnescaped2) @@ -74,19 +74,19 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, count, whe return validPayload, unionVector -def __unionConfirm(comment, place, parameter, value, prefix, suffix, count): +def __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count): validPayload = None unionVector = None # Confirm the inband SQL injection and get the exact column # position which can be used to extract data if not isinstance(kb.unionPosition, int): - validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count) + validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, count) # Assure that the above function found the exploitable full inband # SQL injection position if not isinstance(kb.unionPosition, int): - validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=2) + validPayload, unionVector = __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, count, where=2) # Assure that the above function found the exploitable partial # (single entry) inband SQL injection position with negative @@ -98,7 +98,7 @@ def __unionConfirm(comment, place, parameter, value, prefix, suffix, count): return validPayload, unionVector -def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix): +def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix, dbms): """ This method tests if the target url is affected by an inband SQL injection vulnerability. The test is done up to 50 columns @@ -123,7 +123,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix debugMsg = "testing number of columns: %s" % status logger.debug(debugMsg) - validPayload, unionVector = __unionConfirm(comment, place, parameter, value, prefix, suffix, count) + validPayload, unionVector = __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count) if validPayload: setUnion(count=count) @@ -133,7 +133,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix return validPayload, unionVector -def unionTest(comment, place, parameter, value, prefix, suffix): +def unionTest(comment, place, parameter, value, prefix, suffix, dbms): """ This method tests if the target url is affected by an inband SQL injection vulnerability. The test is done up to 3*50 times @@ -144,7 +144,7 @@ def unionTest(comment, place, parameter, value, prefix, suffix): oldTechnique = kb.technique kb.technique = PAYLOAD.TECHNIQUE.UNION - validPayload, unionVector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix) + validPayload, unionVector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix, dbms) if validPayload: validPayload = agent.removePayloadDelimiters(validPayload, False) diff --git a/lib/techniques/inband/union/use.py b/lib/techniques/inband/union/use.py index 879f23262..3bebc1f85 100644 --- a/lib/techniques/inband/union/use.py +++ b/lib/techniques/inband/union/use.py @@ -25,7 +25,6 @@ from lib.core.enums import DBMS from lib.core.enums import PAYLOAD from lib.core.unescaper import unescaper from lib.request.connect import Connect as Request -from lib.techniques.inband.union.test import unionTest from lib.utils.resume import resume reqCount = 0 @@ -52,9 +51,6 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh if resetCounter: reqCount = 0 - if not kb.unionTest: - unionTest() - if not kb.unionCount: return