mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2025-02-09 08:00:36 +03:00
Adding extra validation step in case of boolean-based blind (e.g. if unexpected 500 occurs)
This commit is contained in:
parent
8994bf2dba
commit
7151df16f6
|
@ -157,7 +157,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
kb.testType = stype = test.stype
|
kb.testType = stype = test.stype
|
||||||
clause = test.clause
|
clause = test.clause
|
||||||
unionExtended = False
|
unionExtended = False
|
||||||
trueCode = None
|
trueCode, falseCode = None, None
|
||||||
|
|
||||||
if stype == PAYLOAD.TECHNIQUE.UNION:
|
if stype == PAYLOAD.TECHNIQUE.UNION:
|
||||||
configUnion(test.request.char)
|
configUnion(test.request.char)
|
||||||
|
@ -561,7 +561,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
trueCode = threadData.lastCode
|
trueCode = threadData.lastCode
|
||||||
|
|
||||||
if trueResult:
|
if trueResult:
|
||||||
# Just extra validation step (e.g. to check for dropping protection mechanisms)
|
# Extra validation step (e.g. to check for DROP protection mechanisms)
|
||||||
if SLEEP_TIME_MARKER in reqPayload:
|
if SLEEP_TIME_MARKER in reqPayload:
|
||||||
falseResult = Request.queryPage(reqPayload.replace(SLEEP_TIME_MARKER, "0"), place, timeBasedCompare=True, raise404=False)
|
falseResult = Request.queryPage(reqPayload.replace(SLEEP_TIME_MARKER, "0"), place, timeBasedCompare=True, raise404=False)
|
||||||
if falseResult:
|
if falseResult:
|
||||||
|
@ -678,6 +678,7 @@ def checkSqlInjection(place, parameter, value):
|
||||||
injection.data[stype].templatePayload = templatePayload
|
injection.data[stype].templatePayload = templatePayload
|
||||||
injection.data[stype].matchRatio = kb.matchRatio
|
injection.data[stype].matchRatio = kb.matchRatio
|
||||||
injection.data[stype].trueCode = trueCode
|
injection.data[stype].trueCode = trueCode
|
||||||
|
injection.data[stype].falseCode = falseCode
|
||||||
|
|
||||||
injection.conf.textOnly = conf.textOnly
|
injection.conf.textOnly = conf.textOnly
|
||||||
injection.conf.titles = conf.titles
|
injection.conf.titles = conf.titles
|
||||||
|
|
|
@ -1983,7 +1983,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
||||||
kb.threadContinue = True
|
kb.threadContinue = True
|
||||||
kb.threadException = False
|
kb.threadException = False
|
||||||
kb.tableExistsChoice = None
|
kb.tableExistsChoice = None
|
||||||
kb.timeValidCharsRun = 0
|
|
||||||
kb.uChar = NULL
|
kb.uChar = NULL
|
||||||
kb.unionDuplicates = False
|
kb.unionDuplicates = False
|
||||||
kb.xpCmdshellAvailable = False
|
kb.xpCmdshellAvailable = False
|
||||||
|
|
|
@ -19,7 +19,7 @@ from lib.core.enums import OS
|
||||||
from lib.core.revision import getRevisionNumber
|
from lib.core.revision import getRevisionNumber
|
||||||
|
|
||||||
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
|
||||||
VERSION = "1.0.9.37"
|
VERSION = "1.0.9.38"
|
||||||
REVISION = getRevisionNumber()
|
REVISION = getRevisionNumber()
|
||||||
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
|
||||||
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
|
||||||
|
@ -510,8 +510,8 @@ PARSE_HEADERS_LIMIT = 3
|
||||||
# Step used in ORDER BY technique used for finding the right number of columns in UNION query injections
|
# Step used in ORDER BY technique used for finding the right number of columns in UNION query injections
|
||||||
ORDER_BY_STEP = 10
|
ORDER_BY_STEP = 10
|
||||||
|
|
||||||
# Maximum number of times for revalidation of a character in time-based injections
|
# Maximum number of times for revalidation of a character in inference (as required)
|
||||||
MAX_TIME_REVALIDATION_STEPS = 5
|
MAX_REVALIDATION_STEPS = 5
|
||||||
|
|
||||||
# Characters that can be used to split parameter values in provided command line (e.g. in --tamper)
|
# Characters that can be used to split parameter values in provided command line (e.g. in --tamper)
|
||||||
PARAMETER_SPLITTING_REGEX = r'[,|;]'
|
PARAMETER_SPLITTING_REGEX = r'[,|;]'
|
||||||
|
@ -547,7 +547,7 @@ HASHDB_FLUSH_RETRIES = 3
|
||||||
HASHDB_END_TRANSACTION_RETRIES = 3
|
HASHDB_END_TRANSACTION_RETRIES = 3
|
||||||
|
|
||||||
# Unique milestone value used for forced deprecation of old HashDB values (e.g. when changing hash/pickle mechanism)
|
# Unique milestone value used for forced deprecation of old HashDB values (e.g. when changing hash/pickle mechanism)
|
||||||
HASHDB_MILESTONE_VALUE = "QWdDkLzhxH" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
HASHDB_MILESTONE_VALUE = "BkfRWrtCYK" # python -c 'import random, string; print "".join(random.sample(string.ascii_letters, 10))'
|
||||||
|
|
||||||
# Warn user of possible delay due to large page dump in full UNION query injections
|
# Warn user of possible delay due to large page dump in full UNION query injections
|
||||||
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
LARGE_OUTPUT_THRESHOLD = 1024 ** 2
|
||||||
|
|
|
@ -41,7 +41,7 @@ from lib.core.settings import INFERENCE_GREATER_CHAR
|
||||||
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
from lib.core.settings import INFERENCE_EQUALS_CHAR
|
||||||
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
|
from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
|
||||||
from lib.core.settings import MAX_BISECTION_LENGTH
|
from lib.core.settings import MAX_BISECTION_LENGTH
|
||||||
from lib.core.settings import MAX_TIME_REVALIDATION_STEPS
|
from lib.core.settings import MAX_REVALIDATION_STEPS
|
||||||
from lib.core.settings import NULL
|
from lib.core.settings import NULL
|
||||||
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
from lib.core.settings import PARTIAL_HEX_VALUE_MARKER
|
||||||
from lib.core.settings import PARTIAL_VALUE_MARKER
|
from lib.core.settings import PARTIAL_VALUE_MARKER
|
||||||
|
@ -198,8 +198,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
|
|
||||||
def validateChar(idx, value):
|
def validateChar(idx, value):
|
||||||
"""
|
"""
|
||||||
Used in time-based inference (in case that original and retrieved
|
Used in inference - in time-based SQLi if original and retrieved value are not equal there will be a deliberate delay
|
||||||
value are not equal there will be a deliberate delay).
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
|
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
|
||||||
|
@ -264,6 +263,7 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
minChar = minValue = charTbl[0]
|
minChar = minValue = charTbl[0]
|
||||||
firstCheck = False
|
firstCheck = False
|
||||||
lastCheck = False
|
lastCheck = False
|
||||||
|
unexpectedCode = False
|
||||||
|
|
||||||
while len(charTbl) != 1:
|
while len(charTbl) != 1:
|
||||||
position = None
|
position = None
|
||||||
|
@ -321,6 +321,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||||
incrementCounter(kb.technique)
|
incrementCounter(kb.technique)
|
||||||
|
|
||||||
|
if not timeBasedCompare:
|
||||||
|
unexpectedCode |= threadData.lastCode not in (kb.injection.data[kb.technique].falseCode, kb.injection.data[kb.technique].trueCode)
|
||||||
|
if unexpectedCode:
|
||||||
|
warnMsg = "unexpected HTTP code '%d' detected. Will use (extra) validation step in similar cases" % threadData.lastCode
|
||||||
|
singleTimeWarnMessage(warnMsg)
|
||||||
|
|
||||||
if result:
|
if result:
|
||||||
minValue = posValue
|
minValue = posValue
|
||||||
|
|
||||||
|
@ -360,15 +366,16 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
retVal = minValue + 1
|
retVal = minValue + 1
|
||||||
|
|
||||||
if retVal in originalTbl or (retVal == ord('\n') and CHAR_INFERENCE_MARK in payload):
|
if retVal in originalTbl or (retVal == ord('\n') and CHAR_INFERENCE_MARK in payload):
|
||||||
if timeBasedCompare and not validateChar(idx, retVal):
|
if (timeBasedCompare or unexpectedCode) and not validateChar(idx, retVal):
|
||||||
if not kb.originalTimeDelay:
|
if not kb.originalTimeDelay:
|
||||||
kb.originalTimeDelay = conf.timeSec
|
kb.originalTimeDelay = conf.timeSec
|
||||||
|
|
||||||
kb.timeValidCharsRun = 0
|
threadData.validationRun = 0
|
||||||
if retried < MAX_TIME_REVALIDATION_STEPS:
|
if retried < MAX_REVALIDATION_STEPS:
|
||||||
errMsg = "invalid character detected. retrying.."
|
errMsg = "invalid character detected. retrying.."
|
||||||
logger.error(errMsg)
|
logger.error(errMsg)
|
||||||
|
|
||||||
|
if timeBasedCompare:
|
||||||
if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE:
|
if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE:
|
||||||
conf.timeSec += 1
|
conf.timeSec += 1
|
||||||
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '')
|
||||||
|
@ -387,8 +394,8 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
||||||
return decodeIntToUnicode(retVal)
|
return decodeIntToUnicode(retVal)
|
||||||
else:
|
else:
|
||||||
if timeBasedCompare:
|
if timeBasedCompare:
|
||||||
kb.timeValidCharsRun += 1
|
threadData.validationRun += 1
|
||||||
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and kb.timeValidCharsRun > VALID_TIME_CHARS_RUN_THRESHOLD:
|
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and threadData.validationRun > VALID_TIME_CHARS_RUN_THRESHOLD:
|
||||||
dbgMsg = "turning back on time auto-adjustment mechanism"
|
dbgMsg = "turning back on time auto-adjustment mechanism"
|
||||||
logger.debug(dbgMsg)
|
logger.debug(dbgMsg)
|
||||||
kb.adjustTimeDelay = ADJUST_TIME_DELAY.YES
|
kb.adjustTimeDelay = ADJUST_TIME_DELAY.YES
|
||||||
|
|
|
@ -20,7 +20,7 @@ b46521e29ea3d813bab5aeb16cac6498 extra/shutils/duplicates.py
|
||||||
cc9c82cfffd8ee9b25ba3af6284f057e extra/sqlharvest/__init__.py
|
cc9c82cfffd8ee9b25ba3af6284f057e extra/sqlharvest/__init__.py
|
||||||
4f2f817596540d82f9fcc0c5b2228beb extra/sqlharvest/sqlharvest.py
|
4f2f817596540d82f9fcc0c5b2228beb extra/sqlharvest/sqlharvest.py
|
||||||
2daa39e4d59526acb4772b6c47eb315f lib/controller/action.py
|
2daa39e4d59526acb4772b6c47eb315f lib/controller/action.py
|
||||||
e2be5a4d5fd7587a78fa15a52fa58f32 lib/controller/checks.py
|
1caf7c1bad475d3e1276edffc6da8a8c lib/controller/checks.py
|
||||||
7c5ba631796f12d6de9b667e4cc7812b lib/controller/controller.py
|
7c5ba631796f12d6de9b667e4cc7812b lib/controller/controller.py
|
||||||
0a64305c3b3a01a2fc3a5e6204f442f1 lib/controller/handler.py
|
0a64305c3b3a01a2fc3a5e6204f442f1 lib/controller/handler.py
|
||||||
cc9c82cfffd8ee9b25ba3af6284f057e lib/controller/__init__.py
|
cc9c82cfffd8ee9b25ba3af6284f057e lib/controller/__init__.py
|
||||||
|
@ -39,13 +39,13 @@ e4aec2b11c1ad6039d0c3dbbfbc5eb1a lib/core/exception.py
|
||||||
cc9c82cfffd8ee9b25ba3af6284f057e lib/core/__init__.py
|
cc9c82cfffd8ee9b25ba3af6284f057e lib/core/__init__.py
|
||||||
91c514013daa796e2cdd940389354eac lib/core/log.py
|
91c514013daa796e2cdd940389354eac lib/core/log.py
|
||||||
b9779615206791e6ebbaa84947842b49 lib/core/optiondict.py
|
b9779615206791e6ebbaa84947842b49 lib/core/optiondict.py
|
||||||
fc390372373b5471b75145f6af4f11bd lib/core/option.py
|
74d826338a2cd66a4724d8486a648d93 lib/core/option.py
|
||||||
1e8948dddbd12def5c2af52530738059 lib/core/profiling.py
|
1e8948dddbd12def5c2af52530738059 lib/core/profiling.py
|
||||||
e60456db5380840a586654344003d4e6 lib/core/readlineng.py
|
e60456db5380840a586654344003d4e6 lib/core/readlineng.py
|
||||||
5ef56abb8671c2ca6ceecb208258e360 lib/core/replication.py
|
5ef56abb8671c2ca6ceecb208258e360 lib/core/replication.py
|
||||||
99a2b496b9d5b546b335653ca801153f lib/core/revision.py
|
99a2b496b9d5b546b335653ca801153f lib/core/revision.py
|
||||||
7c15dd2777af4dac2c89cab6df17462e lib/core/session.py
|
7c15dd2777af4dac2c89cab6df17462e lib/core/session.py
|
||||||
5ea71214107e2dc870a14ca2f90e9b49 lib/core/settings.py
|
db111838c5ffb6dfc66a260733952460 lib/core/settings.py
|
||||||
7af83e4f18cab6dff5e67840eb65be80 lib/core/shell.py
|
7af83e4f18cab6dff5e67840eb65be80 lib/core/shell.py
|
||||||
23657cd7d924e3c6d225719865855827 lib/core/subprocessng.py
|
23657cd7d924e3c6d225719865855827 lib/core/subprocessng.py
|
||||||
0bc2fae1dec18cdd11954b22358293f2 lib/core/target.py
|
0bc2fae1dec18cdd11954b22358293f2 lib/core/target.py
|
||||||
|
@ -87,7 +87,7 @@ cc9c82cfffd8ee9b25ba3af6284f057e lib/takeover/__init__.py
|
||||||
7d6cd7bdfc8f4bc4e8aed60c84cdf87f lib/takeover/udf.py
|
7d6cd7bdfc8f4bc4e8aed60c84cdf87f lib/takeover/udf.py
|
||||||
f6e3084abd506925a8be3d1c0a6d058c lib/takeover/web.py
|
f6e3084abd506925a8be3d1c0a6d058c lib/takeover/web.py
|
||||||
9af83a62de360184f1c14e69b8a95cfe lib/takeover/xp_cmdshell.py
|
9af83a62de360184f1c14e69b8a95cfe lib/takeover/xp_cmdshell.py
|
||||||
004c45c172d549e098a5fd5285a54cb3 lib/techniques/blind/inference.py
|
9e4ae2df75cab68ea297f0db50b574c7 lib/techniques/blind/inference.py
|
||||||
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/blind/__init__.py
|
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/blind/__init__.py
|
||||||
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/brute/__init__.py
|
cc9c82cfffd8ee9b25ba3af6284f057e lib/techniques/brute/__init__.py
|
||||||
d36effffe64e63ef9b3be490f850e2cc lib/techniques/brute/use.py
|
d36effffe64e63ef9b3be490f850e2cc lib/techniques/brute/use.py
|
||||||
|
|
Loading…
Reference in New Issue
Block a user