sqlmap 的时间型盲注判断

请求响应时长判断

wasLastResponseDelayed

sqlmap 的判断逻辑位于 sqlmap\lib\core\common.pywasLastResponseDelayed 函数中。具体判断的逻辑如下:

  1. 首先 在时延判断前 ,sqlmap 的全局变量 kb.responseTimes 中一般会保存收集了至少 30 个,不超过 200 个(用队列的方式永远保持是最近的 200 个方式,防止异常波动)的正常请求的响应时间集合。sqlmap 会计算这些响应时间的标准差 deviation
  2. 如果没有手动设置 --timeSec, 即指定 sleep 时间,sqlmap 会比较当前时延是否超过了 MAX(MIN_VALID_DELAYED_RESPONSE, 平均时延+7 * deviation) 的时长(MIN_VALID_DELAYED_RESPONSE =0.5),如果超出了则判断该请求存在时延。
  3. 如果手动设置了 --timeSec,则比较简单。直接判断时延是否超过了设置的 --timeSec 参数。超出则判断为存在时延。需要注意的一个小细节是 sqlmap 特殊处理了 MySQL 数据库,MySQL 额外再添加了 0.0.5 秒来降低误报。
    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 and not conf.disableStats:
            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.warning(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] "
    
                    kb.adjustTimeDelay = ADJUST_TIME_DELAY.DISABLE if not readInput(msg, default='Y', boolean=True) else ADJUST_TIME_DELAY.YES
                if kb.adjustTimeDelay is ADJUST_TIME_DELAY.YES:
                    adjustTimeDelay(threadData.lastQueryDuration, lowerStdLimit)
    
            return retVal
        else:
            delta = threadData.lastQueryDuration - conf.timeSec
            if Backend.getIdentifiedDbms() in (DBMS.MYSQL,):  # MySQL's SLEEP(X) lasts 0.05 seconds shorter on average
                delta += 0.05
            return delta >= 0