mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-03-23 19:34:13 +03:00
Major bug fix.
Minor code refactoring.
This commit is contained in:
parent
c0d5daee99
commit
0fc4ebdc1b
|
@ -72,11 +72,13 @@ def unescapeDbms(payload, injection, dbms):
|
||||||
# provided a DBMS (conf.dbms), unescape the strings between single
|
# provided a DBMS (conf.dbms), unescape the strings between single
|
||||||
# quotes in the payload
|
# quotes in the payload
|
||||||
if injection.dbms is not None:
|
if injection.dbms is not None:
|
||||||
payload = unescape(payload, injection.dbms)
|
payload = unescape(payload, dbms=injection.dbms)
|
||||||
elif dbms is not None:
|
elif dbms is not None:
|
||||||
payload = unescape(payload, dbms)
|
payload = unescape(payload, dbms=dbms)
|
||||||
elif conf.dbms is not None:
|
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
|
return payload
|
||||||
|
|
||||||
|
@ -387,8 +389,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
configUnion(test.request.char, test.request.columns)
|
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)
|
||||||
reqPayload, vector = 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)
|
||||||
|
|
|
@ -422,26 +422,20 @@ class Agent:
|
||||||
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
fieldsSelectFrom, fieldsSelect, fieldsNoSelect, fieldsSelectTop, fieldsSelectCase, _, fieldsToCastStr = self.getFields(query)
|
||||||
|
|
||||||
if getIdentifiedDBMS() == DBMS.MYSQL:
|
if getIdentifiedDBMS() == DBMS.MYSQL:
|
||||||
if fieldsSelectCase:
|
if fieldsSelectFrom:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
|
||||||
concatenatedQuery += ",'%s')" % kb.misc.stop
|
|
||||||
elif fieldsSelectFrom:
|
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
||||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", ",'%s') FROM " % kb.misc.stop, 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 = concatenatedQuery.replace("SELECT ", "CONCAT('%s'," % kb.misc.start, 1)
|
||||||
concatenatedQuery += ",'%s')" % kb.misc.stop
|
concatenatedQuery += ",'%s')" % kb.misc.stop
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
concatenatedQuery = "CONCAT('%s',%s,'%s')" % (kb.misc.start, concatenatedQuery, kb.misc.stop)
|
||||||
|
|
||||||
elif getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE ):
|
elif getIdentifiedDBMS() in ( DBMS.PGSQL, DBMS.ORACLE, DBMS.SQLITE ):
|
||||||
if fieldsSelectCase:
|
if fieldsSelectFrom:
|
||||||
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("SELECT ", "'%s'||" % kb.misc.start, 1)
|
||||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "||'%s' FROM " % kb.misc.stop, 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 = concatenatedQuery.replace("SELECT ", "'%s'||" % kb.misc.start, 1)
|
||||||
concatenatedQuery += "||'%s'" % kb.misc.stop
|
concatenatedQuery += "||'%s'" % kb.misc.stop
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
|
@ -455,13 +449,10 @@ class Agent:
|
||||||
topNum = re.search("\ASELECT\s+TOP\s+([\d]+)\s+", concatenatedQuery, re.I).group(1)
|
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("SELECT TOP %s " % topNum, "TOP %s '%s'+" % (topNum, kb.misc.start), 1)
|
||||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 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:
|
elif fieldsSelectFrom:
|
||||||
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
|
concatenatedQuery = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
|
||||||
concatenatedQuery = concatenatedQuery.replace(" FROM ", "+'%s' FROM " % kb.misc.stop, 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 = concatenatedQuery.replace("SELECT ", "'%s'+" % kb.misc.start, 1)
|
||||||
concatenatedQuery += "+'%s'" % kb.misc.stop
|
concatenatedQuery += "+'%s'" % kb.misc.stop
|
||||||
elif fieldsNoSelect:
|
elif fieldsNoSelect:
|
||||||
|
@ -524,7 +515,7 @@ class Agent:
|
||||||
inbandQuery += ", "
|
inbandQuery += ", "
|
||||||
|
|
||||||
if element == position:
|
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 ")
|
conditionIndex = query.index(" FROM ")
|
||||||
inbandQuery += query[:conditionIndex]
|
inbandQuery += query[:conditionIndex]
|
||||||
else:
|
else:
|
||||||
|
@ -532,7 +523,7 @@ class Agent:
|
||||||
else:
|
else:
|
||||||
inbandQuery += char
|
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 ")
|
conditionIndex = query.index(" FROM ")
|
||||||
inbandQuery += query[conditionIndex:]
|
inbandQuery += query[conditionIndex:]
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,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, dbms, count, where=1):
|
def __unionPosition(comment, place, parameter, value, prefix, suffix, count, where=1):
|
||||||
validPayload = None
|
validPayload = None
|
||||||
vector = None
|
vector = None
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ def __unionPosition(comment, place, parameter, value, prefix, suffix, dbms, coun
|
||||||
# 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, dbms=dbms)
|
randQueryUnescaped = unescaper.unescape(randQueryProcessed)
|
||||||
|
|
||||||
# Forge the inband SQL injection request
|
# Forge the inband SQL injection request
|
||||||
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, conf.uChar)
|
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
|
# Prepare expression with delimiters
|
||||||
randQuery2 = randomStr()
|
randQuery2 = randomStr()
|
||||||
randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
|
randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
|
||||||
randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2, dbms=dbms)
|
randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2)
|
||||||
|
|
||||||
# Confirm that it is a full inband SQL injection
|
# Confirm that it is a full inband SQL injection
|
||||||
query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, conf.uChar, multipleUnions=randQueryUnescaped2)
|
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
|
return validPayload, vector
|
||||||
|
|
||||||
def __unionConfirm(comment, place, parameter, value, prefix, suffix, dbms, count):
|
def __unionConfirm(comment, place, parameter, value, prefix, suffix, count):
|
||||||
validPayload = None
|
validPayload = None
|
||||||
vector = None
|
vector = 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
|
||||||
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
|
# Assure that the above function found the exploitable full inband
|
||||||
# SQL injection position
|
# SQL injection position
|
||||||
if not validPayload:
|
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
|
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
|
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
|
||||||
|
@ -111,7 +111,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
|
||||||
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))
|
debugMsg = "testing %s columns (%d%%)" % (status, round(100.0*count/conf.uColsStop))
|
||||||
logger.debug(debugMsg)
|
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:
|
if validPayload:
|
||||||
break
|
break
|
||||||
|
@ -120,7 +120,7 @@ def __unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix
|
||||||
|
|
||||||
return validPayload, vector
|
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
|
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
|
||||||
|
@ -130,7 +130,7 @@ def unionTest(comment, place, parameter, value, prefix, suffix, dbms):
|
||||||
return
|
return
|
||||||
|
|
||||||
kb.technique = PAYLOAD.TECHNIQUE.UNION
|
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:
|
if validPayload:
|
||||||
validPayload = agent.removePayloadDelimiters(validPayload, False)
|
validPayload = agent.removePayloadDelimiters(validPayload, False)
|
||||||
|
|
|
@ -67,7 +67,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, unpack
|
||||||
# entry per time
|
# entry per time
|
||||||
# NOTE: I assume that only queries that get data from a table can
|
# NOTE: I assume that only queries that get data from a table can
|
||||||
# return multiple entries
|
# 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)
|
limitRegExp = re.search(queries[getIdentifiedDBMS()].limitregexp.query, expression, re.I)
|
||||||
|
|
||||||
if limitRegExp:
|
if limitRegExp:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user