mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-25 02:53:46 +03:00
Another (better) patch for #1636
This commit is contained in:
parent
0f8a551227
commit
5908964db4
|
@ -2222,16 +2222,16 @@ def wasLastResponseDelayed():
|
|||
# response times should be inside +-7*stdev([normal response times])
|
||||
# Math reference: http://www.answers.com/topic/standard-deviation
|
||||
|
||||
deviation = stdev(kb.responseTimes)
|
||||
deviation = stdev(kb.responseTimes.get(kb.responseTimeMode, []))
|
||||
threadData = getCurrentThreadData()
|
||||
|
||||
if deviation and not conf.direct:
|
||||
if len(kb.responseTimes) < MIN_TIME_RESPONSES:
|
||||
if len(kb.responseTimes[kb.responseTimeMode]) < MIN_TIME_RESPONSES:
|
||||
warnMsg = "time-based standard deviation method used on a model "
|
||||
warnMsg += "with less than %d response times" % MIN_TIME_RESPONSES
|
||||
logger.warn(warnMsg)
|
||||
|
||||
lowerStdLimit = average(kb.responseTimes) + TIME_STDEV_COEFF * deviation
|
||||
lowerStdLimit = average(kb.responseTimes[kb.responseTimeMode]) + TIME_STDEV_COEFF * deviation
|
||||
retVal = (threadData.lastQueryDuration >= max(MIN_VALID_DELAYED_RESPONSE, lowerStdLimit))
|
||||
|
||||
if not kb.testMode and retVal:
|
||||
|
|
|
@ -1891,7 +1891,9 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||
kb.reflectiveCounters = {REFLECTIVE_COUNTER.MISS: 0, REFLECTIVE_COUNTER.HIT: 0}
|
||||
kb.requestCounter = 0
|
||||
kb.resendPostOnRedirect = None
|
||||
kb.responseTimes = []
|
||||
kb.responseTimes = {}
|
||||
kb.responseTimeMode = None
|
||||
kb.responseTimePayload = None
|
||||
kb.resumeValues = True
|
||||
kb.safeCharEncode = False
|
||||
kb.safeReq = AttribDict()
|
||||
|
@ -1915,7 +1917,6 @@ def _setKnowledgeBaseAttributes(flushAll=True):
|
|||
kb.timeValidCharsRun = 0
|
||||
kb.uChar = NULL
|
||||
kb.unionDuplicates = False
|
||||
kb.whereCollectTimes = False
|
||||
kb.xpCmdshellAvailable = False
|
||||
|
||||
if flushAll:
|
||||
|
|
|
@ -61,6 +61,9 @@ URI_QUESTION_MARKER = "__QUESTION_MARK__"
|
|||
ASTERISK_MARKER = "__ASTERISK_MARK__"
|
||||
REPLACEMENT_MARKER = "__REPLACEMENT_MARK__"
|
||||
|
||||
RANDOM_INTEGER_MARKER = "[RANDINT]"
|
||||
RANDOM_STRING_MARKER = "[RANDSTR]"
|
||||
|
||||
PAYLOAD_DELIMITER = "__PAYLOAD_DELIMITER__"
|
||||
CHAR_INFERENCE_MARK = "%c"
|
||||
PRINTABLE_CHAR_REGEX = r"[^\x00-\x1f\x7f-\xff]"
|
||||
|
|
|
@ -97,6 +97,8 @@ from lib.core.settings import LARGE_CHUNK_TRIM_MARKER
|
|||
from lib.core.settings import PAYLOAD_DELIMITER
|
||||
from lib.core.settings import PERMISSION_DENIED_REGEX
|
||||
from lib.core.settings import PLAIN_TEXT_CONTENT_TYPE
|
||||
from lib.core.settings import RANDOM_INTEGER_MARKER
|
||||
from lib.core.settings import RANDOM_STRING_MARKER
|
||||
from lib.core.settings import REPLACEMENT_MARKER
|
||||
from lib.core.settings import TEXT_CONTENT_TYPE_REGEX
|
||||
from lib.core.settings import UNENCODED_ORIGINAL_VALUE
|
||||
|
@ -1020,34 +1022,37 @@ class Connect(object):
|
|||
post = urlencode(post, spaceplus=kb.postSpaceToPlus)
|
||||
|
||||
if timeBasedCompare:
|
||||
if len(kb.responseTimes) < MIN_TIME_RESPONSES:
|
||||
if len(kb.responseTimes.get(kb.responseTimeMode, [])) < MIN_TIME_RESPONSES:
|
||||
clearConsoleLine()
|
||||
|
||||
kb.responseTimes.setdefault(kb.responseTimeMode, [])
|
||||
|
||||
if conf.tor:
|
||||
warnMsg = "it's highly recommended to avoid usage of switch '--tor' for "
|
||||
warnMsg += "time-based injections because of its high latency time"
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
warnMsg = "[%s] [WARNING] time-based comparison requires " % time.strftime("%X")
|
||||
warnMsg = "[%s] [WARNING] %stime-based comparison requires " % (time.strftime("%X"), "(case) " if kb.responseTimeMode else "")
|
||||
warnMsg += "larger statistical model, please wait"
|
||||
dataToStdout(warnMsg)
|
||||
|
||||
while len(kb.responseTimes) < MIN_TIME_RESPONSES:
|
||||
Connect.queryPage(content=True)
|
||||
while len(kb.responseTimes[kb.responseTimeMode]) < MIN_TIME_RESPONSES:
|
||||
value = kb.responseTimePayload.replace(RANDOM_INTEGER_MARKER, str(randomInt(6))).replace(RANDOM_STRING_MARKER, randomStr()) if kb.responseTimePayload else kb.responseTimePayload
|
||||
Connect.queryPage(value=value, content=True, raise404=False)
|
||||
dataToStdout('.')
|
||||
|
||||
dataToStdout("\n")
|
||||
dataToStdout(" (done)\n")
|
||||
|
||||
elif not kb.testMode:
|
||||
warnMsg = "it is very important not to stress the network adapter "
|
||||
warnMsg = "it is very important to not stress the network adapter "
|
||||
warnMsg += "during usage of time-based payloads to prevent potential "
|
||||
warnMsg += "errors "
|
||||
warnMsg += "disruptions "
|
||||
singleTimeWarnMessage(warnMsg)
|
||||
|
||||
if not kb.laggingChecked:
|
||||
kb.laggingChecked = True
|
||||
|
||||
deviation = stdev(kb.responseTimes)
|
||||
deviation = stdev(kb.responseTimes[kb.responseTimeMode])
|
||||
|
||||
if deviation > WARN_TIME_STDEV:
|
||||
kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE
|
||||
|
@ -1115,7 +1120,8 @@ class Connect(object):
|
|||
if timeBasedCompare:
|
||||
return wasLastResponseDelayed()
|
||||
elif noteResponseTime:
|
||||
kb.responseTimes.append(threadData.lastQueryDuration)
|
||||
kb.responseTimes.setdefault(kb.responseTimeMode, [])
|
||||
kb.responseTimes[kb.responseTimeMode].append(threadData.lastQueryDuration)
|
||||
|
||||
if not response and removeReflection:
|
||||
page = removeReflectiveValues(page, payload)
|
||||
|
|
|
@ -432,6 +432,8 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
|||
found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE
|
||||
|
||||
if time and (isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME) or isTechniqueAvailable(PAYLOAD.TECHNIQUE.STACKED)) and not found:
|
||||
kb.responseTimeMode = re.sub(r"(?i)[^a-z]", "", re.sub(r"'[^']+'", "", expression)) if re.search(r"(?i)SELECT.+FROM", expression) else None
|
||||
|
||||
if isTechniqueAvailable(PAYLOAD.TECHNIQUE.TIME):
|
||||
kb.technique = PAYLOAD.TECHNIQUE.TIME
|
||||
else:
|
||||
|
@ -441,7 +443,6 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
|||
value = _goBooleanProxy(booleanExpression)
|
||||
else:
|
||||
value = _goInferenceProxy(query, fromUser, batch, unpack, charsetType, firstChar, lastChar, dump)
|
||||
|
||||
else:
|
||||
errMsg = "none of the injection types identified can be "
|
||||
errMsg += "leveraged to retrieve queries output"
|
||||
|
@ -449,6 +450,7 @@ def getValue(expression, blind=True, union=True, error=True, time=True, fromUser
|
|||
|
||||
finally:
|
||||
kb.resumeValues = True
|
||||
kb.responseTimeMode = None
|
||||
|
||||
conf.tbl = popValue()
|
||||
conf.db = popValue()
|
||||
|
|
|
@ -47,8 +47,10 @@ from lib.core.settings import INFERENCE_NOT_EQUALS_CHAR
|
|||
from lib.core.settings import MIN_TIME_RESPONSES
|
||||
from lib.core.settings import MAX_BISECTION_LENGTH
|
||||
from lib.core.settings import MAX_TIME_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
|
||||
from lib.core.settings import RANDOM_INTEGER_MARKER
|
||||
from lib.core.settings import VALID_TIME_CHARS_RUN_THRESHOLD
|
||||
from lib.core.threads import getCurrentThreadData
|
||||
from lib.core.threads import runThreads
|
||||
|
@ -261,29 +263,23 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
|
|||
while len(charTbl) != 1:
|
||||
position = (len(charTbl) >> 1)
|
||||
posValue = charTbl[position]
|
||||
falsePayload = None
|
||||
|
||||
if "'%s'" % CHAR_INFERENCE_MARK not in payload:
|
||||
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx, posValue))
|
||||
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx, RANDOM_INTEGER_MARKER))
|
||||
else:
|
||||
# e.g.: ... > '%c' -> ... > ORD(..)
|
||||
markingValue = "'%s'" % CHAR_INFERENCE_MARK
|
||||
unescapedCharValue = unescaper.escape("'%s'" % decodeIntToUnicode(posValue))
|
||||
forgedPayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, unescapedCharValue)
|
||||
falsePayload = safeStringFormat(payload, (expressionUnescaped, idx)).replace(markingValue, NULL)
|
||||
|
||||
if timeBasedCompare and kb.whereCollectTimes:
|
||||
kb.responseTimes = []
|
||||
|
||||
warnMsg = "\n[%s] [WARNING] time-based comparison requires " % time.strftime("%X")
|
||||
warnMsg += "larger statistical model, please wait"
|
||||
dataToStdout(warnMsg)
|
||||
|
||||
while len(kb.responseTimes) < MIN_TIME_RESPONSES:
|
||||
falseWherePayload = re.sub(r"\b%s\b" % posValue, str(randomInt(6)), forgedPayload)
|
||||
Request.queryPage(falseWherePayload, content=True, raise404=False)
|
||||
dataToStdout('.')
|
||||
|
||||
dataToStdout("\n")
|
||||
kb.whereCollectTimes = False
|
||||
if timeBasedCompare:
|
||||
if kb.responseTimeMode:
|
||||
kb.responseTimePayload = falsePayload
|
||||
else:
|
||||
kb.responseTimePayload = None
|
||||
|
||||
result = Request.queryPage(forgedPayload, timeBasedCompare=timeBasedCompare, raise404=False)
|
||||
incrementCounter(kb.technique)
|
||||
|
|
|
@ -236,10 +236,6 @@ class Entries:
|
|||
|
||||
query = whereQuery(query)
|
||||
|
||||
if conf.dumpWhere:
|
||||
kb.whereCollectTimes = True
|
||||
pushValue(kb.responseTimes)
|
||||
|
||||
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
||||
|
||||
lengths = {}
|
||||
|
@ -328,10 +324,6 @@ class Entries:
|
|||
warnMsg = "Ctrl+C detected in dumping phase"
|
||||
logger.warn(warnMsg)
|
||||
|
||||
if conf.dumpWhere:
|
||||
kb.responseTimes = popValue()
|
||||
kb.whereCollectTimes = False
|
||||
|
||||
for column, columnEntries in entries.items():
|
||||
length = max(lengths[column], len(column))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user