Example #1
0
def heuristicCheckSqlInjection(place, parameter):
    if kb.nullConnection:
        debugMsg = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return None

    if wasLastRequestDBMSError():
        debugMsg = "heuristic checking skipped "
        debugMsg += "because original page content "
        debugMsg += "contains DBMS error"
        logger.debug(debugMsg)
        return None

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    payload = "%s%s%s" % (prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    page, _ = Request.queryPage(payload, place, content=True, raise404=False)

    parseFilePaths(page)

    result = wasLastRequestDBMSError()

    infoMsg = "heuristic test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    kb.heuristicTest = result

    if not result and kb.dynamicParameter:
        _ = conf.paramDict[place][parameter]

        if _.isdigit():
            randInt = int(randomInt())
            payload = "%s%s%s" % (prefix, "%s-%s" % (int(_) + randInt, randInt), suffix)
            payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
            result = Request.queryPage(payload, place, raise404=False)

    if result:
        infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return result
Example #2
0
def heuristicCheckSqlInjection(place, parameter):
    if kb.nullConnection:
        debugMsg = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    payload = "%s%s%s" % (prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    Request.queryPage(payload, place, content=True, raise404=False)

    result = wasLastRequestDBMSError()

    infoMsg = "heuristic test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    if result:
        infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return result
Example #3
0
def checkConnection(suppressOutput=False):
    try:
        socket.gethostbyname(conf.hostname)
    except socket.gaierror:
        errMsg = "host '%s' does not exist" % conf.hostname
        raise sqlmapConnectionException, errMsg

    if not suppressOutput:
        infoMsg = "testing connection to the target url"
        logger.info(infoMsg)

    try:
        page, _ = Request.queryPage(content=True)
        kb.originalPage = kb.pageTemplate = page

        kb.errorIsNone = False

        if not kb.originalPage:
            errMsg = "unable to retrieve page content"
            raise sqlmapConnectionException, errMsg
        elif wasLastRequestDBMSError():
            warnMsg = "there is a DBMS error found in the HTTP response body"
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        elif wasLastRequestHTTPError():
            warnMsg = "the web server responded with an HTTP error code "
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        else:
            kb.errorIsNone = True
    except sqlmapConnectionException, errMsg:
        errMsg = getUnicode(errMsg)
        raise sqlmapConnectionException, errMsg
Example #4
0
def checkConnection(suppressOutput=False):
    if not any([conf.proxy, conf.tor]):
        try:
            socket.getaddrinfo(conf.hostname, None)
        except socket.gaierror:
            errMsg = "host '%s' does not exist" % conf.hostname
            raise sqlmapConnectionException, errMsg

    if not suppressOutput:
        infoMsg = "testing connection to the target url"
        logger.info(infoMsg)

    try:
        page, _ = Request.queryPage(content=True, noteResponseTime=False)
        kb.originalPage = kb.pageTemplate = page

        kb.errorIsNone = False

        if not kb.originalPage and wasLastRequestHTTPError():
            errMsg = "unable to retrieve page content"
            raise sqlmapConnectionException, errMsg
        elif wasLastRequestDBMSError():
            warnMsg = "there is a DBMS error found in the HTTP response body"
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        elif wasLastRequestHTTPError():
            warnMsg = "the web server responded with an HTTP error code "
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        else:
            kb.errorIsNone = True
    except sqlmapConnectionException, errMsg:
        errMsg = getUnicode(errMsg)
        raise sqlmapConnectionException, errMsg
Example #5
0
def heuristicCheckSqlInjection(place, parameter, value):
    if kb.nullConnection:
        debugMsg  = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    payload = "%s%s%s%s" % (value, prefix, randomStr(length=10, alphabet=['"', '\'', ')', '(']), suffix)
    payload = agent.payload(place, parameter, value, payload)
    Request.queryPage(payload, place, raise404=False)
    result = wasLastRequestDBMSError()

    infoMsg  = "heuristics shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    if result:
        infoMsg += "be injectable (possible DBMS: %s)" % (kb.htmlFp[-1] if kb.htmlFp else 'Unknown')
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warning(infoMsg)
Example #6
0
File: use.py Project: jonas8/sqlmap
def _oneShotUnionUse(expression, unpack=True, limited=False):
    retVal = hashDBRetrieve("%s%s" % (conf.hexConvert, expression), checkConf=True)  # as union data is stored raw unconverted

    threadData = getCurrentThreadData()
    threadData.resumed = retVal is not None

    if retVal is None:
        # Prepare expression with delimiters
        injExpression = unescaper.unescape(agent.concatQuery(expression, unpack))

        where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else None

        # Forge the union SQL injection request
        vector = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector
        kb.unionDuplicates = vector[7]
        query = agent.forgeUnionQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
        payload = agent.payload(newValue=query, where=where)

        # Perform the request
        page, headers = Request.queryPage(payload, content=True, raise404=False)

        incrementCounter(PAYLOAD.TECHNIQUE.UNION)

        # Parse the returned page to get the exact union-based
        # SQL injection output
        def _(regex):
            return reduce(lambda x, y: x if x is not None else y, (\
                    extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE), \
                    extractRegexResult(regex, removeReflectiveValues(listToStrValue(headers.headers \
                    if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), \
                    None)

        # Automatically patching last char trimming cases
        if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
            warnMsg = "automatically patching output having last char trimmed"
            singleTimeWarnMessage(warnMsg)
            page = page.replace(kb.chars.stop[:-1], kb.chars.stop)

        retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))

        if retVal is not None:
            retVal = getUnicode(retVal, kb.pageEncoding)

            # Special case when DBMS is Microsoft SQL Server and error message is used as a result of union injection
            if Backend.isDbms(DBMS.MSSQL) and wasLastRequestDBMSError():
                retVal = htmlunescape(retVal).replace("<br>", "\n")

            hashDBWrite("%s%s" % (conf.hexConvert, expression), retVal)
        else:
            trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))

            if trimmed:
                warnMsg = "possible server trimmed output detected "
                warnMsg += "(probably due to its length and/or content): "
                warnMsg += safecharencode(trimmed)
                logger.warn(warnMsg)

    return retVal
Example #7
0
def __oneShotUnionUse(expression, unpack=True, limited=False):
    retVal = hashDBRetrieve("%s%s" % (conf.hexConvert, expression), checkConf=True)  # as inband data is stored raw unconverted

    threadData = getCurrentThreadData()
    threadData.resumed = retVal is not None

    if retVal is None:
        # Prepare expression with delimiters
        injExpression = unescaper.unescape(agent.concatQuery(expression, unpack))

        where = PAYLOAD.WHERE.NEGATIVE if conf.limitStart or conf.limitStop else None

        # Forge the inband SQL injection request
        vector = kb.injection.data[PAYLOAD.TECHNIQUE.UNION].vector
        kb.unionDuplicates = vector[7]
        query = agent.forgeInbandQuery(injExpression, vector[0], vector[1], vector[2], vector[3], vector[4], vector[5], vector[6], None, limited)
        payload = agent.payload(newValue=query, where=where)

        # Perform the request
        page, headers = Request.queryPage(payload, content=True, raise404=False)

        incrementCounter(PAYLOAD.TECHNIQUE.UNION)

        # Parse the returned page to get the exact union-based
        # SQL injection output
        def _(regex):
            return reduce(lambda x, y: x if x is not None else y, ( \
                    extractRegexResult(regex, removeReflectiveValues(page, payload), re.DOTALL | re.IGNORECASE), \
                    extractRegexResult(regex, removeReflectiveValues(listToStrValue(headers.headers \
                    if headers else None), payload, True), re.DOTALL | re.IGNORECASE)), \
                    None)

        # Automatically patching last char trimming cases
        if kb.chars.stop not in (page or "") and kb.chars.stop[:-1] in (page or ""):
            warnMsg = "automatically patching output having last char trimmed"
            singleTimeWarnMessage(warnMsg)
            page = page.replace(kb.chars.stop[:-1], kb.chars.stop)

        retVal = _("(?P<result>%s.*%s)" % (kb.chars.start, kb.chars.stop))

        if retVal is not None:
            retVal = getUnicode(retVal, kb.pageEncoding)

            # Special case when DBMS is Microsoft SQL Server and error message is used as a result of inband injection
            if Backend.isDbms(DBMS.MSSQL) and wasLastRequestDBMSError():
                retVal = htmlunescape(retVal).replace("<br>", "\n")

            hashDBWrite("%s%s" % (conf.hexConvert, expression), retVal)
        else:
            trimmed = _("%s(?P<result>.*?)<" % (kb.chars.start))

            if trimmed:
                warnMsg = "possible server trimmed output detected (probably due to its length): "
                warnMsg += safecharencode(trimmed)
                logger.warn(warnMsg)

    return retVal
Example #8
0
def checkConnection(suppressOutput=False):
    if not any([conf.proxy, conf.tor]):
        try:
            socket.getaddrinfo(conf.hostname, None)
        except socket.gaierror:
            errMsg = "host '%s' does not exist" % conf.hostname
            raise sqlmapConnectionException, errMsg

    if not suppressOutput:
        infoMsg = "testing connection to the target url"
        logger.info(infoMsg)

    try:
        page, _ = Request.queryPage(content=True, noteResponseTime=False)
        kb.originalPage = kb.pageTemplate = page

        kb.errorIsNone = False

        if not kb.originalPage and wasLastRequestHTTPError():
            errMsg = "unable to retrieve page content"
            raise sqlmapConnectionException, errMsg
        elif wasLastRequestDBMSError():
            warnMsg = "there is a DBMS error found in the HTTP response body"
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        elif wasLastRequestHTTPError():
            warnMsg = "the web server responded with an HTTP error code (%d) " % getLastRequestHTTPError(
            )
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        else:
            kb.errorIsNone = True

    except sqlmapConnectionException, errMsg:
        errMsg = getUnicode(errMsg)
        logger.critical(errMsg)

        if conf.ipv6:
            warnMsg = "check connection to a provided "
            warnMsg += "IPv6 address with a tool like ping6 "
            warnMsg += "(e.g. 'ping6 %s') " % conf.hostname
            warnMsg += "prior to running sqlmap to avoid "
            warnMsg += "any addressing issues"
            singleTimeWarnMessage(warnMsg)

        if any(code in kb.httpErrorCodes for code in (httplib.NOT_FOUND, )):
            if conf.multipleTargets:
                return False

            msg = "it is not recommended to continue in this kind of cases. Do you want to quit and make sure that everything is set up properly? [Y/n] "
            if readInput(msg, default="Y") not in ("n", "N"):
                raise sqlmapSilentQuitException
            else:
                kb.ignoreNotFound = True
        else:
            raise
Example #9
0
def checkConnection(suppressOutput=False):
    if not any([conf.proxy, conf.tor]):
        try:
            socket.getaddrinfo(conf.hostname, None)
        except socket.gaierror:
            errMsg = "host '%s' does not exist" % conf.hostname
            raise SqlmapConnectionException, errMsg

    if not suppressOutput:
        infoMsg = "testing connection to the target url"
        logger.info(infoMsg)

    try:
        page, _ = Request.queryPage(content=True, noteResponseTime=False)
        kb.originalPage = kb.pageTemplate = page

        kb.errorIsNone = False

        if not kb.originalPage and wasLastRequestHTTPError():
            errMsg = "unable to retrieve page content"
            raise SqlmapConnectionException, errMsg
        elif wasLastRequestDBMSError():
            warnMsg = "there is a DBMS error found in the HTTP response body "
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        elif wasLastRequestHTTPError():
            warnMsg = "the web server responded with an HTTP error code (%d) " % getLastRequestHTTPError()
            warnMsg += "which could interfere with the results of the tests"
            logger.warn(warnMsg)
        else:
            kb.errorIsNone = True

    except SqlmapConnectionException, errMsg:
        errMsg = getUnicode(errMsg)
        logger.critical(errMsg)

        if conf.ipv6:
            warnMsg = "check connection to a provided "
            warnMsg += "IPv6 address with a tool like ping6 "
            warnMsg += "(e.g. 'ping6 %s') " % conf.hostname
            warnMsg += "prior to running sqlmap to avoid "
            warnMsg += "any addressing issues"
            singleTimeWarnMessage(warnMsg)

        if any(code in kb.httpErrorCodes for code in (httplib.NOT_FOUND, )):
            if conf.multipleTargets:
                return False

            msg = "it is not recommended to continue in this kind of cases. Do you want to quit and make sure that everything is set up properly? [Y/n] "
            if readInput(msg, default="Y") not in ("n", "N"):
                raise SqlmapSilentQuitException
            else:
                kb.ignoreNotFound = True
        else:
            raise
Example #10
0
def simpletonCheckSqlInjection(place, parameter, value):
    """
    This is a function for the quickest and simplest
    SQL injection check (e.g. AND 1=1) - only works
    with integer parameters
    """

    result = False
    randInt = randomInt()

    if value.isdigit():
        payload = "%s AND %d=%d" % (value, randInt, randInt)
    else:
        return False

    payload = agent.payload(place, parameter, value, payload)
    firstPage, _ = Request.queryPage(payload,
                                     place,
                                     content=True,
                                     raise404=False)

    if not (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
        if getComparePageRatio(kb.originalPage, firstPage,
                               filtered=True) > CONSTANT_RATIO:
            payload = "%s AND %d=%d" % (value, randInt, randInt + 1)

            payload = agent.payload(place, parameter, value, payload)
            secondPage, _ = Request.queryPage(payload,
                                              place,
                                              content=True,
                                              raise404=False)
            result = getComparePageRatio(firstPage, secondPage,
                                         filtered=True) <= CONSTANT_RATIO

    infoMsg = "simpleton test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    if result:
        infoMsg += "be injectable"
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return result
Example #11
0
    def __getDatabaseDir(self):
        retVal = None

        infoMsg = "searching for database directory"
        logger.info(infoMsg)

        randInt = randomInt()
        randStr = randomStr()
        _ = inject.checkBooleanExpression("EXISTS(SELECT * FROM %s.%s WHERE %d=%d)" % (randStr, randStr, randInt, randInt))

        if wasLastRequestDBMSError():
            threadData = getCurrentThreadData()
            match = re.search("Could not find file\s+'([^']+?)'", threadData.lastErrorPage[1])

            if match:
                retVal = match.group(1).rstrip("%s.mdb" % randStr)

                if retVal.endswith('\\'):
                    retVal = retVal[:-1]

        return retVal
Example #12
0
    def __getDatabaseDir(self):
        retVal = None

        infoMsg = "searching for database directory"
        logger.info(infoMsg)

        randInt = randomInt()
        randStr = randomStr()
        query = agent.prefixQuery("AND EXISTS(SELECT * FROM %s.%s WHERE %d=%d)" % (randStr, randStr, randInt, randInt))
        query = agent.suffixQuery(query)
        payload = agent.payload(newValue=query)
        page = Request.queryPage(payload, content=True)

        if wasLastRequestDBMSError():
            match = re.search("Could not find file\s+'([^']+?)'", page[0])

            if match:
                retVal = match.group(1).rstrip("%s.mdb" % randStr)

                if retVal.endswith("\\"):
                    retVal = retVal[:-1]

        return retVal
Example #13
0
def simpletonCheckSqlInjection(place, parameter, value):
    """
    This is a function for the quickest and simplest
    SQL injection check (e.g. AND 1=1) - only works
    with integer parameters
    """

    result = False
    randInt = randomInt()

    if value.isdigit():
        payload = "%s AND %d=%d" % (value, randInt, randInt)
    else:
        return False

    payload = agent.payload(place, parameter, value, payload)
    firstPage, _ = Request.queryPage(payload, place, content=True, raise404=False)

    if not (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
        if getComparePageRatio(kb.originalPage, firstPage, filtered=True) > CONSTANT_RATIO:
            payload = "%s AND %d=%d" % (value, randInt, randInt + 1)

            payload = agent.payload(place, parameter, value, payload)
            secondPage, _ = Request.queryPage(payload, place, content=True, raise404=False)
            result = getComparePageRatio(firstPage, secondPage, filtered=True) <= CONSTANT_RATIO

    infoMsg = "simpleton test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    if result:
        infoMsg += "be injectable"
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return result
Example #14
0
def heuristicCheckSqlInjection(place, parameter):
    if kb.nullConnection:
        debugMsg = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    payload = "%s%s%s" % (prefix, randomStr(length=10, alphabet=['"', "'", ")", "("]), suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    Request.queryPage(payload, place, content=True, raise404=False)

    result = wasLastRequestDBMSError()

    infoMsg = "heuristic test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    kb.heuristicTest = result

    if result:
        infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
        logger.info(infoMsg)
    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return result
Example #15
0
    def __getDatabaseDir(self):
        retVal = None

        infoMsg = "searching for database directory"
        logger.info(infoMsg)

        randInt = randomInt()
        randStr = randomStr()
        _ = inject.checkBooleanExpression(
            "EXISTS(SELECT * FROM %s.%s WHERE %d=%d)" %
            (randStr, randStr, randInt, randInt))

        if wasLastRequestDBMSError():
            threadData = getCurrentThreadData()
            match = re.search("Could not find file\s+'([^']+?)'",
                              threadData.lastErrorPage[1])

            if match:
                retVal = match.group(1).rstrip("%s.mdb" % randStr)

                if retVal.endswith('\\'):
                    retVal = retVal[:-1]

        return retVal
Example #16
0
def _unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLOAD.WHERE.ORIGINAL):
    validPayload = None
    vector = None

    positions = range(0, count)

    # Unbiased approach for searching appropriate usable column
    random.shuffle(positions)

    # For each column of the table (# of NULL) perform a request using
    # the UNION ALL SELECT statement to test it the target url is
    # affected by an exploitable union SQL injection vulnerability
    for position in positions:
        # Prepare expression with delimiters
        randQuery = randomStr(UNION_MIN_RESPONSE_CHARS)
        phrase = "%s%s%s".lower() % (kb.chars.start, randQuery, kb.chars.stop)
        randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
        randQueryUnescaped = unescaper.unescape(randQueryProcessed)

        # Forge the union SQL injection request
        query = agent.forgeUnionQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where)
        payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)

        # Perform the request
        page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
        content = "%s%s".lower() % (removeReflectiveValues(page, payload) or "", \
            removeReflectiveValues(listToStrValue(headers.headers if headers else None), \
            payload, True) or "")

        if content and phrase in content:
            validPayload = payload
            kb.unionDuplicates = content.count(phrase) > 1
            vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates)

            if where == PAYLOAD.WHERE.ORIGINAL:
                # Prepare expression with delimiters
                randQuery2 = randomStr(UNION_MIN_RESPONSE_CHARS)
                phrase2 = "%s%s%s".lower() % (kb.chars.start, randQuery2, kb.chars.stop)
                randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
                randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2)

                # Confirm that it is a full union SQL injection
                query = agent.forgeUnionQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where, multipleUnions=randQueryUnescaped2)
                payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)

                # Perform the request
                page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
                content = "%s%s".lower() % (page or "", listToStrValue(headers.headers if headers else None) or "")

                if not all(_ in content for _ in (phrase, phrase2)):
                    vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)
                elif not kb.unionDuplicates:
                    fromTable = " FROM (%s) AS %s" % (" UNION ".join("SELECT %d%s%s" % (_, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""), " AS %s" % randomStr() if _ == 0 else "") for _ in xrange(LIMITED_ROWS_TEST_NUMBER)), randomStr())

                    # Check for limited row output
                    query = agent.forgeUnionQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where, fromTable=fromTable)
                    payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)

                    # Perform the request
                    page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
                    content = "%s%s".lower() % (removeReflectiveValues(page, payload) or "", \
                        removeReflectiveValues(listToStrValue(headers.headers if headers else None), \
                        payload, True) or "")
                    if content.count(phrase) > 0 and content.count(phrase) < LIMITED_ROWS_TEST_NUMBER:
                        warnMsg = "output with limited number of rows detected. Switching to partial mode"
                        logger.warn(warnMsg)
                        vector = (position, count, comment, prefix, suffix, kb.uChar, PAYLOAD.WHERE.NEGATIVE, kb.unionDuplicates)

            unionErrorCase = kb.errorIsNone and wasLastRequestDBMSError()

            if unionErrorCase and count > 1:
                warnMsg = "combined UNION/error-based SQL injection case found on "
                warnMsg += "column %d. sqlmap will try to find another " % (position + 1)
                warnMsg += "column with better characteristics"
                logger.warn(warnMsg)
            else:
                break

    return validPayload, vector
Example #17
0
def _comparison(page, headers, code, getRatioValue, pageLength):
    threadData = getCurrentThreadData()

    if kb.testMode:
        threadData.lastComparisonPage = page

    if page is None and pageLength is None:
        return None

    seqMatcher = threadData.seqMatcher
    seqMatcher.set_seq1(kb.pageTemplate)

    if any((conf.string, conf.notString, conf.regexp)):
        rawResponse = "%s%s" % (
            listToStrValue(headers.headers if headers else ""), page)

        # String to match in page when the query is True and/or valid
        if conf.string:
            return conf.string in rawResponse

        # String to match in page when the query is False and/or invalid
        if conf.notString:
            return conf.notString not in rawResponse

        # Regular expression to match in page when the query is True and/or valid
        if conf.regexp:
            return re.search(conf.regexp, rawResponse, re.I | re.M) is not None

    # HTTP code to match when the query is valid
    if conf.code:
        return conf.code == code

    if page:
        # In case of an DBMS error page return None
        if kb.errorIsNone and (wasLastRequestDBMSError()
                               or wasLastRequestHTTPError()):
            return None

        # Dynamic content lines to be excluded before comparison
        if not kb.nullConnection:
            page = removeDynamicContent(page)
            seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate))

        if not pageLength:
            pageLength = len(page)

    if kb.nullConnection and pageLength:
        if not seqMatcher.a:
            errMsg = "problem occured while retrieving original page content "
            errMsg += "which prevents sqlmap from continuation. Please rerun, "
            errMsg += "and if the problem persists turn off any optimization switches"
            raise SqlmapNoneDataException(errMsg)

        ratio = 1. * pageLength / len(seqMatcher.a)

        if ratio > 1.:
            ratio = 1. / ratio
    else:
        # Preventing "Unicode equal comparison failed to convert both arguments to Unicode"
        # (e.g. if one page is PDF and the other is HTML)
        if isinstance(seqMatcher.a, str) and isinstance(page, unicode):
            page = page.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING,
                               'ignore')
        elif isinstance(seqMatcher.a, unicode) and isinstance(page, str):
            seqMatcher.a = seqMatcher.a.encode(
                kb.pageEncoding or DEFAULT_PAGE_ENCODING, 'ignore')

        seq1, seq2 = None, None

        if conf.titles:
            seq1 = extractRegexResult(HTML_TITLE_REGEX, seqMatcher.a)
            seq2 = extractRegexResult(HTML_TITLE_REGEX, page)
        else:
            seq1 = getFilteredPageContent(
                seqMatcher.a, True) if conf.textOnly else seqMatcher.a
            seq2 = getFilteredPageContent(page,
                                          True) if conf.textOnly else page

        if seq1 is None or seq2 is None:
            return None

        seq1 = seq1.replace(REFLECTED_VALUE_MARKER, "")
        seq2 = seq2.replace(REFLECTED_VALUE_MARKER, "")

        count = 0
        while count < min(len(seq1), len(seq2)):
            if seq1[count] == seq2[count]:
                count += 1
            else:
                break
        if count:
            seq1 = seq1[count:]
            seq2 = seq2[count:]

        seqMatcher.set_seq1(seq1)
        seqMatcher.set_seq2(seq2)

        ratio = round(seqMatcher.quick_ratio(), 3)

    # If the url is stable and we did not set yet the match ratio and the
    # current injected value changes the url page content
    if kb.matchRatio is None:
        if ratio >= LOWER_RATIO_BOUND and ratio <= UPPER_RATIO_BOUND:
            kb.matchRatio = ratio
            logger.debug("setting match ratio for current parameter to %.3f" %
                         kb.matchRatio)

    # If it has been requested to return the ratio and not a comparison
    # response
    if getRatioValue:
        return ratio

    elif ratio > UPPER_RATIO_BOUND:
        return True

    elif kb.matchRatio is None:
        return None

    else:
        return (ratio - kb.matchRatio) > DIFF_TOLERANCE
Example #18
0
def __unionPosition(comment, place, parameter, prefix, suffix, count, where=PAYLOAD.WHERE.ORIGINAL):
    validPayload = None
    vector = None

    positions = range(0, count)

    # Unbiased approach for searching appropriate usable column
    random.shuffle(positions)

    # For each column of the table (# of NULL) perform a request using
    # the UNION ALL SELECT statement to test it the target url is
    # affected by an exploitable inband SQL injection vulnerability
    for position in positions:
        # Prepare expression with delimiters
        randQuery = randomStr(UNION_MIN_RESPONSE_CHARS)
        phrase = "%s%s%s".lower() % (kb.chars.start, randQuery, kb.chars.stop)
        randQueryProcessed = agent.concatQuery("'%s'" % randQuery)
        randQueryUnescaped = unescaper.unescape(randQueryProcessed)

        # Forge the inband SQL injection request
        query = agent.forgeInbandQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where)
        payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)

        # Perform the request
        page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
        content = "%s%s".lower() % (
            removeReflectiveValues(page, payload) or "",
            removeReflectiveValues(listToStrValue(headers.headers if headers else None), payload, True) or "",
        )

        if content and phrase in content:
            validPayload = payload
            kb.unionDuplicates = content.count(phrase) > 1
            vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates)

            if where == PAYLOAD.WHERE.ORIGINAL:
                # Prepare expression with delimiters
                randQuery2 = randomStr(UNION_MIN_RESPONSE_CHARS)
                phrase2 = "%s%s%s".lower() % (kb.chars.start, randQuery2, kb.chars.stop)
                randQueryProcessed2 = agent.concatQuery("'%s'" % randQuery2)
                randQueryUnescaped2 = unescaper.unescape(randQueryProcessed2)

                # Confirm that it is a full inband SQL injection
                query = agent.forgeInbandQuery(
                    randQueryUnescaped,
                    position,
                    count,
                    comment,
                    prefix,
                    suffix,
                    kb.uChar,
                    where,
                    multipleUnions=randQueryUnescaped2,
                )
                payload = agent.payload(place=place, parameter=parameter, newValue=query, where=where)

                # Perform the request
                page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
                content = "%s%s".lower() % (page or "", listToStrValue(headers.headers if headers else None) or "")

                if not all(_ in content for _ in (phrase, phrase2)):
                    vector = (
                        position,
                        count,
                        comment,
                        prefix,
                        suffix,
                        kb.uChar,
                        PAYLOAD.WHERE.NEGATIVE,
                        kb.unionDuplicates,
                    )

            unionErrorCase = kb.errorIsNone and wasLastRequestDBMSError()

            if unionErrorCase and count > 1:
                warnMsg = "combined UNION/error-based SQL injection case found on "
                warnMsg += "column %d. sqlmap will try to find another " % (position + 1)
                warnMsg += "column with better characteristics"
                logger.warn(warnMsg)
            else:
                break

    return validPayload, vector
Example #19
0
def comparison(page, getRatioValue=False, pageLength=None):
    if page is None and pageLength is None:
        return None

    regExpResults = None

    seqMatcher = getCurrentThreadData().seqMatcher
    seqMatcher.set_seq1(kb.pageTemplate)

    if page:
        # String to match in page when the query is valid
        if conf.string:
            condition = conf.string in page
            return condition if not getRatioValue else (MAX_RATIO if condition else MIN_RATIO)

        # Regular expression to match in page when the query is valid
        if conf.regexp:
            condition = re.search(conf.regexp, page, re.I | re.M) is not None
            return condition if not getRatioValue else (MAX_RATIO if condition else MIN_RATIO)

        # In case of an DBMS error page return None
        if kb.errorIsNone and (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
            return None

        # Dynamic content lines to be excluded before comparison
        if not kb.nullConnection:
            page = removeDynamicContent(page)
            seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate))

        if not pageLength:
            pageLength = len(page)

    if kb.nullConnection and pageLength:
        if not seqMatcher.a:
            errMsg = "problem occured while retrieving original page content "
            errMsg += "which prevents sqlmap from continuation. please rerun, "
            errMsg += "and if problem persists please turn off optimization switches"
            raise sqlmapNoneDataException, errMsg

        ratio = 1. * pageLength / len(seqMatcher.a)

        if ratio > 1.:
            ratio = 1. / ratio
    else:
        seqMatcher.set_seq1(getFilteredPageContent(seqMatcher.a, True) if conf.textOnly else seqMatcher.a)
        seqMatcher.set_seq2(getFilteredPageContent(page, True) if conf.textOnly else page)
        ratio = round(seqMatcher.quick_ratio(), 3)

    # If the url is stable and we did not set yet the match ratio and the
    # current injected value changes the url page content
    if kb.matchRatio is None:
        if kb.pageStable and ratio >= LOWER_RATIO_BOUND and ratio <= UPPER_RATIO_BOUND:
            kb.matchRatio = ratio
            logger.debug("setting match ratio for current parameter to %.3f" % kb.matchRatio)

        elif not kb.pageStable:
            kb.matchRatio = CONSTANT_RATIO
            logger.debug("setting match ratio for current parameter to default value 0.900")

    # If it has been requested to return the ratio and not a comparison
    # response
    if getRatioValue:
        return ratio

    elif ratio > UPPER_RATIO_BOUND:
        return True

    elif kb.matchRatio is None:
        return None

    else:
        if kb.matchRatio == CONSTANT_RATIO:
            return ratio > kb.matchRatio
        else:
            return (ratio - kb.matchRatio) > DIFF_TOLERANCE
Example #20
0
def heuristicCheckSqlInjection(place, parameter):
    if kb.nullConnection:
        debugMsg = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return None

    if wasLastRequestDBMSError():
        debugMsg = "heuristic checking skipped "
        debugMsg += "because original page content "
        debugMsg += "contains DBMS error"
        logger.debug(debugMsg)
        return None

    origValue = conf.paramDict[place][parameter]

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    randStr = ""
    while '\'' not in randStr:
        randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)

    payload = "%s%s%s" % (prefix, randStr, suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    page, _ = Request.queryPage(payload, place, content=True, raise404=False)

    parseFilePaths(page)
    result = wasLastRequestDBMSError()

    infoMsg = "heuristic test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    def _(page):
        return any(_ in (page or "") for _ in FORMAT_EXCEPTION_STRINGS)

    casting = _(page) and not _(kb.originalPage)

    if not casting and not result and kb.dynamicParameter and origValue.isdigit():
        randInt = int(randomInt())
        payload = "%s%s%s" % (prefix, "%d-%d" % (int(origValue) + randInt, randInt), suffix)
        payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
        result = Request.queryPage(payload, place, raise404=False)

        if not result:
            randStr = randomStr()
            payload = "%s%s%s" % (prefix, "%s%s" % (origValue, randStr), suffix)
            payload = agent.payload(place, parameter, newValue=payload, where=PAYLOAD.WHERE.REPLACE)
            casting = Request.queryPage(payload, place, raise404=False)

    kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE

    if casting:
        errMsg = "possible %s casting " % ("integer" if origValue.isdigit() else "type")
        errMsg += "detected (e.g. %s=(int)$_REQUEST('%s')) " % (parameter, parameter)
        errMsg += "at the back-end web application"
        logger.error(errMsg)

        if kb.ignoreCasted is None:
            message = "do you want to skip those kind of cases (and save scanning time)? %s " % ("[Y/n]" if conf.multipleTargets else "[y/N]")
            kb.ignoreCasted = readInput(message, default='Y' if conf.multipleTargets else 'N').upper() != 'N'

    elif result:
        infoMsg += "be injectable (possible DBMS: %s)" % (Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
        logger.info(infoMsg)

    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return kb.heuristicTest
Example #21
0
def comparison(page, headers=None, getSeqMatcher=False, pageLength=None):
    if page is None and pageLength is None:
        return None

    regExpResults = None

    if page:
        # String to be excluded before calculating page hash
        if conf.eString and conf.eString in page:
            index = page.index(conf.eString)
            length = len(conf.eString)
            pageWithoutString = page[:index]
            pageWithoutString += page[index + length:]
            page = pageWithoutString

        # Regular expression matches to be excluded before calculating page hash
        if conf.eRegexp:
            regExpResults = re.findall(conf.eRegexp, page, re.I | re.M)

            if regExpResults:
                for regExpResult in regExpResults:
                    index = page.index(regExpResult)
                    length = len(regExpResult)
                    pageWithoutRegExp = page[:index]
                    pageWithoutRegExp += page[index + length:]
                    page = pageWithoutRegExp

        # String to match in page when the query is valid
        if conf.string:
            return conf.string in page

        # Regular expression to match in page when the query is valid
        if conf.regexp:
            return re.search(conf.regexp, page, re.I | re.M) is not None

        # In case of an DBMS error page return None
        if wasLastRequestDBMSError():
            return None

        # Dynamic content lines to be excluded before comparison
        if not kb.nullConnection and not conf.longestCommon:
            for item in kb.dynamicMarkings:
                prefix, suffix = item

                if prefix is None:
                    page = re.sub('(?s)^.+%s' % suffix, suffix, page)
                elif suffix is None:
                    page = re.sub('(?s)%s.+$' % prefix, prefix, page)
                else:
                    page = re.sub('(?s)%s.+%s' % (prefix, suffix),
                                  '%s%s' % (prefix, suffix), page)

        if not pageLength:
            pageLength = len(page)

    if kb.locks.seqLock:
        kb.locks.seqLock.acquire()

    if conf.longestCommon:
        (firstPage, secondPage) = (conf.seqMatcher.a, page)
        match = SequenceMatcher(None, firstPage,
                                secondPage).find_longest_match(
                                    0, len(firstPage), 0, len(secondPage))
        ratio = round(
            SequenceMatcher(None, firstPage[match[0]:match[0] + match[2]],
                            secondPage[match[1]:match[1] + match[2]]).ratio(),
            3)

    elif not conf.eRegexp and not conf.eString and kb.nullConnection and pageLength:
        ratio = 1. * pageLength / len(conf.seqMatcher.a)

        if ratio > 1.:
            ratio = 1. / ratio
    else:
        conf.seqMatcher.set_seq2(page)
        ratio = round(conf.seqMatcher.ratio(), 3)

    if kb.locks.seqLock:
        kb.locks.seqLock.release()

    # If the url is stable and we did not set yet the match ratio and the
    # current injected value changes the url page content
    if conf.matchRatio is None:
        if conf.thold:
            conf.matchRatio = conf.thold

        elif kb.pageStable and ratio > 0.6 and ratio < 1:
            conf.matchRatio = ratio
            logger.debug("setting match ratio for current parameter to %.3f" %
                         conf.matchRatio)

        elif not kb.pageStable or (kb.pageStable and ratio < 0.6):
            conf.matchRatio = CONSTANT_RATIO
            logger.debug(
                "setting match ratio for current parameter to default value 0.900"
            )

    # If it has been requested to return the ratio and not a comparison
    # response
    if getSeqMatcher:
        return ratio

    elif ratio == 1:
        return True

    elif conf.matchRatio is None:
        return None

    else:
        if conf.matchRatio == CONSTANT_RATIO or conf.thold:
            return ratio > conf.matchRatio
        else:
            return (ratio - conf.matchRatio) > DIFF_TOLERANCE
Example #22
0
def heuristicCheckSqlInjection(place, parameter):
    if kb.nullConnection:
        debugMsg = "heuristic checking skipped "
        debugMsg += "because NULL connection used"
        logger.debug(debugMsg)
        return None

    if wasLastRequestDBMSError():
        debugMsg = "heuristic checking skipped "
        debugMsg += "because original page content "
        debugMsg += "contains DBMS error"
        logger.debug(debugMsg)
        return None

    origValue = conf.paramDict[place][parameter]

    prefix = ""
    suffix = ""

    if conf.prefix or conf.suffix:
        if conf.prefix:
            prefix = conf.prefix

        if conf.suffix:
            suffix = conf.suffix

    randStr = ""
    while '\'' not in randStr:
        randStr = randomStr(length=10, alphabet=HEURISTIC_CHECK_ALPHABET)

    payload = "%s%s%s" % (prefix, randStr, suffix)
    payload = agent.payload(place, parameter, newValue=payload)
    page, _ = Request.queryPage(payload, place, content=True, raise404=False)

    parseFilePaths(page)
    result = wasLastRequestDBMSError()

    infoMsg = "heuristic test shows that %s " % place
    infoMsg += "parameter '%s' might " % parameter

    def _(page):
        return any(_ in (page or "") for _ in FORMAT_EXCEPTION_STRINGS)

    casting = _(page) and not _(kb.originalPage)

    if not casting and not result and kb.dynamicParameter and origValue.isdigit(
    ):
        randInt = int(randomInt())
        payload = "%s%s%s" % (prefix, "%d-%d" %
                              (int(origValue) + randInt, randInt), suffix)
        payload = agent.payload(place,
                                parameter,
                                newValue=payload,
                                where=PAYLOAD.WHERE.REPLACE)
        result = Request.queryPage(payload, place, raise404=False)

        if not result:
            randStr = randomStr()
            payload = "%s%s%s" % (prefix, "%s%s" %
                                  (origValue, randStr), suffix)
            payload = agent.payload(place,
                                    parameter,
                                    newValue=payload,
                                    where=PAYLOAD.WHERE.REPLACE)
            casting = Request.queryPage(payload, place, raise404=False)

    kb.heuristicTest = HEURISTIC_TEST.CASTED if casting else HEURISTIC_TEST.NEGATIVE if not result else HEURISTIC_TEST.POSITIVE

    if casting:
        errMsg = "possible %s casting " % ("integer"
                                           if origValue.isdigit() else "type")
        errMsg += "detected (e.g. %s=(int)$_REQUEST('%s')) " % (parameter,
                                                                parameter)
        errMsg += "at the back-end web application"
        logger.error(errMsg)

        if kb.ignoreCasted is None:
            message = "do you want to skip those kind of cases (and save scanning time)? %s " % (
                "[Y/n]" if conf.multipleTargets else "[y/N]")
            kb.ignoreCasted = readInput(
                message,
                default='Y' if conf.multipleTargets else 'N').upper() != 'N'

    elif result:
        infoMsg += "be injectable (possible DBMS: %s)" % (
            Format.getErrorParsedDBMSes() or UNKNOWN_DBMS_VERSION)
        logger.info(infoMsg)

    else:
        infoMsg += "not be injectable"
        logger.warn(infoMsg)

    return kb.heuristicTest
Example #23
0
def _comparison(page, headers, code, getRatioValue, pageLength):
    threadData = getCurrentThreadData()

    if kb.testMode:
        threadData.lastComparisonHeaders = listToStrValue(headers.headers) if headers else ""
        threadData.lastComparisonPage = page

    if page is None and pageLength is None:
        return None

    seqMatcher = threadData.seqMatcher
    seqMatcher.set_seq1(kb.pageTemplate)

    if any((conf.string, conf.notString, conf.regexp)):
        rawResponse = "%s%s" % (listToStrValue(headers.headers) if headers else "", page)

        # String to match in page when the query is True and/or valid
        if conf.string:
            return conf.string in rawResponse

        # String to match in page when the query is False and/or invalid
        if conf.notString:
            return conf.notString not in rawResponse

        # Regular expression to match in page when the query is True and/or valid
        if conf.regexp:
            return re.search(conf.regexp, rawResponse, re.I | re.M) is not None

    # HTTP code to match when the query is valid
    if conf.code:
        return conf.code == code

    if page:
        # In case of an DBMS error page return None
        if kb.errorIsNone and (wasLastRequestDBMSError() or wasLastRequestHTTPError()):
            return None

        # Dynamic content lines to be excluded before comparison
        if not kb.nullConnection:
            page = removeDynamicContent(page)
            seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate))

        if not pageLength:
            pageLength = len(page)

    if kb.nullConnection and pageLength:
        if not seqMatcher.a:
            errMsg = "problem occured while retrieving original page content "
            errMsg += "which prevents sqlmap from continuation. Please rerun, "
            errMsg += "and if the problem persists turn off any optimization switches"
            raise SqlmapNoneDataException(errMsg)

        ratio = 1. * pageLength / len(seqMatcher.a)

        if ratio > 1.:
            ratio = 1. / ratio
    else:
        # Preventing "Unicode equal comparison failed to convert both arguments to Unicode"
        # (e.g. if one page is PDF and the other is HTML)
        if isinstance(seqMatcher.a, str) and isinstance(page, unicode):
            page = page.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING, 'ignore')
        elif isinstance(seqMatcher.a, unicode) and isinstance(page, str):
            seqMatcher.a = seqMatcher.a.encode(kb.pageEncoding or DEFAULT_PAGE_ENCODING, 'ignore')

        seq1, seq2 = None, None

        if conf.titles:
            seq1 = extractRegexResult(HTML_TITLE_REGEX, seqMatcher.a)
            seq2 = extractRegexResult(HTML_TITLE_REGEX, page)
        else:
            seq1 = getFilteredPageContent(seqMatcher.a, True) if conf.textOnly else seqMatcher.a
            seq2 = getFilteredPageContent(page, True) if conf.textOnly else page

        if seq1 is None or seq2 is None:
            return None

        seq1 = seq1.replace(REFLECTED_VALUE_MARKER, "")
        seq2 = seq2.replace(REFLECTED_VALUE_MARKER, "")

        count = 0
        while count < min(len(seq1), len(seq2)):
            if seq1[count] == seq2[count]:
                count += 1
            else:
                break
        if count:
            seq1 = seq1[count:]
            seq2 = seq2[count:]

        seqMatcher.set_seq1(seq1)
        seqMatcher.set_seq2(seq2)

        ratio = round(seqMatcher.quick_ratio(), 3)

    # If the url is stable and we did not set yet the match ratio and the
    # current injected value changes the url page content
    if kb.matchRatio is None:
        if ratio >= LOWER_RATIO_BOUND and ratio <= UPPER_RATIO_BOUND:
            kb.matchRatio = ratio
            logger.debug("setting match ratio for current parameter to %.3f" % kb.matchRatio)

    # If it has been requested to return the ratio and not a comparison
    # response
    if getRatioValue:
        return ratio

    elif ratio > UPPER_RATIO_BOUND:
        return True

    elif kb.matchRatio is None:
        return None

    else:
        return (ratio - kb.matchRatio) > DIFF_TOLERANCE
Example #24
0
def comparison(page, getRatioValue=False, pageLength=None):
    if page is None and pageLength is None:
        return None

    regExpResults = None

    seqMatcher = getCurrentThreadData().seqMatcher
    seqMatcher.set_seq1(kb.pageTemplate)

    if page:
        # String to match in page when the query is valid
        if conf.string:
            condition = conf.string in page
            return condition if not getRatioValue else (
                MAX_RATIO if condition else MIN_RATIO)

        # Regular expression to match in page when the query is valid
        if conf.regexp:
            condition = re.search(conf.regexp, page, re.I | re.M) is not None
            return condition if not getRatioValue else (
                MAX_RATIO if condition else MIN_RATIO)

        # In case of an DBMS error page return None
        if kb.errorIsNone and (wasLastRequestDBMSError()
                               or wasLastRequestHTTPError()):
            return None

        # Dynamic content lines to be excluded before comparison
        if not kb.nullConnection:
            page = removeDynamicContent(page)
            seqMatcher.set_seq1(removeDynamicContent(kb.pageTemplate))

        if not pageLength:
            pageLength = len(page)

    if kb.nullConnection and pageLength:
        if not seqMatcher.a:
            errMsg = "problem occured while retrieving original page content "
            errMsg += "which prevents sqlmap from continuation. please rerun, "
            errMsg += "and if problem persists please turn off optimization switches"
            raise sqlmapNoneDataException, errMsg

        ratio = 1. * pageLength / len(seqMatcher.a)

        if ratio > 1.:
            ratio = 1. / ratio
    else:
        seqMatcher.set_seq1(
            getFilteredPageContent(seqMatcher.a, True) if conf.
            textOnly else seqMatcher.a)
        seqMatcher.set_seq2(
            getFilteredPageContent(page, True) if conf.textOnly else page)
        ratio = round(seqMatcher.quick_ratio(), 3)

    # If the url is stable and we did not set yet the match ratio and the
    # current injected value changes the url page content
    if kb.matchRatio is None:
        if kb.pageStable and ratio >= LOWER_RATIO_BOUND and ratio <= UPPER_RATIO_BOUND:
            kb.matchRatio = ratio
            logger.debug("setting match ratio for current parameter to %.3f" %
                         kb.matchRatio)

        elif not kb.pageStable:
            kb.matchRatio = CONSTANT_RATIO
            logger.debug(
                "setting match ratio for current parameter to default value 0.900"
            )

    # If it has been requested to return the ratio and not a comparison
    # response
    if getRatioValue:
        return ratio

    elif ratio > UPPER_RATIO_BOUND:
        return True

    elif kb.matchRatio is None:
        return None

    else:
        if kb.matchRatio == CONSTANT_RATIO:
            return ratio > kb.matchRatio
        else:
            return (ratio - kb.matchRatio) > DIFF_TOLERANCE