mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-05-10 10:43:44 +03:00
fixes #181 - proper save/resume information about single entry UNION SQL injection
This commit is contained in:
parent
d00e4a458a
commit
d13ad8b2d7
|
@ -55,11 +55,11 @@ class Agent:
|
||||||
retValue = ""
|
retValue = ""
|
||||||
newValue = urlencode(newValue)
|
newValue = urlencode(newValue)
|
||||||
|
|
||||||
if negative or conf.paramNegative:
|
if negative or kb.unionNegative:
|
||||||
negValue = "-"
|
negValue = "-"
|
||||||
elif falseCond or conf.paramFalseCond:
|
elif falseCond or kb.unionFalseCond:
|
||||||
randInt = randomInt()
|
randInt = randomInt()
|
||||||
falseValue = " AND %d=%d" % (randInt, randInt + 1)
|
falseValue = urlencode(" AND %d=%d" % (randInt, randInt + 1))
|
||||||
|
|
||||||
# After identifing the injectable parameter
|
# After identifing the injectable parameter
|
||||||
if kb.injPlace == "User-Agent":
|
if kb.injPlace == "User-Agent":
|
||||||
|
|
|
@ -872,8 +872,6 @@ def __setConfAttributes():
|
||||||
conf.outputPath = None
|
conf.outputPath = None
|
||||||
conf.paramDict = {}
|
conf.paramDict = {}
|
||||||
conf.parameters = {}
|
conf.parameters = {}
|
||||||
conf.paramFalseCond = False
|
|
||||||
conf.paramNegative = False
|
|
||||||
conf.path = None
|
conf.path = None
|
||||||
conf.port = None
|
conf.port = None
|
||||||
conf.progressWidth = 54
|
conf.progressWidth = 54
|
||||||
|
@ -932,6 +930,9 @@ def __setKnowledgeBaseAttributes():
|
||||||
kb.unionComment = ""
|
kb.unionComment = ""
|
||||||
kb.unionCount = None
|
kb.unionCount = None
|
||||||
kb.unionPosition = None
|
kb.unionPosition = None
|
||||||
|
kb.unionNegative = False
|
||||||
|
kb.unionFalseCond = False
|
||||||
|
|
||||||
|
|
||||||
def __saveCmdline():
|
def __saveCmdline():
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -199,7 +199,7 @@ def setStacked():
|
||||||
if condition:
|
if condition:
|
||||||
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest))
|
dataToSessionFile("[%s][%s][%s][Stacked queries][%s]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace], kb.stackedTest))
|
||||||
|
|
||||||
def setUnion(comment=None, count=None, position=None):
|
def setUnion(comment=None, count=None, position=None, negative=False, falseCond=False):
|
||||||
"""
|
"""
|
||||||
@param comment: union comment to save in session file
|
@param comment: union comment to save in session file
|
||||||
@type comment: C{str}
|
@type comment: C{str}
|
||||||
|
@ -226,7 +226,7 @@ def setUnion(comment=None, count=None, position=None):
|
||||||
kb.unionComment = comment
|
kb.unionComment = comment
|
||||||
kb.unionCount = count
|
kb.unionCount = count
|
||||||
|
|
||||||
elif position:
|
if position:
|
||||||
condition = (
|
condition = (
|
||||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
( not kb.resumedQueries[conf.url].has_key("Union position")
|
( not kb.resumedQueries[conf.url].has_key("Union position")
|
||||||
|
@ -238,6 +238,30 @@ def setUnion(comment=None, count=None, position=None):
|
||||||
|
|
||||||
kb.unionPosition = position
|
kb.unionPosition = position
|
||||||
|
|
||||||
|
if negative:
|
||||||
|
condition = (
|
||||||
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
|
( not kb.resumedQueries[conf.url].has_key("Union negative")
|
||||||
|
) )
|
||||||
|
)
|
||||||
|
|
||||||
|
if condition:
|
||||||
|
dataToSessionFile("[%s][%s][%s][Union negative][Yes]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace]))
|
||||||
|
|
||||||
|
kb.unionNegative = True
|
||||||
|
|
||||||
|
if falseCond:
|
||||||
|
condition = (
|
||||||
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
|
( not kb.resumedQueries[conf.url].has_key("Union false condition")
|
||||||
|
) )
|
||||||
|
)
|
||||||
|
|
||||||
|
if condition:
|
||||||
|
dataToSessionFile("[%s][%s][%s][Union false condition][Yes]\n" % (conf.url, kb.injPlace, conf.parameters[kb.injPlace]))
|
||||||
|
|
||||||
|
kb.unionFalseCond = True
|
||||||
|
|
||||||
def setRemoteTempPath():
|
def setRemoteTempPath():
|
||||||
condition = (
|
condition = (
|
||||||
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
not kb.resumedQueries or ( kb.resumedQueries.has_key(conf.url) and
|
||||||
|
@ -430,6 +454,20 @@ def resumeConfKb(expression, url, value):
|
||||||
logMsg += "%s from session file" % kb.unionPosition
|
logMsg += "%s from session file" % kb.unionPosition
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
|
|
||||||
|
elif expression == "Union negative" and url == conf.url:
|
||||||
|
kb.unionNegative = True if value[:-1] == "Yes" else False
|
||||||
|
|
||||||
|
logMsg = "resuming union negative "
|
||||||
|
logMsg += "%s from session file" % kb.unionPosition
|
||||||
|
logger.info(logMsg)
|
||||||
|
|
||||||
|
elif expression == "Union false condition" and url == conf.url:
|
||||||
|
kb.unionFalseCond = True if value[:-1] == "Yes" else False
|
||||||
|
|
||||||
|
logMsg = "resuming union false condition "
|
||||||
|
logMsg += "%s from session file" % kb.unionPosition
|
||||||
|
logger.info(logMsg)
|
||||||
|
|
||||||
elif expression == "Remote temp path" and url == conf.url:
|
elif expression == "Remote temp path" and url == conf.url:
|
||||||
conf.tmpPath = value[:-1]
|
conf.tmpPath = value[:-1]
|
||||||
|
|
||||||
|
|
|
@ -368,16 +368,16 @@ def getValue(expression, blind=True, inband=True, fromUser=False, expected=None,
|
||||||
warnMsg += "technique, sqlmap is going blind"
|
warnMsg += "technique, sqlmap is going blind"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
oldParamFalseCond = conf.paramFalseCond
|
oldParamFalseCond = kb.unionFalseCond
|
||||||
oldParamNegative = conf.paramNegative
|
oldParamNegative = kb.unionNegative
|
||||||
conf.paramFalseCond = False
|
kb.unionFalseCond = False
|
||||||
conf.paramNegative = False
|
kb.unionNegative = False
|
||||||
|
|
||||||
if blind and not value:
|
if blind and not value:
|
||||||
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar)
|
value = __goInferenceProxy(expression, fromUser, expected, batch, resumeValue, unpack, charsetType, firstChar, lastChar)
|
||||||
|
|
||||||
conf.paramFalseCond = oldParamFalseCond
|
kb.unionFalseCond = oldParamFalseCond
|
||||||
conf.paramNegative = oldParamNegative
|
kb.unionNegative = oldParamNegative
|
||||||
|
|
||||||
if value and isinstance(value, str):
|
if value and isinstance(value, str):
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
|
|
|
@ -33,7 +33,26 @@ 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 __forgeUserFriendlyValue(payload):
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
if kb.injPlace == "GET":
|
||||||
|
value = "%s?%s" % (conf.url, payload)
|
||||||
|
elif kb.injPlace == "POST":
|
||||||
|
value = "URL:\t'%s'" % conf.url
|
||||||
|
value += "\nPOST:\t'%s'\n" % payload
|
||||||
|
elif kb.injPlace == "Cookie":
|
||||||
|
value = "URL:\t'%s'" % conf.url
|
||||||
|
value += "\nCookie:\t'%s'\n" % payload
|
||||||
|
elif kb.injPlace == "User-Agent":
|
||||||
|
value = "URL:\t\t'%s'" % conf.url
|
||||||
|
value += "\nUser-Agent:\t'%s'\n" % payload
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
def __unionPosition(negative=False, falseCond=False):
|
def __unionPosition(negative=False, falseCond=False):
|
||||||
|
value = None
|
||||||
|
|
||||||
if negative or falseCond:
|
if negative or falseCond:
|
||||||
negLogMsg = "partial (single entry)"
|
negLogMsg = "partial (single entry)"
|
||||||
else:
|
else:
|
||||||
|
@ -73,6 +92,7 @@ def __unionPosition(negative=False, falseCond=False):
|
||||||
|
|
||||||
if randQuery in resultPage and not htmlParsed:
|
if randQuery in resultPage and not htmlParsed:
|
||||||
setUnion(position=exprPosition)
|
setUnion(position=exprPosition)
|
||||||
|
value = __forgeUserFriendlyValue(payload)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -90,22 +110,26 @@ def __unionPosition(negative=False, falseCond=False):
|
||||||
|
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
def __unionConfirm():
|
def __unionConfirm():
|
||||||
|
value = None
|
||||||
|
|
||||||
# Confirm the inband SQL injection and get the exact column
|
# Confirm the inband SQL injection and get the exact column
|
||||||
# position
|
# position
|
||||||
if not isinstance(kb.unionPosition, int):
|
if not isinstance(kb.unionPosition, int):
|
||||||
__unionPosition()
|
value = __unionPosition()
|
||||||
|
|
||||||
# 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):
|
||||||
__unionPosition(falseCond=True)
|
value = __unionPosition(falseCond=True)
|
||||||
|
|
||||||
# Assure that the above function found the exploitable partial
|
# Assure that the above function found the exploitable partial
|
||||||
# (single entry) inband SQL injection position by appending
|
# (single entry) inband SQL injection position by appending
|
||||||
# a false condition after the parameter value
|
# a false condition after the parameter value
|
||||||
if not isinstance(kb.unionPosition, int):
|
if not isinstance(kb.unionPosition, int):
|
||||||
__unionPosition(negative=True)
|
value = __unionPosition(negative=True)
|
||||||
|
|
||||||
# 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
|
||||||
|
@ -113,24 +137,9 @@ def __unionConfirm():
|
||||||
if not isinstance(kb.unionPosition, int):
|
if not isinstance(kb.unionPosition, int):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
conf.paramNegative = True
|
setUnion(negative=True)
|
||||||
else:
|
else:
|
||||||
conf.paramFalseCond = True
|
setUnion(falseCond=True)
|
||||||
|
|
||||||
def __forgeUserFriendlyValue(payload):
|
|
||||||
value = ""
|
|
||||||
|
|
||||||
if kb.injPlace == "GET":
|
|
||||||
value = "%s?%s" % (conf.url, payload)
|
|
||||||
elif kb.injPlace == "POST":
|
|
||||||
value = "URL:\t'%s'" % conf.url
|
|
||||||
value += "\nPOST:\t'%s'\n" % payload
|
|
||||||
elif kb.injPlace == "Cookie":
|
|
||||||
value = "URL:\t'%s'" % conf.url
|
|
||||||
value += "\nCookie:\t'%s'\n" % payload
|
|
||||||
elif kb.injPlace == "User-Agent":
|
|
||||||
value = "URL:\t\t'%s'" % conf.url
|
|
||||||
value += "\nUser-Agent:\t'%s'\n" % payload
|
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -142,7 +151,6 @@ def __unionTestByNULLBruteforce(comment):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
columns = None
|
columns = None
|
||||||
value = None
|
|
||||||
query = agent.prefixQuery(" UNION ALL SELECT NULL")
|
query = agent.prefixQuery(" UNION ALL SELECT NULL")
|
||||||
|
|
||||||
for count in range(0, 50):
|
for count in range(0, 50):
|
||||||
|
@ -161,15 +169,13 @@ def __unionTestByNULLBruteforce(comment):
|
||||||
|
|
||||||
if seqMatcher >= 0.6:
|
if seqMatcher >= 0.6:
|
||||||
columns = count + 1
|
columns = count + 1
|
||||||
value = __forgeUserFriendlyValue(payload)
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
return value, columns
|
return columns
|
||||||
|
|
||||||
def __unionTestByOrderBy(comment):
|
def __unionTestByOrderBy(comment):
|
||||||
columns = None
|
columns = None
|
||||||
value = None
|
|
||||||
prevPayload = ""
|
prevPayload = ""
|
||||||
|
|
||||||
for count in range(1, 51):
|
for count in range(1, 51):
|
||||||
|
@ -182,13 +188,11 @@ def __unionTestByOrderBy(comment):
|
||||||
columns = count
|
columns = count
|
||||||
|
|
||||||
elif columns:
|
elif columns:
|
||||||
value = __forgeUserFriendlyValue(prevPayload)
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
prevPayload = payload
|
prevPayload = payload
|
||||||
|
|
||||||
return value, columns
|
return columns
|
||||||
|
|
||||||
def unionTest():
|
def unionTest():
|
||||||
"""
|
"""
|
||||||
|
@ -205,25 +209,28 @@ def unionTest():
|
||||||
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
|
infoMsg += "'%s' with %s technique" % (kb.injParameter, technique)
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
value = ""
|
value = None
|
||||||
columns = None
|
columns = None
|
||||||
|
|
||||||
for comment in (queries[kb.dbms].comment, ""):
|
for comment in (queries[kb.dbms].comment, ""):
|
||||||
if conf.uTech == "orderby":
|
if conf.uTech == "orderby":
|
||||||
value, columns = __unionTestByOrderBy(comment)
|
columns = __unionTestByOrderBy(comment)
|
||||||
else:
|
else:
|
||||||
value, columns = __unionTestByNULLBruteforce(comment)
|
columns = __unionTestByNULLBruteforce(comment)
|
||||||
|
|
||||||
if columns:
|
if columns:
|
||||||
setUnion(comment, columns)
|
setUnion(comment=comment, count=columns)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if kb.unionCount:
|
if kb.unionCount:
|
||||||
__unionConfirm()
|
value = __unionConfirm()
|
||||||
else:
|
else:
|
||||||
warnMsg = "the target url is not affected by an "
|
warnMsg = "the target url is not affected by an "
|
||||||
warnMsg += "inband sql injection vulnerability"
|
warnMsg += "inband sql injection vulnerability"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
value = ""
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
|
@ -70,7 +70,7 @@ def unionUse(expression, direct=False, unescape=True, resetCounter=False, nullCh
|
||||||
expression = agent.concatQuery(expression, unpack)
|
expression = agent.concatQuery(expression, unpack)
|
||||||
expression = unescaper.unescape(expression)
|
expression = unescaper.unescape(expression)
|
||||||
|
|
||||||
if ( conf.paramNegative or conf.paramFalseCond ) and not direct:
|
if ( kb.unionNegative or kb.unionFalseCond ) and not direct:
|
||||||
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
_, _, _, _, _, expressionFieldsList, expressionFields = agent.getFields(origExpr)
|
||||||
|
|
||||||
if len(expressionFieldsList) > 1:
|
if len(expressionFieldsList) > 1:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user