mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-05-07 17:23:46 +03:00
Added a precaution when, in some rare circumstances, fingerprinted DBMS differ during detection phase.
Adapted UNION tests' titles when --union-char is provided. Lots of comment adjustments. Code cleanup
This commit is contained in:
parent
cffa17f5a6
commit
eda0b41859
|
@ -100,13 +100,18 @@ def checkSqlInjection(place, parameter, value):
|
||||||
stype = test.stype
|
stype = test.stype
|
||||||
clause = test.clause
|
clause = test.clause
|
||||||
|
|
||||||
if stype == 3 and test.request.columns == "[COLSTART]-[COLSTOP]":
|
if stype == 3:
|
||||||
if conf.uCols is None:
|
configUnion(test.request.char)
|
||||||
continue
|
|
||||||
else:
|
if test.request.columns == "[COLSTART]-[COLSTOP]":
|
||||||
configUnion()
|
if conf.uCols is None:
|
||||||
title = title.replace("[COLSTART]", str(conf.uColsStart))
|
continue
|
||||||
title = title.replace("[COLSTOP]", str(conf.uColsStop))
|
else:
|
||||||
|
title = title.replace("[COLSTART]", str(conf.uColsStart))
|
||||||
|
title = title.replace("[COLSTOP]", str(conf.uColsStop))
|
||||||
|
|
||||||
|
if "[CHAR]" in title:
|
||||||
|
title = title.replace("[CHAR]", conf.uChar)
|
||||||
|
|
||||||
# Skip test if the user's wants to test only for a specific
|
# Skip test if the user's wants to test only for a specific
|
||||||
# technique
|
# technique
|
||||||
|
@ -136,7 +141,8 @@ def checkSqlInjection(place, parameter, value):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip DBMS-specific test if it does not match either the
|
# Skip DBMS-specific test if it does not match either the
|
||||||
# previously identified or the user's provided DBMS
|
# previously identified or the user's provided DBMS (either
|
||||||
|
# from program switch or from parsed error message(s))
|
||||||
if "details" in test and "dbms" in test.details:
|
if "details" in test and "dbms" in test.details:
|
||||||
dbms = test.details.dbms
|
dbms = test.details.dbms
|
||||||
else:
|
else:
|
||||||
|
@ -387,10 +393,12 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# used afterwards by Agent.forgeInbandQuery()
|
# used afterwards by Agent.forgeInbandQuery()
|
||||||
# method to forge the UNION query payload
|
# method to forge the UNION query payload
|
||||||
|
|
||||||
# Set fingerprinted DBMS according to the
|
# Force back-end DBMS according to the current
|
||||||
# current test settings for proper unescaping
|
# test value for proper payload unescaping
|
||||||
kb.misc.forcedDbms = dbms
|
kb.misc.forcedDbms = dbms
|
||||||
|
|
||||||
|
# Skip test if the user provided custom column
|
||||||
|
# range and this is not a custom UNION test
|
||||||
if conf.uCols is not None and test.request.columns != "[COLSTART]-[COLSTOP]":
|
if conf.uCols is not None and test.request.columns != "[COLSTART]-[COLSTOP]":
|
||||||
debugMsg = "skipping test '%s' because custom " % title
|
debugMsg = "skipping test '%s' because custom " % title
|
||||||
debugMsg += "UNION columns range was provided"
|
debugMsg += "UNION columns range was provided"
|
||||||
|
@ -405,6 +413,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
warnMsg += "back-end DBMS"
|
warnMsg += "back-end DBMS"
|
||||||
logger.warn(warnMsg)
|
logger.warn(warnMsg)
|
||||||
|
|
||||||
|
# Test for UNION query SQL injection
|
||||||
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
|
reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix)
|
||||||
|
|
||||||
if isinstance(reqPayload, basestring):
|
if isinstance(reqPayload, basestring):
|
||||||
|
@ -417,6 +426,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
# by unionTest() directly
|
# by unionTest() directly
|
||||||
where = vector[6]
|
where = vector[6]
|
||||||
|
|
||||||
|
# Reset back-end DBMS value
|
||||||
kb.misc.forcedDbms = None
|
kb.misc.forcedDbms = None
|
||||||
|
|
||||||
# If the injection test was successful feed the injection
|
# If the injection test was successful feed the injection
|
||||||
|
@ -454,15 +464,38 @@ def checkSqlInjection(place, parameter, value):
|
||||||
injection.conf.regexp = conf.regexp
|
injection.conf.regexp = conf.regexp
|
||||||
|
|
||||||
if hasattr(test, "details"):
|
if hasattr(test, "details"):
|
||||||
for detailKey, detailValue in test.details.items():
|
for dKey, dValue in test.details.items():
|
||||||
if detailKey == "dbms" and injection.dbms is None:
|
# Little precaution, in theory this condition
|
||||||
injection.dbms = detailValue
|
# should always be false
|
||||||
kb.dbms = aliasToDbmsEnum(detailValue)
|
if dKey == "dbms" and injection.dbms is not None and dValue != injection.dbms:
|
||||||
elif detailKey == "dbms_version" and injection.dbms_version is None:
|
msg = "previous test(s) identified that the "
|
||||||
injection.dbms_version = detailValue
|
msg += "back-end DBMS possibly is %s. " % injection.dbms
|
||||||
kb.dbmsVersion = [ detailValue ]
|
msg += "However the last successful test "
|
||||||
elif detailKey == "os" and injection.os is None:
|
msg += "fingerprinted %s. " % dValue
|
||||||
injection.os = detailValue
|
msg += "Please, specify which DBMS is "
|
||||||
|
msg += "correct [%s (default)/%s] " % (injection.dbms, dValue)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
inp = readInput(msg, default=injection.dbms)
|
||||||
|
|
||||||
|
if inp == injection.dbms:
|
||||||
|
break
|
||||||
|
elif inp == dValue:
|
||||||
|
kb.dbms = aliasToDbmsEnum(inp)
|
||||||
|
injection.dbms = aliasToDbmsEnum(inp)
|
||||||
|
injection.dbms_version = None
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
warnMsg = "invalid value"
|
||||||
|
logger.warn(warnMsg)
|
||||||
|
elif dKey == "dbms" and injection.dbms is None:
|
||||||
|
kb.dbms = aliasToDbmsEnum(dValue)
|
||||||
|
injection.dbms = aliasToDbmsEnum(dValue)
|
||||||
|
elif dKey == "dbms_version" and injection.dbms_version is None:
|
||||||
|
kb.dbmsVersion = [ dValue ]
|
||||||
|
injection.dbms_version = dValue
|
||||||
|
elif dKey == "os" and injection.os is None:
|
||||||
|
injection.os = dValue
|
||||||
|
|
||||||
if conf.beep or conf.realTest:
|
if conf.beep or conf.realTest:
|
||||||
beep()
|
beep()
|
||||||
|
@ -500,7 +533,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
|
|
||||||
def heuristicCheckSqlInjection(place, parameter):
|
def heuristicCheckSqlInjection(place, parameter):
|
||||||
if kb.nullConnection:
|
if kb.nullConnection:
|
||||||
debugMsg = "heuristic checking skipped "
|
debugMsg = "heuristic checking skipped "
|
||||||
debugMsg += "because NULL connection used"
|
debugMsg += "because NULL connection used"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
return
|
return
|
||||||
|
@ -521,7 +554,7 @@ def heuristicCheckSqlInjection(place, parameter):
|
||||||
|
|
||||||
result = wasLastRequestDBMSError()
|
result = wasLastRequestDBMSError()
|
||||||
|
|
||||||
infoMsg = "heuristic test shows that %s " % place
|
infoMsg = "heuristic test shows that %s " % place
|
||||||
infoMsg += "parameter '%s' might " % parameter
|
infoMsg += "parameter '%s' might " % parameter
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
@ -559,7 +592,7 @@ def simpletonCheckSqlInjection(place, parameter, value):
|
||||||
secondPage, _ = Request.queryPage(payload, place, content=True, raise404=False)
|
secondPage, _ = Request.queryPage(payload, place, content=True, raise404=False)
|
||||||
result = getComparePageRatio(firstPage, secondPage, filtered=True) <= CONSTANT_RATIO
|
result = getComparePageRatio(firstPage, secondPage, filtered=True) <= CONSTANT_RATIO
|
||||||
|
|
||||||
infoMsg = "simpleton test shows that %s " % place
|
infoMsg = "simpleton test shows that %s " % place
|
||||||
infoMsg += "parameter '%s' might " % parameter
|
infoMsg += "parameter '%s' might " % parameter
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
|
@ -605,7 +638,7 @@ def checkDynamicContent(firstPage, secondPage):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if kb.nullConnection:
|
if kb.nullConnection:
|
||||||
debugMsg = "dynamic content checking skipped "
|
debugMsg = "dynamic content checking skipped "
|
||||||
debugMsg += "because NULL connection used"
|
debugMsg += "because NULL connection used"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
return
|
return
|
||||||
|
@ -661,17 +694,17 @@ def checkStability():
|
||||||
|
|
||||||
if kb.pageStable:
|
if kb.pageStable:
|
||||||
if firstPage:
|
if firstPage:
|
||||||
logMsg = "url is stable"
|
logMsg = "url is stable"
|
||||||
logger.info(logMsg)
|
logger.info(logMsg)
|
||||||
else:
|
else:
|
||||||
errMsg = "there was an error checking the stability of page "
|
errMsg = "there was an error checking the stability of page "
|
||||||
errMsg += "because of lack of content. please check the "
|
errMsg += "because of lack of content. please check the "
|
||||||
errMsg += "page request results (and probable errors) by "
|
errMsg += "page request results (and probable errors) by "
|
||||||
errMsg += "using higher verbosity levels"
|
errMsg += "using higher verbosity levels"
|
||||||
raise sqlmapNoneDataException, errMsg
|
raise sqlmapNoneDataException, errMsg
|
||||||
|
|
||||||
else:
|
else:
|
||||||
warnMsg = "url is not stable, sqlmap will base the page "
|
warnMsg = "url is not stable, sqlmap will base the page "
|
||||||
warnMsg += "comparison on a sequence matcher. If no dynamic nor "
|
warnMsg += "comparison on a sequence matcher. If no dynamic nor "
|
||||||
warnMsg += "injectable parameters are detected, or in case of "
|
warnMsg += "injectable parameters are detected, or in case of "
|
||||||
warnMsg += "junk results, refer to user's manual paragraph "
|
warnMsg += "junk results, refer to user's manual paragraph "
|
||||||
|
@ -698,7 +731,7 @@ def checkStability():
|
||||||
conf.string = test
|
conf.string = test
|
||||||
|
|
||||||
if kb.nullConnection:
|
if kb.nullConnection:
|
||||||
debugMsg = "turning off NULL connection "
|
debugMsg = "turning off NULL connection "
|
||||||
debugMsg += "support because of string checking"
|
debugMsg += "support because of string checking"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
@ -715,7 +748,7 @@ def checkStability():
|
||||||
conf.regex = test
|
conf.regex = test
|
||||||
|
|
||||||
if kb.nullConnection:
|
if kb.nullConnection:
|
||||||
debugMsg = "turning off NULL connection "
|
debugMsg = "turning off NULL connection "
|
||||||
debugMsg += "support because of regex checking"
|
debugMsg += "support because of regex checking"
|
||||||
logger.debug(debugMsg)
|
logger.debug(debugMsg)
|
||||||
|
|
||||||
|
@ -733,14 +766,14 @@ def checkString():
|
||||||
if not conf.string:
|
if not conf.string:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing if the provided string is within the "
|
infoMsg = "testing if the provided string is within the "
|
||||||
infoMsg += "target URL page content"
|
infoMsg += "target URL page content"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
page, _ = Request.queryPage(content=True)
|
page, _ = Request.queryPage(content=True)
|
||||||
|
|
||||||
if conf.string not in page:
|
if conf.string not in page:
|
||||||
warnMsg = "you provided '%s' as the string to " % conf.string
|
warnMsg = "you provided '%s' as the string to " % conf.string
|
||||||
warnMsg += "match, but such a string is not within the target "
|
warnMsg += "match, but such a string is not within the target "
|
||||||
warnMsg += "URL page content original request, sqlmap will "
|
warnMsg += "URL page content original request, sqlmap will "
|
||||||
warnMsg += "keep going anyway"
|
warnMsg += "keep going anyway"
|
||||||
|
@ -752,14 +785,14 @@ def checkRegexp():
|
||||||
if not conf.regexp:
|
if not conf.regexp:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
infoMsg = "testing if the provided regular expression matches within "
|
infoMsg = "testing if the provided regular expression matches within "
|
||||||
infoMsg += "the target URL page content"
|
infoMsg += "the target URL page content"
|
||||||
logger.info(infoMsg)
|
logger.info(infoMsg)
|
||||||
|
|
||||||
page, _ = Request.queryPage(content=True)
|
page, _ = Request.queryPage(content=True)
|
||||||
|
|
||||||
if not re.search(conf.regexp, page, re.I | re.M):
|
if not re.search(conf.regexp, page, re.I | re.M):
|
||||||
warnMsg = "you provided '%s' as the regular expression to " % conf.regexp
|
warnMsg = "you provided '%s' as the regular expression to " % conf.regexp
|
||||||
warnMsg += "match, but such a regular expression does not have any "
|
warnMsg += "match, but such a regular expression does not have any "
|
||||||
warnMsg += "match within the target URL page content, sqlmap "
|
warnMsg += "match within the target URL page content, sqlmap "
|
||||||
warnMsg += "will keep going anyway"
|
warnMsg += "will keep going anyway"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user