diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 49016be1a..105990747 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -157,7 +157,7 @@ def checkSqlInjection(place, parameter, value): kb.testType = stype = test.stype clause = test.clause unionExtended = False - trueCode = None + trueCode, falseCode = None, None if stype == PAYLOAD.TECHNIQUE.UNION: configUnion(test.request.char) @@ -561,7 +561,7 @@ def checkSqlInjection(place, parameter, value): trueCode = threadData.lastCode 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: falseResult = Request.queryPage(reqPayload.replace(SLEEP_TIME_MARKER, "0"), place, timeBasedCompare=True, raise404=False) if falseResult: @@ -678,6 +678,7 @@ def checkSqlInjection(place, parameter, value): injection.data[stype].templatePayload = templatePayload injection.data[stype].matchRatio = kb.matchRatio injection.data[stype].trueCode = trueCode + injection.data[stype].falseCode = falseCode injection.conf.textOnly = conf.textOnly injection.conf.titles = conf.titles diff --git a/lib/core/option.py b/lib/core/option.py index 27273c3a4..8de8cc10f 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -1983,7 +1983,6 @@ def _setKnowledgeBaseAttributes(flushAll=True): kb.threadContinue = True kb.threadException = False kb.tableExistsChoice = None - kb.timeValidCharsRun = 0 kb.uChar = NULL kb.unionDuplicates = False kb.xpCmdshellAvailable = False diff --git a/lib/core/settings.py b/lib/core/settings.py index c288449b5..234a1718e 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -19,7 +19,7 @@ from lib.core.enums import OS from lib.core.revision import getRevisionNumber # sqlmap version (...) -VERSION = "1.0.9.37" +VERSION = "1.0.9.38" REVISION = getRevisionNumber() TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" 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 ORDER_BY_STEP = 10 -# Maximum number of times for revalidation of a character in time-based injections -MAX_TIME_REVALIDATION_STEPS = 5 +# Maximum number of times for revalidation of a character in inference (as required) +MAX_REVALIDATION_STEPS = 5 # Characters that can be used to split parameter values in provided command line (e.g. in --tamper) PARAMETER_SPLITTING_REGEX = r'[,|;]' @@ -547,7 +547,7 @@ HASHDB_FLUSH_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) -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 LARGE_OUTPUT_THRESHOLD = 1024 ** 2 diff --git a/lib/techniques/blind/inference.py b/lib/techniques/blind/inference.py index 979659bf7..9dff16303 100644 --- a/lib/techniques/blind/inference.py +++ b/lib/techniques/blind/inference.py @@ -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_NOT_EQUALS_CHAR 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 PARTIAL_HEX_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): """ - Used in time-based inference (in case that original and retrieved - value are not equal there will be a deliberate delay). + Used in inference - in time-based SQLi if original and retrieved value are not equal there will be a deliberate delay """ 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] firstCheck = False lastCheck = False + unexpectedCode = False while len(charTbl) != 1: position = None @@ -321,6 +321,12 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False) 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: minValue = posValue @@ -360,24 +366,25 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None retVal = minValue + 1 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: kb.originalTimeDelay = conf.timeSec - kb.timeValidCharsRun = 0 - if retried < MAX_TIME_REVALIDATION_STEPS: + threadData.validationRun = 0 + if retried < MAX_REVALIDATION_STEPS: errMsg = "invalid character detected. retrying.." logger.error(errMsg) - if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE: - conf.timeSec += 1 - warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '') - logger.warn(warnMsg) + if timeBasedCompare: + if kb.adjustTimeDelay is not ADJUST_TIME_DELAY.DISABLE: + conf.timeSec += 1 + warnMsg = "increasing time delay to %d second%s " % (conf.timeSec, 's' if conf.timeSec > 1 else '') + logger.warn(warnMsg) - if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES: - dbgMsg = "turning off time auto-adjustment mechanism" - logger.debug(dbgMsg) - kb.adjustTimeDelay = ADJUST_TIME_DELAY.NO + if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES: + dbgMsg = "turning off time auto-adjustment mechanism" + logger.debug(dbgMsg) + kb.adjustTimeDelay = ADJUST_TIME_DELAY.NO return getChar(idx, originalTbl, continuousOrder, expand, shiftTable, (retried or 0) + 1) else: @@ -387,8 +394,8 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None return decodeIntToUnicode(retVal) else: if timeBasedCompare: - kb.timeValidCharsRun += 1 - if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and kb.timeValidCharsRun > VALID_TIME_CHARS_RUN_THRESHOLD: + threadData.validationRun += 1 + if kb.adjustTimeDelay is ADJUST_TIME_DELAY.NO and threadData.validationRun > VALID_TIME_CHARS_RUN_THRESHOLD: dbgMsg = "turning back on time auto-adjustment mechanism" logger.debug(dbgMsg) kb.adjustTimeDelay = ADJUST_TIME_DELAY.YES diff --git a/txt/checksum.md5 b/txt/checksum.md5 index 0dc2d0202..577529fc9 100644 --- a/txt/checksum.md5 +++ b/txt/checksum.md5 @@ -20,7 +20,7 @@ b46521e29ea3d813bab5aeb16cac6498 extra/shutils/duplicates.py cc9c82cfffd8ee9b25ba3af6284f057e extra/sqlharvest/__init__.py 4f2f817596540d82f9fcc0c5b2228beb extra/sqlharvest/sqlharvest.py 2daa39e4d59526acb4772b6c47eb315f lib/controller/action.py -e2be5a4d5fd7587a78fa15a52fa58f32 lib/controller/checks.py +1caf7c1bad475d3e1276edffc6da8a8c lib/controller/checks.py 7c5ba631796f12d6de9b667e4cc7812b lib/controller/controller.py 0a64305c3b3a01a2fc3a5e6204f442f1 lib/controller/handler.py cc9c82cfffd8ee9b25ba3af6284f057e lib/controller/__init__.py @@ -39,13 +39,13 @@ e4aec2b11c1ad6039d0c3dbbfbc5eb1a lib/core/exception.py cc9c82cfffd8ee9b25ba3af6284f057e lib/core/__init__.py 91c514013daa796e2cdd940389354eac lib/core/log.py b9779615206791e6ebbaa84947842b49 lib/core/optiondict.py -fc390372373b5471b75145f6af4f11bd lib/core/option.py +74d826338a2cd66a4724d8486a648d93 lib/core/option.py 1e8948dddbd12def5c2af52530738059 lib/core/profiling.py e60456db5380840a586654344003d4e6 lib/core/readlineng.py 5ef56abb8671c2ca6ceecb208258e360 lib/core/replication.py 99a2b496b9d5b546b335653ca801153f lib/core/revision.py 7c15dd2777af4dac2c89cab6df17462e lib/core/session.py -5ea71214107e2dc870a14ca2f90e9b49 lib/core/settings.py +db111838c5ffb6dfc66a260733952460 lib/core/settings.py 7af83e4f18cab6dff5e67840eb65be80 lib/core/shell.py 23657cd7d924e3c6d225719865855827 lib/core/subprocessng.py 0bc2fae1dec18cdd11954b22358293f2 lib/core/target.py @@ -87,7 +87,7 @@ cc9c82cfffd8ee9b25ba3af6284f057e lib/takeover/__init__.py 7d6cd7bdfc8f4bc4e8aed60c84cdf87f lib/takeover/udf.py f6e3084abd506925a8be3d1c0a6d058c lib/takeover/web.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/brute/__init__.py d36effffe64e63ef9b3be490f850e2cc lib/techniques/brute/use.py