SQLMAP 基于时间注入判断原理
检测入口
lib/controller/checks.pyche ckSqlInjection函数中:
elifmethod == PAYLOAD.METHOD.TIME:
# Perform the test's request
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
if trueResult:
# Confirm test's results
trueResult = Request.queryPage(reqPayload, place, timeBasedCompare=True, raise404=False)
if trueResult:
infoMsg = "%s parameter '%s' appears to be '%s' injectable "% (paramType, parameter, title)
logger.info(infoMsg)
injectable = True
检测是否是时间盲注注入点,调用queryPage函数,若返回True,再调用该函数验证一次,验证成功之后,则判断该注入点存在时间盲注。
Lib/requests/connect.py queryPage函数:
若检测时间盲注,queryPage函数中timeBasedCompare设置为True
判断是否存在时间盲注时,若kb.responseTimes中的长度小于MIN_TIME_RESPONSES(30),则连续请求30次页面,获取响应时间。
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(" (done)\n")
timeBasedCompare为True,调用wasLastResponseDelayed()判断上次请求是否存在延迟。
if timeBasedCompare:
return wasLastResponseDelayed()
elif noteResponseTime:
kb.responseTimes.setdefault(kb.responseTimeMode, [])
kb.responseTimes[kb.responseTimeMode].append(threadData.lastQueryDuration)
Lib/core/common.py wasLastResponseDelayed()
首先根据responseTimes中的所有时间计算得到标准差deviation
计算最慢的响应时间:lowerStdLimit平均值+TIME_STDEV_COEFF*标准差。
TIME_STDEV_COEFF设置为7可以使得判断的准确度在99.9999999997440%
之上。
判断上次请求的响应时间是否大于max(MIN_VALID_DELAYED_RESPONSE,lowerStdLimit)),是则置retVal为True,返回。(即存在时间注入)
若当前网络情况良好,用户可以输入Y来optimize value,调用adjustTimeDelay()来缩短sleep时间。
def wasLastResponseDelayed():
"""
Returns True if the last web request resulted in a time-delay
"""
# 99.9999999997440% of all non time-based SQL injection affected
# response times should be inside +-7*stdev([normal response times])
# Math reference: http://www.answers.com/topic/standard-deviation
deviation = stdev(kb.responseTimes.get(kb.responseTimeMode, []))
threadData = getCurrentThreadData()
if deviation and not conf.direct:
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[kb.responseTimeMode]) + TIME_STDEV_COEFF * deviation
retVal = (threadData.lastQueryDuration >= max(MIN_VALID_DELAYED_RESPONSE, lowerStdLimit))
if not kb.testMode and retVal:
if kb.adjustTimeDelay is None:
msg = "do you want sqlmap to try to optimize value(s) "
msg += "for DBMS delay responses (option '--time-sec')? [Y/n] "
choice = readInput(msg, default='Y')
kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE if choice.upper() == 'N' else ADJUST_TIME_DELAY.YES
if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES:
adjustTimeDelay(threadData.lastQueryDuration, lowerStdLimit)
return retVal
else:
return (threadData.lastQueryDuration - conf.timeSec) >= 0
总结
Sqlmap根据基于时间的盲注技术来检测注入点,不需要依赖具体的sleep(n) n的大小,而是判断上次请求的响应时间是否在预期之内,不在则认为产生了时延,存在注入点。
并且采用了数学的方法, 将判断的准确度控制在相当高的一个百分比之上。
检测的思想具有很好的学习价值。