检测入口

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的大小,而是判断上次请求的响应时间是否在预期之内,不在则认为产生了时延,存在注入点。

并且采用了数学的方法, 将判断的准确度控制在相当高的一个百分比之上。

检测的思想具有很好的学习价值。

参考:

  1. http://blog.csdn.net/jinzhichaoshuiping/article/details/45568883
  2. http://www.cnblogs.com/hongfei/p/sqlmap-time-based-blind.html