Fixed previous bug in getErrorParsedDBMSes() call in detection phase.

Added minor support to escape quotes in UNION payloads during detection phase.
This commit is contained in:
Bernardo Damele 2011-01-11 23:47:32 +00:00
parent aa49aa579f
commit 5c7c3c76c3
5 changed files with 27 additions and 25 deletions

View File

@ -149,14 +149,15 @@ def checkSqlInjection(place, parameter, value):
continue continue
# NOTE: Leave this commented for the time being if getErrorParsedDBMSes() and dbms not in getErrorParsedDBMSes() and kb.skipOthersDbms is None:
#if getErrorParsedDBMSes() and dbms not in getErrorParsedDBMSes() and kb.skipTests is None: msg = "parsed error message(s) showed that the "
# msg = "parsed error message(s) showed that the " msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted()
# msg += "back-end DBMS could be '%s'. " % getErrorParsedDBMSesFormatted() msg += "Do you want to skip test payloads specific for other DBMSes? [Y/n]"
# 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 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 = "skipping test '%s' because " % title
debugMsg += "the parsed error message(s) showed " debugMsg += "the parsed error message(s) showed "
debugMsg += "that the back-end DBMS could be " debugMsg += "that the back-end DBMS could be "
@ -378,7 +379,8 @@ def checkSqlInjection(place, parameter, value):
elif method == PAYLOAD.METHOD.UNION: elif method == PAYLOAD.METHOD.UNION:
configUnion(test.request.char, test.request.columns) 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): if isinstance(reqPayload, basestring):
infoMsg = "%s parameter '%s' is '%s' injectable" % (place, parameter, title) infoMsg = "%s parameter '%s' is '%s' injectable" % (place, parameter, title)

View File

@ -1159,7 +1159,7 @@ def __setKnowledgeBaseAttributes(flushAll=True):
kb.responseTimes = [] kb.responseTimes = []
kb.resumedQueries = {} kb.resumedQueries = {}
kb.retriesCount = 0 kb.retriesCount = 0
kb.skipTests = None kb.skipOthersDbms = None
kb.suppressSession = False kb.suppressSession = False
kb.technique = None kb.technique = None
kb.testMode = False kb.testMode = False

View File

@ -11,9 +11,13 @@ from lib.core.data import kb
from lib.core.datatype import advancedDict from lib.core.datatype import advancedDict
class Unescaper(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: 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: elif hasattr(kb.misc, "testedDbms") and kb.misc.testedDbms is not None:
return self[kb.misc.testedDbms](expression, quote=quote) return self[kb.misc.testedDbms](expression, quote=quote)
else: else:

View File

@ -26,7 +26,7 @@ from lib.core.unescaper import unescaper
from lib.parse.html import htmlParser from lib.parse.html import htmlParser
from lib.request.connect import Connect as Request 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 validPayload = None
unionVector = None unionVector = None
@ -40,7 +40,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, count, whe
# Prepare expression with delimiters # Prepare expression with delimiters
randQuery = randomStr() randQuery = randomStr()
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery) randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
randQueryUnescaped = unescaper.unescape(randQueryProcessed) randQueryUnescaped = unescaper.unescape(randQueryProcessed, dbms=dbms)
# Forge the inband SQL injection request # Forge the inband SQL injection request
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition, count=count, comment=comment, prefix=prefix, suffix=suffix) 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 # Prepare expression with delimiters
randQuery2 = randomStr() randQuery2 = randomStr()
randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2) randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2) randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2, dbms=dbms)
# Confirm that it is a full inband SQL injection # Confirm that it is a full inband SQL injection
query = agent.forgeInbandQuery(randQueryUnescaped, exprPosition, count=count, comment=comment, prefix=prefix, suffix=suffix, multipleUnions=randQueryUnescaped2) 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 return validPayload, unionVector
def __unionConfirm(comment, place, parameter, value, prefix, suffix, count): def __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count):
validPayload = None validPayload = None
unionVector = None unionVector = None
# Confirm the inband SQL injection and get the exact column # Confirm the inband SQL injection and get the exact column
# position which can be used to extract data # position which can be used to extract data
if not isinstance(kb.unionPosition, int): 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 # Assure that the above function found the exploitable full inband
# SQL injection position # SQL injection position
if not isinstance(kb.unionPosition, int): 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 # Assure that the above function found the exploitable partial
# (single entry) inband SQL injection position with negative # (single entry) inband SQL injection position with negative
@ -98,7 +98,7 @@ def __unionConfirm(comment, place, parameter, value, prefix, suffix, count):
return validPayload, unionVector 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 This method tests if the target url is affected by an inband
SQL injection vulnerability. The test is done up to 50 columns 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 debugMsg = "testing number of columns: %s" % status
logger.debug(debugMsg) 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: if validPayload:
setUnion(count=count) setUnion(count=count)
@ -133,7 +133,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
return validPayload, unionVector 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 This method tests if the target url is affected by an inband
SQL injection vulnerability. The test is done up to 3*50 times 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 oldTechnique = kb.technique
kb.technique = PAYLOAD.TECHNIQUE.UNION 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: if validPayload:
validPayload = agent.removePayloadDelimiters(validPayload, False) validPayload = agent.removePayloadDelimiters(validPayload, False)

View File

@ -25,7 +25,6 @@ from lib.core.enums import DBMS
from lib.core.enums import PAYLOAD from lib.core.enums import PAYLOAD
from lib.core.unescaper import unescaper from lib.core.unescaper import unescaper
from lib.request.connect import Connect as Request from lib.request.connect import Connect as Request
from lib.techniques.inband.union.test import unionTest
from lib.utils.resume import resume from lib.utils.resume import resume
reqCount = 0 reqCount = 0
@ -52,9 +51,6 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
if resetCounter: if resetCounter:
reqCount = 0 reqCount = 0
if not kb.unionTest:
unionTest()
if not kb.unionCount: if not kb.unionCount:
return return