Esempio n. 1
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
Esempio n. 2
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))
                payload = payload.replace(SINGLE_QUOTE_MARKER, "'")

                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
Esempio n. 3
0
    def cleanupPayload(self, payload, origValue=None):
        if payload is None:
            return

        _ = (('[DELIMITER_START]', 'qzkzq'), ('[DELIMITER_STOP]', 'qpkpq'), ('[AT_REPLACE]', 'qtq'), ('[SPACE_REPLACE]', 'qiq'), ('[DOLLAR_REPLACE]', 'qvq'), ('[HASH_REPLACE]', 'qiq'))

        payload = reduce(lambda x, y: x.replace(y[0], y[1]), _, payload)

        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())

        if origValue is not None:
            payload = payload.replace("[ORIGVALUE]", origValue if origValue.isdigit() else unescaper.escape("'%s'" % 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)
            elif not kb.testMode:
                errMsg = "invalid usage of inference payload without "
                errMsg += "knowledge of underlying DBMS"
                raise SqlmapNoneDataException(errMsg)

        return payload
Esempio n. 4
0
    def payload(self, place=None, parameter=None, value=None, newValue=None, where=None, addValue=None):

        """
        This method replaces the affected parameter with the SQL
        injection statement to request
        """
      
        retVal = ""
        paramString = place['paramstring']
        paramDict = place['paramdict']
        origValue = paramDict[parameter]#getUnicode(paramDict[parameter])
        
        randstr = ""

        if addValue is not None:
            value = origValue
            newValue = "%s%s" % (value, addValue)
            newValue = urlencode(newValue, '%', False, 'GET' != 'URI')
        else:
            if value is None:
                if all(c in "0123456789.+-" for c in parameter):
                    randstr = str(randomInt())
                else:
                    randstr = randomStr()
            
                return randstr

        #    """
        #    if where == PAYLOAD.WHERE.ORIGINAL:
        #        value = origValue
        #    elif where == PAYLOAD.WHERE.NEGATIVE:
        #        if conf.invalidLogical:
        #            match = re.search(r'\A[^ ]+', newValue)
        #            newValue = newValue[len(match.group() if match else ""):]
        #            _ = randomInt(2)
        #            value = "%s%s AND %s=%s" % (origValue, match.group() if
        #            match else "", _, _ + 1)
        #        elif conf.invalidBignum:
        #            value = randomInt(6)
        #        elif conf.invalidString:
        #            value = randomStr(6)
        #        else:
        #            if newValue.startswith("-"):
        #                value = ""
        #            else:
        #                value = "-%s" % randomInt()
        #    """
        

        if False:
            pass
        else:
            def _(pattern, repl, string):
                retVal = string
                match = None
                for match in re.finditer(pattern, string):
                    pass

                if match:
                    while True:
                        _ = re.search(r"\\g<([^>]+)>", repl)
                        if _:
                            try:
                                repl = repl.replace(_.group(0), match.group(int(_.group(1)) if _.group(1).isdigit() else _.group(1)))
                            except IndexError:
                                break
                        else:
                            break
                    retVal = string[:match.start()] + repl + string[match.end():]
                return retVal

            if origValue:
                regex = r"(\A|\b)%s=%s%s" % (re.escape(parameter), re.escape(origValue), r"(\Z|\b)" if origValue[-1].isalnum() else "")
                retVal = _(regex, "%s=%s" % (parameter, self.addPayloadDelimiters(newValue.replace("\\", "\\\\"))), paramString)

            
            """
            else:
                retVal = _(r"(\A|\b)%s=%s(\Z|%s|%s|\s)" % (re.escape(parameter), re.escape(origValue), DEFAULT_GET_POST_DELIMITER, DEFAULT_COOKIE_DELIMITER), "%s=%s\g<2>" % (parameter, self.addPayloadDelimiters(newValue.replace("\\", "\\\\"))), paramString)

            if retVal == paramString and urlencode(parameter) != parameter:
                retVal = _(r"(\A|\b)%s=%s" % (re.escape(urlencode(parameter)), re.escape(origValue)), "%s=%s" % (urlencode(parameter), self.addPayloadDelimiters(newValue.replace("\\", "\\\\"))), paramString)
            """

        if retVal:
            retVal = retVal.replace(BOUNDARY_BACKSLASH_MARKER, '\\')

        return retVal
Esempio n. 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
Esempio n. 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
Esempio n. 7
0
def _setKnowledgeBaseAttributes():
    kb.chars = AttribDict()
    kb.chars.delimiter = randomStr(length=6, lowercase=True)
    kb.chars.start = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR)
    kb.chars.stop = "%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, randomStr(length=3, alphabet=KB_CHARS_LOW_FREQUENCY_ALPHABET), KB_CHARS_BOUNDARY_CHAR)
    kb.chars.at, kb.chars.space, kb.chars.dollar, kb.chars.hash_ = ("%s%s%s" % (KB_CHARS_BOUNDARY_CHAR, _, KB_CHARS_BOUNDARY_CHAR) for _ in randomStr(length=4, lowercase=True))