Major bug fix.

Minor code refactoring.
This commit is contained in:
Bernardo Damele 2011-01-16 01:17:09 +00:00
parent c0d5daee99
commit 0fc4ebdc1b
4 changed files with 24 additions and 32 deletions

View File

@ -72,11 +72,13 @@ def unescapeDbms(payload, injection, dbms):
# provided a DBMS (conf.dbms), unescape the strings between single
# quotes in the payload
if injection.dbms is not None:
payload = unescape(payload, injection.dbms)
payload = unescape(payload, dbms=injection.dbms)
elif dbms is not None:
payload = unescape(payload, dbms)
payload = unescape(payload, dbms=dbms)
elif conf.dbms is not None:
payload = unescape(payload, conf.dbms)
payload = unescape(payload, dbms=conf.dbms)
elif getIdentifiedDBMS() is not None:
payload = unescape(payload, dbms=getIdentifiedDBMS())
return payload
@ -387,8 +389,7 @@ def checkSqlInjection(place, parameter, value):
logger.warn(warnMsg)
configUnion(test.request.char, test.request.columns)
dbmsToUnescape = kb.misc.fpDbms if kb.misc.fpDbms is not None else injection.dbms
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix, dbmsToUnescape)
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
if isinstance(reqPayload, basestring):
infoMsg = "%s parameter '%s' is '%s' injectable" % (place, parameter, title)

View File

@ -422,26 +422,20 @@ class Agent:
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
if getIdentifiedDBMS() == DBMS.MYSQL:
if fieldsSelectCase:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
concatenatedQuery += ",'%s')" % kb.misc.stop
elif fieldsSelectFrom:
if fieldsSelectFrom:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % kb.misc.stop, 1)
elif fieldsSelect:
elif (fieldsSelect, fieldsSelectCase):
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
concatenatedQuery += ",'%s')" % kb.misc.stop
elif fieldsNoSelect:
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
elif getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE ):
if fieldsSelectCase:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery += "||'%s'" % kb.misc.stop
elif fieldsSelectFrom:
if fieldsSelectFrom:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % kb.misc.stop, 1)
elif fieldsSelect:
elif (fieldsSelect, fieldsSelectCase):
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
concatenatedQuery += "||'%s'" % kb.misc.stop
elif fieldsNoSelect:
@ -455,13 +449,10 @@ class Agent:
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
concatenatedQuery = concatenatedQuery.replace("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.misc.start), 1)
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 1)
elif fieldsSelectCase:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
concatenatedQuery += "+'%s'" % kb.misc.stop
elif fieldsSelectFrom:
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 1)
elif fieldsSelect:
elif (fieldsSelect, fieldsSelectCase):
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
concatenatedQuery += "+'%s'" % kb.misc.stop
elif fieldsNoSelect:
@ -524,7 +515,7 @@ class Agent:
inbandQuery += ", "
if element == position:
if " FROM " in query and "EXISTS(" not in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
if " FROM " in query and "EXISTS(" not in query and not query.startswith("SELECT "):
conditionIndex = query.index(" FROM ")
inbandQuery += query[:conditionIndex]
else:
@ -532,7 +523,7 @@ class Agent:
else:
inbandQuery += char
if " FROM " in query and "EXISTS(" not in query and not query.startswith("SELECT ") and "(CASE WHEN (" not in query:
if " FROM " in query and "EXISTS(" not in query and not query.startswith("SELECT "):
conditionIndex = query.index(" FROM ")
inbandQuery += query[conditionIndex:]

View File

@ -27,7 +27,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, dbms, count, where=1):
def __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=1):
validPayload = None
vector = None
@ -38,7 +38,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, coun
# Prepare expression with delimiters
randQuery = randomStr()
randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
randQueryUnescaped = unescaper.unescape(randQueryProcessed, dbms=dbms)
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
# Forge the inband SQL injection request
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, conf.uChar)
@ -55,7 +55,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, coun
# Prepare expression with delimiters
randQuery2 = randomStr()
randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2, dbms=dbms)
randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2)
# Confirm that it is a full inband SQL injection
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, conf.uChar, multipleUnions=randQueryUnescaped2)
@ -71,22 +71,22 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, coun
return validPayload, vector
def __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count):
def __unionConfirm(comment, place, parameter, value, prefix, suffix, count):
validPayload = None
vector = None
# Confirm the inband SQL injection and get the exact column
# position which can be used to extract data
validPayload, vector = __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, count)
validPayload, vector = __unionPosition(comment, place, parameter, value, prefix, suffix, count)
# Assure that the above function found the exploitable full inband
# SQL injection position
if not validPayload:
validPayload, vector = __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, count, where=2)
validPayload, vector = __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=2)
return validPayload, vector
def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix, dbms):
def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix):
"""
This method tests if the target url is affected by an inband
SQL injection vulnerability. The test is done up to 50 columns
@ -111,7 +111,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))
logger.debug(debugMsg)
validPayload, vector = __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count)
validPayload, vector = __unionConfirm(comment, place, parameter, value, prefix, suffix, count)
if validPayload:
break
@ -120,7 +120,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
return validPayload, vector
def unionTest(comment, place, parameter, value, prefix, suffix, dbms):
def unionTest(comment, place, parameter, value, prefix, suffix):
"""
This method tests if the target url is affected by an inband
SQL injection vulnerability. The test is done up to 3*50 times
@ -130,7 +130,7 @@ def unionTest(comment, place, parameter, value, prefix, suffix, dbms):
return
kb.technique = PAYLOAD.TECHNIQUE.UNION
validPayload, vector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix, dbms)
validPayload, vector = __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)
if validPayload:
validPayload = agent.removePayloadDelimiters(validPayload, False)

View File

@ -67,7 +67,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
# entry per time
# NOTE: I assume that only queries that get data from a table can
# return multiple entries
if " FROM " in expression and "EXISTS(" not in expression:
if " FROM " in expression.upper() and " FROM DUAL" not in expression.upper() and "EXISTS(" not in expression.upper():
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
if limitRegExp: