Exemple #1
0
def checkDynParam_t(place, url_test, uri, paramDict, parameters, parameter,
                    value):
    dynResult = None
    randInt = randomInt()
    try:
        payload = agent.payload_t(paramDict, parameters, place, parameter,
                                  value, getUnicode(randInt))
        if (payload):
            url = "%s?%s" % (uri, payload)
        firstreponse = proxyqueryPage(url)
        dynResult = url_test.comparison(firstreponse.getdata())

        if not dynResult:
            #生成随机数  拼接成url 尝试两个不同的随机匹配结果
            randInt = randomInt()
            payload = agent.payload_t(paramDict, parameters, place, parameter,
                                      value, getUnicode(randInt))
            if (payload):
                url = "%s?%s" % (uri, payload)
            secondreponse = proxyqueryPage(url)
            dynResult = url_test.comparison(secondreponse.getdata())
    except Exception as ex:
        print ex

    result = None if dynResult is None else not dynResult

    return result
Exemple #2
0
def heuristicCheckSqlInjection(place, parameter, paramDict, parameters):
    origValue = paramDict[place][parameter]

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

    payload = agent.payload_t(paramDict,
                              parameters,
                              place,
                              parameter,
                              newValue=randStr)
    #payload = agent.payload(place, key, addValue=randStr)
    if (payload):
        url = "%s?%s" % (conf.url, payload)
    response = proxyqueryPage(url)
    page = response.getdata()

    handler = HTMLHandler(page)

    parseXmlFile(conf.errorsXML, handler)

    if conf.ErrorPage:
        return True
    else:
        return False
Exemple #3
0
        def _orderByTest(cols):
            query = agent.prefixQuery("ORDER BY %d" % cols, prefix=prefix)
            query = agent.suffixQuery(query, suffix=suffix, comment=comment)
            payload = agent.payload_t(paramDict, parameters, place, parameter, newValue=query, where=where)

            url = "%s?%s" % (conf.url, payload)
            response = proxyqueryPage(url)
            page = response.getdata()
            code = response.getstatus()

            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 checkComparison(page, kb.pageTemplate) or re.search(r"data types cannot be compared or sorted", page or "", re.I) is not None
Exemple #4
0
def checkTimeBasedCompare(value, url):
    start = time.time()
    value = agent.adjustLateValues(value)
    value = "%s%s%s" % (PAYLOAD_DELIMITER, value, PAYLOAD_DELIMITER)
    payload = agent.extractPayload(value)
    url = "%s?%s" % (url, payload)
    response = proxyqueryPage(url)
    # code = response.getstatus()

    lastQueryDuration = calculateDeltaSeconds(start)
    deviation = stdev(kb.responseTimes)

    if deviation:
        # if len(kb.responseTimes) < MIN_TIME_RESPONSES:
        #     warnMsg = "time-based standard deviation method used on a model "
        #     warnMsg += "with less than %d response times" % MIN_TIME_RESPONSES
        #     print warnMsg

        lowerStdLimit = average(
            kb.responseTimes) + TIME_STDEV_COEFF * deviation
        # print lastQueryDuration,lowerStdLimit,MIN_VALID_DELAYED_RESPONSE
        retVal = (lastQueryDuration >= max(MIN_VALID_DELAYED_RESPONSE,
                                           lowerStdLimit))
        return retVal
Exemple #5
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.

    place
    """

    #if kb.redirectChoice:
    #    return None

    paramString = place['paramstring']

    #dynResult = None
    #randInt = randomInt()

    #infoMsg = "testing if %s parameter '%s' is dynamic" %
    #(str(type(paramType)), parameter)
    #logger.info(infoMsg)

    payload = ""
    randstr = ""

    length = len(value)

    try:
        #FixME:这个可以优化掉
        response = proxyqueryPage(place['uri'])

        httpCode = response.getstatus()
        page = response.getdata()

        if all(c in "0123456789.+-" for c in value):
            randstr = str(randomInt(length=length))
        else:
            randstr = randomStr(length=length)

        payload = agent.payload(place, parameter, value, randstr)

        url = place['uri'].replace(paramString, payload)

        reponse = proxyqueryPage(url)

        firstPage = reponse.getdata()
        firstCode = reponse.getstatus()

        #second Page
        if all(c in "0123456789.+-" for c in value):
            randstr = str(randomInt(length=length))
        else:
            randstr = randomStr(length=length)

        payload = agent.payload(place, parameter, '', randstr)

        url = place['uri'].replace(paramString, payload)
        reponse = queryPage(url)

        secondPage = reponse.getdata()
        secondCode = reponse.getstatus()

        ratio1 = diffRatio(page, firstPage)
        ratio2 = diffRatio(page, secondPage)

        if ratio1 > UPPER_RATIO_BOUND_DYN and ratio2 > UPPER_RATIO_BOUND_DYN:
            if secondCode == firstCode and httpCode == firstCode:
                if diffRatio(firstPage, secondPage) > UPPER_RATIO_BOUND:
                    return True
                else:
                    return False
            else:
                return False
        else:
            return False
    except:
        print 'Excepiton occurred url:{0}'.format(place['uri'].replace(
            paramString, payload))
        return False
Exemple #6
0
def _unionPosition(comment, place, parameter, prefix, suffix, count, paramDict, parameters, where=PAYLOAD.WHERE.ORIGINAL):
    validPayload = None
    vector = None

    positions = [_ for _ in xrange(0, count)]

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

    for charCount in (UNION_MIN_RESPONSE_CHARS << 2, UNION_MIN_RESPONSE_CHARS):
        if vector:
            break

        # 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(charCount)
            phrase = ("%s%s%s" % (kb.chars.start, randQuery, kb.chars.stop)).lower()
            randQueryProcessed = agent.concatQuery("\'%s\'" % randQuery)
            randQueryUnescaped = _escape(randQueryProcessed)

            # Forge the union SQL injection request
            query = agent.forgeUnionQuery(randQueryUnescaped, position, count, comment, prefix, suffix, kb.uChar, where)
            payload = agent.payload_t(paramDict, parameters, place, parameter, newValue=query, where=where)
            url = "%s?%s" % (conf.url, payload)
            response = proxyqueryPage(url)
            page = response.getdata()
            headers = response.getheaders()

            # Perform the request
            content = ("%s%s" % (removeReflectiveValues(page, payload) or "", removeReflectiveValues(str(headers if headers else None), payload, True) or "")).lower()
            if content and phrase in content:
                validPayload = payload
                kb.unionDuplicates = len(re.findall(phrase, content, re.I)) > 1
                vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, False)

                if where == PAYLOAD.WHERE.ORIGINAL:
                    # Prepare expression with delimiters
                    randQuery2 = randomStr(charCount)
                    phrase2 = ("%s%s%s" % (kb.chars.start, randQuery2, kb.chars.stop)).lower()
                    randQueryProcessed2 = agent.concatQuery("\'%s\'" % randQuery2)
                    randQueryUnescaped2 = _escape(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_t(paramDict, parameters, place, parameter, newValue=query, where=where)
                    url = "%s?%s" % (conf.url, payload)
                    response = proxyqueryPage(url)
                    page = response.getdata()
                    headers = response.getheaders()
                    content = ("%s%s" % (page or "", str(headers if headers else None) or "")).lower()
                    
                    if not all(_ in content for _ in (phrase, phrase2)):
                        vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True)
                    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_t(paramDict, parameters, place, parameter, newValue=query, where=where)
                        url = "%s?%s" % (conf.url, payload)
                        response = proxyqueryPage(url)
                        page = response.getdata()
                        headers = response.getheaders()

                        # Perform the request
                        content = ("%s%s" % (removeReflectiveValues(page, payload) or "", removeReflectiveValues(str(headers if headers else None), payload, True) or "")).lower()
                        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"
                            print (warnMsg)
                            vector = (position, count, comment, prefix, suffix, kb.uChar, where, kb.unionDuplicates, True)

                unionErrorCase = kb.errorIsNone

                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"
                    print(warnMsg)
                else:
                    break

    return validPayload, vector
def checkSqlInjection(place, parameter, value, paramDict, parameters, url_test):

    injection = InjectionDict()
    tests_check = getSortedInjectionTests()
    seenPayload = set()
    extendTests = kb.dbms
    reduceTests = kb.dbms

    while conf.tests:
        
        test = conf.tests.pop(0)
        title = test.title
        clause = test.clause
        stype = test.stype
        # print title

        injection.dbms = kb.dbms

        if stype == PAYLOAD.TECHNIQUE.UNION:
            if "[CHAR]" in title:
                continue

            elif "[RANDNUM]" in title or "(NULL)" in title:
                    title = title.replace("[RANDNUM]", "random number")

            if test.request.columns == "[COLSTART]-[COLSTOP]":
                continue

            match = re.search(r"(\d+)-(\d+)", test.request.columns)
            if injection.data and match:
                lower, upper = int(match.group(1)), int(match.group(2))
                for _ in (lower, upper):
                    if _ > 1:
                        unionExtended = True
                        test.request.columns = re.sub(r"\b%d\b" % _, str(2 * _), test.request.columns)
                        title = re.sub(r"\b%d\b" % _, str(2 * _), title)
                        test.title = re.sub(r"\b%d\b" % _, str(2 * _), test.title)


        if injection.data and stype in injection.data:
            continue


        # Parse DBMS-specific payloads' details
        if "details" in test and "dbms" in test.details:
            payloadDbms = test.details.dbms
        else:
            payloadDbms = None


        if payloadDbms is not None:

            if reduceTests and not intersect(payloadDbms, reduceTests, True):
                continue


        comment = agent.getComment(test.request) if len(conf.boundaries) > 1 else None
        fstPayload = agent.cleanupPayload(test.request.payload, origValue=value)

        if value.isdigit():
            conf.boundaries = sorted(copy.deepcopy(conf.boundaries), key=lambda x: any(_ in (x.prefix or "") or _ in (x.suffix or "") for _ in ('"', '\'')))

        for boundary in conf.boundaries:
            injectable = False

            if boundary.level > 1:
                continue

            clauseMatch = False

            for clauseTest in test.clause:
                if clauseTest in boundary.clause:
                    clauseMatch = True
                    break

            if test.clause != [0] and boundary.clause != [0] and not clauseMatch:
                continue

            whereMatch = False

            for where in test.where:
                if where in boundary.where:
                    whereMatch = True
                    break

            if not whereMatch:
                continue

                # Parse boundary's <prefix>, <suffix> and <ptype>
            prefix = boundary.prefix if boundary.prefix else ""
            suffix = boundary.suffix if boundary.suffix else ""
            ptype = boundary.ptype


            condBound = (injection.prefix is not None and injection.suffix is not None)
            condBound &= (injection.prefix != prefix or injection.suffix != suffix)
            condType = injection.ptype is not None and injection.ptype != ptype


            if stype != PAYLOAD.TECHNIQUE.QUERY and (condBound or condType):
                    continue

            for where in test.where:
                templatePayload = None
                vector = None

                # Threat the parameter original value according to the
                # test's <where> tag
                if where == WHERE.ORIGINAL:
                    origValue = value

                    templatePayload = None

                if fstPayload:
                    boundPayload = agent.prefixQuery(fstPayload, prefix, where, clause)
                    boundPayload = agent.suffixQuery(boundPayload, comment, suffix, where)
                    reqPayload = agent.payload_t(paramDict, parameters, place, parameter, newValue=boundPayload, where=where)
                    if reqPayload:
                        if reqPayload in seenPayload:
                            continue
                        else:
                            seenPayload.add(reqPayload)
                else:
                    reqPayload = None

                for method, check in test.response.items():
                    check = agent.cleanupPayload(check, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None)
                    # In case of boolean-based blind SQL injection
                    if method == PAYLOAD.METHOD.COMPARISON:
                        def genCmpPayload():
                            sndPayload = agent.cleanupPayload(test.response.comparison, origValue=value if place not in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER) else None)

                            # Forge response payload by prepending with
                            # boundary's prefix and appending the
                            # boundary's
                            # suffix to the test's ' <payload><comment> '
                            # string
                            boundPayload = agent.prefixQuery(sndPayload, prefix, where, clause)
                            boundPayload = agent.suffixQuery(boundPayload, comment, suffix, where)
                            cmpPayload = agent.payload_t(paramDict, parameters, place, parameter, newValue=boundPayload, where=where)

                            return cmpPayload
                        
                        if(genCmpPayload()):
                            url = "%s?%s" % (conf.url, genCmpPayload())
                        falseResponse = proxyqueryPage(url)
                        falsePage = falseResponse.getdata()

                        if(reqPayload):
                            url = "%s?%s" % (conf.url, reqPayload)
                        trueResponse = proxyqueryPage(url)
                        truePage = trueResponse.getdata()
                        trueResult = url_test.comparison(truePage)

                        if trueResult and not(truePage == falsePage):
                            if(genCmpPayload()):
                                url = "%s?%s" % (conf.url, genCmpPayload())
                            falseResponse = proxyqueryPage(url)
                            falsePage = falseResponse.getdata()
                            falseResult = url_test.comparison(falsePage)
                            if not falseResult:
                                injectable = True

                        if not injectable:
                            trueSet = set(extractTextTagContent(truePage))
                            falseSet = set(extractTextTagContent(falsePage))
                            candidates = filter(None, (_.strip() if _.strip() in (url_test.firstPage or "") and _.strip() not in falsePage and _.strip() else None for _ in (trueSet - falseSet)))


                            if candidates:
                                injectable = True

                    # In case of time-based blind or stacked queries
                    # SQL injections
                    elif method == PAYLOAD.METHOD.TIME:
                        # Perform the test's request
                        trueResult = checkTimeBasedCompare(reqPayload, conf.url)
                        # trueResult = True
                        if trueResult:
                            if SLEEP_TIME_MARKER in reqPayload:
                                falseResult = checkTimeBasedCompare(reqPayload.replace(SLEEP_TIME_MARKER, "0"), conf.url)
                                if falseResult:
                                    continue
                            # Confirm test's results
                            trueResult = checkTimeBasedCompare(reqPayload, conf.url)

                            if trueResult:
                                # infoMsg = "%sparameter '%s' appears to be '%s' injectable " % ("%s " % paramType if paramType != parameter else "", parameter, title)
                                # print infoMsg

                                injectable = True
                    # In case of UNION query SQL injection
                    elif method == PAYLOAD.METHOD.UNION:
                        # Test for UNION injection and set the sample
                        # payload as well as the vector.
                        # NOTE: vector is set to  a tuple with 6 elements,
                        # used afterwards by Agent.forgeUnionQuery()
                        # method to forge the UNION query payload
                        configUnion(test.request.char, test.request.columns)

                        # # Test for UNION query SQL injection
                        reqPayload, vector = unionTest(comment, place, parameter, value, prefix, suffix,paramDict,parameters)
                        if isinstance(reqPayload, six.string_types):

                            injectable = True

                            # Overwrite 'where' because it can be set
                            # by unionTest() directly
                            where = vector[6]


                if injectable is True:
                    if injection.place is None or injection.parameter is None:
                        if place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
                                injection.parameter = place
                        else:
                                injection.parameter = parameter

                        injection.place = place
                        injection.ptype = ptype
                        injection.prefix = prefix
                        injection.suffix = suffix
                        injection.clause = clause


                    if hasattr(test, "details"):
                        for dKey, dValue in test.details.items():
                            if dKey == "dbms":
                                injection.dbms = dValue

                                if not isinstance(dValue, list):
                                    Backend.setDbms(dValue)
                                else:
                                    Backend.forceDbms(dValue[0], True)

                            elif dKey == "dbms_version" and injection.dbms_version is None:
                                injection.dbms_version = Backend.setVersion(dValue)

                            # elif dKey == "os" and injection.os is None:
                            #     injection.os = Backend.setOs(dValue)


                    if vector is None and "vector" in test and test.vector is not None:
                        vector = test.vector

                    injection.data[stype] = AttribDict()
                    injection.data[stype].title = title
                    injection.data[stype].payload = reqPayload
                    injection.data[stype].where = where
                    injection.data[stype].vector = vector
                    injection.data[stype].comment = comment
                    injection.data[stype].templatePayload = templatePayload

                    break


            if injectable is True:
                print injection.data[stype]