Esempio n. 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
Esempio n. 2
0
def _unionTestByCharBruteforce(comment, place, parameter, value, prefix, suffix, paramDict, parameters):
    """
    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)

    # 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, paramDict, parameters, PAYLOAD.WHERE.ORIGINAL if isNullValue(kb.uChar) else PAYLOAD.WHERE.NEGATIVE)
    if count:
        validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count, paramDict, parameters)

        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:
                    conf.uChar = kb.uChar = str(randomInt(2))
                    validPayload, vector = _unionConfirm(comment, place, parameter, prefix, suffix, count, paramDict, parameters)


        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
Esempio n. 3
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. 4
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. 5
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. 6
0
    def payload_t(self, paramDict, parameters=None, place=None, parameter=None, value=None, newValue=None, where=None):
        """
        This method replaces the affected parameter with the SQL
        injection statement to request
        """

        retVal = ""
        paramString = parameters[place]
        paramDict = paramDict[place]
        origValue = getUnicode(paramDict[parameter])

        #如果参数值为空则生成个值
        if value is None:
            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()
            elif where == PAYLOAD.WHERE.REPLACE:
                value = ""
            else:
                value = origValue

            newValue = "%s%s" % (value, newValue)

        newValue = self.cleanupPayload(newValue, origValue)

        #支持修改http中各种请求的参数
        if place in (PLACE.URI, PLACE.CUSTOM_POST, PLACE.CUSTOM_HEADER):
            pass
        elif place in (PLACE.USER_AGENT, PLACE.REFERER, PLACE.HOST):
            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:
                pass
                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. 7
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. 8
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_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
        
        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"
            # print (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
                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