Пример #1
0
def checkPayload(payload):
    """
    This method checks if the generated payload is detectable by the
    PHPIDS filter rules
    """

    if not payload:
        return

    global rules

    detected = False
    payload = urldecode(payload)

    if not rules:
        xmlrules = readXmlFile(paths.PHPIDS_RULES_XML)
        rules = []

        for xmlrule in xmlrules.getElementsByTagName("filter"):
            rule = "(?i)%s" % xmlrule.getElementsByTagName('rule')[0].childNodes[0].nodeValue
            desc = __adjustGrammar(xmlrule.getElementsByTagName('description')[0].childNodes[0].nodeValue)
            rules.append((rule, desc))

    if payload:
        for rule, desc in rules:
            if re.search(rule, payload):
                detected = True
                logger.warn("highly probable IDS/IPS detection: '%s: %s'" % (desc, payload))

    if not detected:
        logger.warn("payload '%s' possibly gone undetected" % payload)
Пример #2
0
def parseTargetUrl():
    """
    Parse target url and set some attributes into the configuration
    singleton.
    """

    if not conf.url:
        return

    if not re.search("^http[s]*://", conf.url):
        if ":443/" in conf.url:
            conf.url = "https://" + conf.url
        else:
            conf.url = "http://" + conf.url

    __urlSplit = urlparse.urlsplit(conf.url)
    __hostnamePort = __urlSplit[1].split(":")

    conf.scheme = __urlSplit[0]
    conf.path = __urlSplit[2]
    conf.hostname = __hostnamePort[0]

    if len(__hostnamePort) == 2:
        conf.port = int(__hostnamePort[1])
    elif conf.scheme == "https":
        conf.port = 443
    else:
        conf.port = 80

    if __urlSplit[3]:
        conf.parameters["GET"] = urldecode(__urlSplit[3]).replace("%", "%%")

    conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port,
                                 conf.path)
Пример #3
0
def parseTargetUrl():
    """
    Parse target url and set some attributes into the configuration
    singleton.
    """

    if not conf.url:
        return

    if not re.search("^http[s]*://", conf.url):
        if ":443/" in conf.url:
            conf.url = "https://" + conf.url
        else:
            conf.url = "http://" + conf.url

    __urlSplit     = urlparse.urlsplit(conf.url)
    __hostnamePort = __urlSplit[1].split(":")

    conf.scheme    = __urlSplit[0]
    conf.path      = __urlSplit[2]
    conf.hostname  = __hostnamePort[0]

    if len(__hostnamePort) == 2:
        conf.port = int(__hostnamePort[1])
    elif conf.scheme == "https":
        conf.port = 443
    else:
        conf.port = 80

    if __urlSplit[3]:
        conf.parameters["GET"] = urldecode(__urlSplit[3]).replace("%", "%%")

    conf.url = "%s://%s:%d%s" % (conf.scheme, conf.hostname, conf.port, conf.path)
Пример #4
0
    def getTargetUrls(self):
        """
        This method returns the list of hosts with parameters out of
        your Google dork search results
        """

        for _ in self._matches:
            _ = urldecode(_)
            if re.search(r"(.*?)\?(.+)", _):
                kb.targetUrls.add((_, None, None, None))
            elif re.search(URI_INJECTABLE_REGEX, _, re.I):
                if kb.scanOnlyGoogleGETs is None:
                    message = "do you want to scan only results containing GET parameters? [Y/n] "
                    test = readInput(message, default="Y")
                    kb.scanOnlyGoogleGETs = test.lower() != 'n'
                if not kb.scanOnlyGoogleGETs:
                    kb.targetUrls.add((_, None, None, None))
Пример #5
0
    def getTargetUrls(self):
        """
        This method returns the list of hosts with parameters out of
        your Google dork search results
        """

        for _ in self._matches:
            _ = urldecode(_)
            if re.search(r"(.*?)\?(.+)", _):
                kb.targetUrls.add((_, None, None, None))
            elif re.search(URI_INJECTABLE_REGEX, _, re.I):
                if kb.scanOnlyGoogleGETs is None:
                    message = "do you want to scan only results containing GET parameters? [Y/n] "
                    test = readInput(message, default="Y")
                    kb.scanOnlyGoogleGETs = test.lower() != 'n'
                if not kb.scanOnlyGoogleGETs:
                    kb.targetUrls.add((_, None, None, None))
Пример #6
0
def checkPayload(payload):
    """
    This method checks if the generated payload is detectable by the
    PHPIDS filter rules
    """

    global rules

    payload = urldecode(payload)

    if not rules:
        xmlrules = readXmlFile(paths.PHPIDS_RULES_XML)
        rules = []

        for xmlrule in xmlrules.getElementsByTagName("filter"):
            rule = "(?i)%s" % xmlrule.getElementsByTagName('rule')[0].childNodes[0].nodeValue
            desc = __adjustGrammar(xmlrule.getElementsByTagName('description')[0].childNodes[0].nodeValue)
            rules.append((rule, desc))

    if payload:
        for rule, desc in rules:
            regObj = getCompiledRegex(rule)
            if regObj.search(payload):
                logger.warn("highly probable IDS/IPS detection: '%s: %s'" % (desc, payload))
Пример #7
0
def start():
    """
    This function calls a function that performs checks on both URL
    stability and all GET, POST, Cookie and User-Agent parameters to
    check if they are dynamic and SQL injection affected
    """

    if not conf.start:
        return False

    if conf.direct:
        initTargetEnv()
        setupTargetEnv()
        action()
        return True

    if conf.url and not any([conf.forms, conf.crawlDepth]):
        kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie))

    if conf.configFile and not kb.targetUrls:
        errMsg = "you did not edit the configuration file properly, set "
        errMsg += "the target url, list of targets or google dork"
        logger.error(errMsg)
        return False

    if kb.targetUrls and len(kb.targetUrls) > 1:
        infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
        logger.info(infoMsg)

    hostCount = 0
    cookieStr = ""

    for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
        try:
            conf.url = targetUrl
            conf.method = targetMethod
            conf.data = targetData
            conf.cookie = targetCookie

            initTargetEnv()
            parseTargetUrl()

            testSqlInj = False

            if PLACE.GET in conf.parameters and not any([conf.data, conf.testParameter]):
                for parameter in re.findall(
                    r"([^=]+)=([^%s]+%s?|\Z)" % (conf.pDel or ";", conf.pDel or ";"), conf.parameters[PLACE.GET]
                ):
                    paramKey = (conf.hostname, conf.path, PLACE.GET, parameter[0])

                    if paramKey not in kb.testedParams:
                        testSqlInj = True
                        break
            else:
                paramKey = (conf.hostname, conf.path, None, None)
                if paramKey not in kb.testedParams:
                    testSqlInj = True

            testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams

            if not testSqlInj:
                infoMsg = "skipping '%s'" % targetUrl
                logger.info(infoMsg)
                continue

            if conf.multipleTargets:
                hostCount += 1

                if conf.forms:
                    message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
                else:
                    message = "url %d:\n%s %s%s" % (
                        hostCount,
                        conf.method or HTTPMETHOD.GET,
                        targetUrl,
                        " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "",
                    )

                if conf.cookie:
                    message += "\nCookie: %s" % conf.cookie

                if conf.data:
                    message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else ""

                if conf.forms:
                    if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
                        continue

                    message += "\ndo you want to test this form? [Y/n/q] "
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        if conf.method == HTTPMETHOD.POST:
                            message = "Edit POST data [default: %s]%s: " % (
                                urlencode(conf.data) if conf.data else "None",
                                " (Warning: blank fields detected)"
                                if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)
                                else "",
                            )
                            conf.data = readInput(message, default=conf.data)
                            conf.data = __randomFillBlankFields(conf.data)
                            conf.data = (
                                urldecode(conf.data)
                                if conf.data and urlencode(DEFAULT_GET_POST_DELIMITER, None) not in conf.data
                                else conf.data
                            )

                        elif conf.method == HTTPMETHOD.GET:
                            if targetUrl.find("?") > -1:
                                firstPart = targetUrl[: targetUrl.find("?")]
                                secondPart = targetUrl[targetUrl.find("?") + 1 :]
                                message = "Edit GET data [default: %s]: " % secondPart
                                test = readInput(message, default=secondPart)
                                test = __randomFillBlankFields(test)
                                conf.url = "%s?%s" % (firstPart, test)

                        parseTargetUrl()

                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                elif conf.realTest:
                    logger.info(message)
                else:
                    message += "\ndo you want to test this url? [Y/n/q]"
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        pass
                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                    infoMsg = "testing url %s" % targetUrl
                    logger.info(infoMsg)

            setupTargetEnv()

            if not checkConnection(suppressOutput=conf.forms) or not checkString() or not checkRegexp():
                continue

            if conf.checkWaf:
                checkWaf()

            if conf.nullConnection:
                checkNullConnection()

            if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) and (
                kb.injection.place is None or kb.injection.parameter is None
            ):

                if not conf.string and not conf.regexp and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
                    # NOTE: this is not needed anymore, leaving only to display
                    # a warning message to the user in case the page is not stable
                    checkStability()

                # Do a little prioritization reorder of a testable parameter list
                parameters = conf.parameters.keys()

                # Order of testing list (last to first)
                orderList = (PLACE.URI, PLACE.GET, PLACE.POST, PLACE.CUSTOM_POST)

                for place in orderList:
                    if place in parameters:
                        parameters.remove(place)
                        parameters.insert(0, place)

                proceed = True

                for place in parameters:
                    # Test User-Agent and Referer headers only if
                    # --level >= 3
                    skip = place == PLACE.UA and conf.level < 3
                    skip |= place == PLACE.REFERER and conf.level < 3

                    # Test Host header only if
                    # --level >= 5
                    skip |= place == PLACE.HOST and conf.level < 5

                    # Test Cookie header only if --level >= 2
                    skip |= place == PLACE.COOKIE and conf.level < 2

                    skip |= place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.skip, True) not in ([], None)
                    skip |= place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.skip, True) not in ([], None)
                    skip |= place == PLACE.COOKIE and intersect(PLACE.COOKIE, conf.skip, True) not in ([], None)

                    skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter, True))
                    skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter, True))
                    skip &= not (place == PLACE.HOST and intersect(HOST_ALIASES, conf.testParameter, True))

                    if skip:
                        continue

                    if not conf.paramDict.has_key(place):
                        continue

                    paramDict = conf.paramDict[place]

                    for parameter, value in paramDict.items():
                        if not proceed:
                            break

                        kb.vainRun = False
                        testSqlInj = True
                        paramKey = (conf.hostname, conf.path, place, parameter)

                        if paramKey in kb.testedParams:
                            testSqlInj = False

                            infoMsg = "skipping previously processed %s parameter '%s'" % (place, parameter)
                            logger.info(infoMsg)

                        elif parameter in conf.testParameter:
                            pass

                        elif parameter == conf.rParam:
                            testSqlInj = False

                            infoMsg = "skipping randomizing %s parameter '%s'" % (place, parameter)
                            logger.info(infoMsg)

                        elif parameter in conf.skip:
                            testSqlInj = False

                            infoMsg = "skipping %s parameter '%s'" % (place, parameter)
                            logger.info(infoMsg)

                        # Ignore session-like parameters for --level < 4
                        elif conf.level < 4 and parameter.upper() in IGNORE_PARAMETERS:
                            testSqlInj = False

                            infoMsg = "ignoring %s parameter '%s'" % (place, parameter)
                            logger.info(infoMsg)

                        elif conf.realTest:
                            pass

                        elif PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
                            if not checkDynParam(place, parameter, value):
                                warnMsg = "%s parameter '%s' appears to be not dynamic" % (place, parameter)
                                logger.warn(warnMsg)

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

                        kb.testedParams.add(paramKey)

                        if testSqlInj:
                            check = heuristicCheckSqlInjection(place, parameter)

                            if not check:
                                if (
                                    conf.smart
                                    or conf.realTest
                                    and not simpletonCheckSqlInjection(place, parameter, value)
                                ):
                                    infoMsg = "skipping %s parameter '%s'" % (place, parameter)
                                    logger.info(infoMsg)
                                    continue

                            infoMsg = "testing for SQL injection on %s " % place
                            infoMsg += "parameter '%s'" % parameter
                            logger.info(infoMsg)

                            injection = checkSqlInjection(place, parameter, value)
                            proceed = not kb.endDetection

                            if injection is not None and injection.place is not None:
                                kb.injections.append(injection)

                                # In case when user wants to end detection phase (Ctrl+C)
                                if not proceed:
                                    break

                                msg = "%s parameter '%s' " % (injection.place, injection.parameter)
                                msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
                                test = readInput(msg, default="N")

                                if test[0] not in ("y", "Y"):
                                    proceed = False
                                    paramKey = (conf.hostname, conf.path, None, None)
                                    kb.testedParams.add(paramKey)
                            else:
                                warnMsg = "%s parameter '%s' is not " % (place, parameter)
                                warnMsg += "injectable"
                                logger.warn(warnMsg)

            if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None):
                if kb.vainRun and not conf.multipleTargets:
                    errMsg = "no parameter(s) found for testing in the provided data "
                    errMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')"
                    raise sqlmapNoneDataException, errMsg
                elif not conf.realTest:
                    errMsg = "all parameters appear to be not injectable."

                    if conf.level < 5 or conf.risk < 3:
                        errMsg += " Try to increase --level/--risk values "
                        errMsg += "to perform more tests."

                    if isinstance(conf.tech, list) and len(conf.tech) < 5:
                        errMsg += " Rerun without providing the option '--technique'."

                    if not conf.textOnly and kb.originalPage:
                        percent = 100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage)

                        if kb.dynamicParameters:
                            errMsg += " You can give it a go with the --text-only "
                            errMsg += "switch if the target page has a low percentage "
                            errMsg += "of textual content (~%.2f%% of " % percent
                            errMsg += "page content is text)."
                        elif percent < LOW_TEXT_PERCENT and not kb.errorIsNone:
                            errMsg += " Please retry with the --text-only switch "
                            errMsg += "(along with --technique=BU) as this case "
                            errMsg += "looks like a perfect candidate "
                            errMsg += "(low textual content along with inability "
                            errMsg += "of comparison engine to detect at least "
                            errMsg += "one dynamic parameter)."

                    if kb.heuristicTest:
                        errMsg += " As heuristic test turned out positive you are "
                        errMsg += "strongly advised to continue on with the tests. "
                        errMsg += "Please, consider usage of tampering scripts as "
                        errMsg += "your target might filter the queries."

                    if not conf.string and not conf.regexp:
                        errMsg += " Also, you can try to rerun by providing "
                        errMsg += "either a valid --string "
                        errMsg += "or a valid --regexp, refer to the user's "
                        errMsg += "manual for details"
                    elif conf.string:
                        errMsg += " Also, you can try to rerun by providing a "
                        errMsg += "valid --string as perhaps the string you "
                        errMsg += "have choosen does not match "
                        errMsg += "exclusively True responses"
                    elif conf.regexp:
                        errMsg += " Also, you can try to rerun by providing a "
                        errMsg += "valid --regexp as perhaps the regular "
                        errMsg += "expression that you have choosen "
                        errMsg += "does not match exclusively True responses"

                    raise sqlmapNotVulnerableException, errMsg
                else:
                    errMsg = "it seems that all parameters are not injectable"
                    raise sqlmapNotVulnerableException, errMsg
            else:
                # Flush the flag
                kb.testMode = False

                __saveToResultsFile()
                __saveToHashDB()
                __showInjections()
                __selectInjection()

            if kb.injection.place is not None and kb.injection.parameter is not None:
                if kb.testQueryCount == 0 and conf.realTest:
                    condition = False
                elif conf.multipleTargets:
                    message = "do you want to exploit this SQL injection? [Y/n] "
                    exploit = readInput(message, default="Y")

                    condition = not exploit or exploit[0] in ("y", "Y")
                else:
                    condition = True

                if condition:
                    action()

        except KeyboardInterrupt:
            if conf.multipleTargets:
                warnMsg = "user aborted in multiple target mode"
                logger.warn(warnMsg)

                message = "do you want to skip to the next target in list? [Y/n/q]"
                test = readInput(message, default="Y")

                if not test or test[0] in ("y", "Y"):
                    pass
                elif test[0] in ("n", "N"):
                    return False
                elif test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
            else:
                raise

        except sqlmapUserQuitException:
            raise

        except sqlmapSilentQuitException:
            raise

        except exceptionsTuple, e:
            e = getUnicode(e)

            if conf.multipleTargets:
                e += ", skipping to the next %s" % ("form" if conf.forms else "url")
                logger.error(e)
            else:
                logger.critical(e)
                return False

        finally:
Пример #8
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    if conf.direct:
        conf.parameters[None] = "direct connection"
        return

    testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
        parameters = conf.parameters[PLACE.GET]
        paramDict = paramToDict(PLACE.GET, parameters)

        if paramDict:
            conf.paramDict[PLACE.GET] = paramDict
            testableParameters = True

    # Perform checks on POST parameters
    if conf.method == HTTPMETHOD.POST and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        if hasattr(conf.data, UNENCODED_ORIGINAL_VALUE):
            original = getattr(conf.data, UNENCODED_ORIGINAL_VALUE)
            conf.data = type(conf.data)(conf.data.replace("\n", " "))
            setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
        else:
            conf.data = conf.data.replace("\n", " ")

        place = PLACE.SOAP if re.match(SOAP_REGEX, conf.data, re.I | re.M) else PLACE.POST

        conf.parameters[place] = conf.data
        paramDict = paramToDict(place, conf.data)

        if paramDict:
            conf.paramDict[place] = paramDict
            testableParameters = True

        conf.method = HTTPMETHOD.POST

    if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(map(lambda place: place in conf.parameters, [PLACE.GET, PLACE.POST])):
        warnMsg  = "you've provided target url without any GET "
        warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
        warnMsg += "and without providing any POST parameters "
        warnMsg += "through --data option"
        logger.warn(warnMsg)

        message = "do you want to try URI injections "
        message += "in the target url itself? [Y/n/q] "
        test = readInput(message, default="Y")

        if not test or test[0] not in ("n", "N"):
            conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR)
            kb.processUserMarks = True
        elif test[0] in ("q", "Q"):
            raise sqlmapUserQuitException

    for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data)):
        if CUSTOM_INJECTION_MARK_CHAR in (value or ""):
            if kb.processUserMarks is None:
                message = "custom injection marking character ('%s') found in option " % CUSTOM_INJECTION_MARK_CHAR
                message += "'%s'. Do you want to process it? [Y/n/q] " % {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data'}[place]
                test = readInput(message, default="Y")
                if test and test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
                else:
                    kb.processUserMarks = not test or test[0] not in ("n", "N")

            if not kb.processUserMarks:
                continue

            conf.parameters[place] = value
            conf.paramDict[place] = {}
            parts = value.split(CUSTOM_INJECTION_MARK_CHAR)

            for i in xrange(len(parts) - 1):
                conf.paramDict[place]["#%d%s" % (i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))

            if place == PLACE.URI and PLACE.GET in conf.paramDict:
                del conf.paramDict[PLACE.GET]
            elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict:
                del conf.paramDict[PLACE.POST]

            testableParameters = True

    if kb.processUserMarks:
        conf.url = conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, "")
        conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, "") if conf.data else conf.data

    # Perform checks on Cookie parameters
    if conf.cookie:
        conf.parameters[PLACE.COOKIE] = conf.cookie
        paramDict = paramToDict(PLACE.COOKIE, conf.cookie)

        if paramDict:
            conf.paramDict[PLACE.COOKIE] = paramDict
            testableParameters = True

    # Perform checks on header values
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            # Url encoding of the header values should be avoided
            # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value

            if httpHeader == PLACE.UA:
                conf.parameters[PLACE.UA] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.UA] = {PLACE.UA: headerValue}
                    testableParameters = True

            elif httpHeader == PLACE.REFERER:
                conf.parameters[PLACE.REFERER] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.REFERER] = {PLACE.REFERER: headerValue}
                    testableParameters = True

            elif httpHeader == PLACE.HOST:
                conf.parameters[PLACE.HOST] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.HOST] = {PLACE.HOST: headerValue}
                    testableParameters = True

    if not conf.parameters:
        errMsg = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent, Referer or Host header value"
        raise sqlmapGenericException, errMsg

    elif not testableParameters:
        errMsg = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg
Пример #9
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    if conf.direct:
        conf.parameters[None] = "direct connection"
        return

    __testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
        parameters = conf.parameters[PLACE.GET]
        __paramDict = paramToDict(PLACE.GET, parameters)

        if __paramDict:
            conf.paramDict[PLACE.GET] = __paramDict
            __testableParameters = True

    # Perform checks on POST parameters
    if conf.method == HTTPMETHOD.POST and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        conf.data = conf.data.replace("\n", " ")
        conf.parameters[PLACE.POST] = conf.data

        # Check if POST data is in xml syntax
        if re.match("[\n]*<(\?xml |soap\:|ns).*>", conf.data):
            conf.paramDict["POSTxml"] = True
            __paramDict = paramToDict("POSTxml", conf.data)
        else:
            __paramDict = paramToDict(PLACE.POST, conf.data)

        if __paramDict:
            conf.paramDict[PLACE.POST] = __paramDict
            __testableParameters = True

        conf.method = HTTPMETHOD.POST

    if re.search(URI_INJECTABLE_REGEX, conf.url,
                 re.I) and not conf.parameters.has_key(PLACE.GET):
        conf.url = "%s%s" % (conf.url, URI_INJECTION_MARK_CHAR)

    if URI_INJECTION_MARK_CHAR in conf.url:
        conf.parameters[PLACE.URI] = conf.url
        conf.paramDict[PLACE.URI] = {}
        parts = conf.url.split(URI_INJECTION_MARK_CHAR)
        for i in range(len(parts) - 1):
            result = str()
            for j in range(len(parts)):
                result += parts[j]
                if i == j:
                    result += URI_INJECTION_MARK_CHAR
            conf.paramDict[PLACE.URI]["#%d%s" %
                                      (i + 1,
                                       URI_INJECTION_MARK_CHAR)] = result
        conf.url = conf.url.replace(URI_INJECTION_MARK_CHAR, str())
        __testableParameters = True

    # Perform checks on Cookie parameters
    if conf.cookie:
        conf.parameters[PLACE.COOKIE] = conf.cookie
        __paramDict = paramToDict(PLACE.COOKIE, conf.cookie)

        if __paramDict:
            conf.paramDict[PLACE.COOKIE] = __paramDict
            __testableParameters = True

    # Perform checks on User-Agent header value
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            if httpHeader == PLACE.UA:
                # No need for url encoding/decoding the user agent
                conf.parameters[PLACE.UA] = urldecode(headerValue)

                condition = any([
                    not conf.testParameter,
                    intersect(conf.testParameter, USER_AGENT_ALIASES)
                ])

                if condition:
                    conf.paramDict[PLACE.UA] = {PLACE.UA: headerValue}
                    __testableParameters = True

            elif httpHeader == PLACE.REFERER:
                # No need for url encoding/decoding the referer
                conf.parameters[PLACE.REFERER] = urldecode(headerValue)

                condition = any([
                    not conf.testParameter,
                    intersect(conf.testParameter, REFERER_ALIASES)
                ])

                if condition:
                    conf.paramDict[PLACE.REFERER] = {
                        PLACE.REFERER: headerValue
                    }
                    __testableParameters = True

    if not conf.parameters:
        errMsg = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent or Referer header"
        raise sqlmapGenericException, errMsg

    elif not __testableParameters:
        errMsg = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg
Пример #10
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    if conf.direct:
        conf.parameters[None] = "direct connection"
        return

    __testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
        parameters = conf.parameters[PLACE.GET]
        __paramDict = paramToDict(PLACE.GET, parameters)

        if __paramDict:
            conf.paramDict[PLACE.GET] = __paramDict
            __testableParameters = True

    # Perform checks on POST parameters
    if conf.method == HTTPMETHOD.POST and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        conf.data = conf.data.replace("\n", " ")
        conf.parameters[PLACE.POST] = conf.data

        # Check if POST data is in xml syntax
        if re.match("[\n]*<(\?xml |soap\:|ns).*>", conf.data):
            conf.paramDict["POSTxml"] = True
            __paramDict = paramToDict("POSTxml", conf.data)
        else:
            __paramDict = paramToDict(PLACE.POST, conf.data)

        if __paramDict:
            conf.paramDict[PLACE.POST] = __paramDict
            __testableParameters = True

        conf.method = HTTPMETHOD.POST

    if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not conf.parameters.has_key(PLACE.GET):
        conf.url = "%s%s" % (conf.url, URI_INJECTION_MARK_CHAR)

    if URI_INJECTION_MARK_CHAR in conf.url:
        conf.parameters[PLACE.URI] = conf.url
        conf.paramDict[PLACE.URI] = {}
        parts = conf.url.split(URI_INJECTION_MARK_CHAR)
        for i in range(len(parts)-1):
            result = str()
            for j in range(len(parts)):
                result += parts[j]
                if i == j:
                    result += URI_INJECTION_MARK_CHAR
            conf.paramDict[PLACE.URI]["#%d%s" % (i+1, URI_INJECTION_MARK_CHAR)] = result
        conf.url = conf.url.replace(URI_INJECTION_MARK_CHAR, str())
        __testableParameters = True

    # Perform checks on Cookie parameters
    if conf.cookie:
        conf.parameters[PLACE.COOKIE] = conf.cookie
        __paramDict = paramToDict(PLACE.COOKIE, conf.cookie)

        if __paramDict:
            conf.paramDict[PLACE.COOKIE] = __paramDict
            __testableParameters = True

    # Perform checks on User-Agent header value
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            if httpHeader == PLACE.UA:
                # No need for url encoding/decoding the user agent
                conf.parameters[PLACE.UA] = urldecode(headerValue)

                condition = any([not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES)])

                if condition:
                    conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
                    __testableParameters = True

            elif httpHeader == PLACE.REFERER:
                # No need for url encoding/decoding the referer
                conf.parameters[PLACE.REFERER] = urldecode(headerValue)

                condition = any([not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES)])

                if condition:
                    conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
                    __testableParameters = True

    if not conf.parameters:
        errMsg  = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent or Referer header"
        raise sqlmapGenericException, errMsg

    elif not __testableParameters:
        errMsg  = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg
Пример #11
0
def start():
    """
    This function calls a function that performs checks on both URL
    stability and all GET, POST, Cookie and User-Agent parameters to
    check if they are dynamic and SQL injection affected
    """

    if not conf.start:
        return False

    if conf.direct:
        initTargetEnv()
        setupTargetEnv()
        action()
        return True

    if conf.url and not any([conf.forms, conf.crawlDepth]):
        kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie))

    if conf.configFile and not kb.targetUrls:
        errMsg = "you did not edit the configuration file properly, set "
        errMsg += "the target url, list of targets or google dork"
        logger.error(errMsg)
        return False

    if kb.targetUrls and len(kb.targetUrls) > 1:
        infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
        logger.info(infoMsg)

    hostCount = 0
    cookieStr = ""

    for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
        try:
            conf.url = targetUrl
            conf.method = targetMethod
            conf.data = targetData
            conf.cookie = targetCookie

            initTargetEnv()
            parseTargetUrl()

            testSqlInj = False

            if PLACE.GET in conf.parameters and not any(
                [conf.data, conf.testParameter]):
                for parameter in re.findall(
                        r"([^=]+)=([^%s]+%s?|\Z)" %
                    (conf.pDel or ";", conf.pDel or ";"),
                        conf.parameters[PLACE.GET]):
                    paramKey = (conf.hostname, conf.path, PLACE.GET,
                                parameter[0])

                    if paramKey not in kb.testedParams:
                        testSqlInj = True
                        break
            else:
                paramKey = (conf.hostname, conf.path, None, None)
                if paramKey not in kb.testedParams:
                    testSqlInj = True

            testSqlInj &= (conf.hostname, conf.path, None,
                           None) not in kb.testedParams

            if not testSqlInj:
                infoMsg = "skipping '%s'" % targetUrl
                logger.info(infoMsg)
                continue

            if conf.multipleTargets:
                hostCount += 1

                if conf.forms:
                    message = "[#%d] form:\n%s %s" % (
                        hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
                else:
                    message = "url %d:\n%s %s%s" % (
                        hostCount, conf.method or HTTPMETHOD.GET, targetUrl,
                        " (PageRank: %s)" % get_pagerank(targetUrl)
                        if conf.googleDork and conf.pageRank else "")

                if conf.cookie:
                    message += "\nCookie: %s" % conf.cookie

                if conf.data:
                    message += "\nPOST data: %s" % urlencode(
                        conf.data) if conf.data else ""

                if conf.forms:
                    if conf.method == HTTPMETHOD.GET and targetUrl.find(
                            "?") == -1:
                        continue

                    message += "\ndo you want to test this form? [Y/n/q] "
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        if conf.method == HTTPMETHOD.POST:
                            message = "Edit POST data [default: %s]%s: " % (
                                urlencode(conf.data) if conf.data else "None",
                                " (Warning: blank fields detected)"
                                if conf.data and extractRegexResult(
                                    EMPTY_FORM_FIELDS_REGEX, conf.data) else
                                "")
                            conf.data = readInput(message, default=conf.data)
                            conf.data = __randomFillBlankFields(conf.data)
                            conf.data = urldecode(
                                conf.data) if conf.data and urlencode(
                                    DEFAULT_GET_POST_DELIMITER,
                                    None) not in conf.data else conf.data

                        elif conf.method == HTTPMETHOD.GET:
                            if targetUrl.find("?") > -1:
                                firstPart = targetUrl[:targetUrl.find("?")]
                                secondPart = targetUrl[targetUrl.find("?") +
                                                       1:]
                                message = "Edit GET data [default: %s]: " % secondPart
                                test = readInput(message, default=secondPart)
                                test = __randomFillBlankFields(test)
                                conf.url = "%s?%s" % (firstPart, test)

                        parseTargetUrl()

                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                elif conf.realTest:
                    logger.info(message)
                else:
                    message += "\ndo you want to test this url? [Y/n/q]"
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        pass
                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                    infoMsg = "testing url %s" % targetUrl
                    logger.info(infoMsg)

            setupTargetEnv()

            if not checkConnection(suppressOutput=conf.forms
                                   ) or not checkString() or not checkRegexp():
                continue

            if conf.checkWaf:
                checkWaf()

            if conf.nullConnection:
                checkNullConnection()

            if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
                and (kb.injection.place is None or kb.injection.parameter is None):

                if not conf.string and not conf.regexp and PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
                    # NOTE: this is not needed anymore, leaving only to display
                    # a warning message to the user in case the page is not stable
                    checkStability()

                # Do a little prioritization reorder of a testable parameter list
                parameters = conf.parameters.keys()

                # Order of testing list (last to first)
                orderList = (PLACE.URI, PLACE.GET, PLACE.POST,
                             PLACE.CUSTOM_POST)

                for place in orderList:
                    if place in parameters:
                        parameters.remove(place)
                        parameters.insert(0, place)

                proceed = True

                for place in parameters:
                    # Test User-Agent and Referer headers only if
                    # --level >= 3
                    skip = (place == PLACE.UA and conf.level < 3)
                    skip |= (place == PLACE.REFERER and conf.level < 3)

                    # Test Host header only if
                    # --level >= 5
                    skip |= (place == PLACE.HOST and conf.level < 5)

                    # Test Cookie header only if --level >= 2
                    skip |= (place == PLACE.COOKIE and conf.level < 2)

                    skip |= (place == PLACE.UA and intersect(
                        USER_AGENT_ALIASES, conf.skip, True) not in ([], None))
                    skip |= (place == PLACE.REFERER and intersect(
                        REFERER_ALIASES, conf.skip, True) not in ([], None))
                    skip |= (place == PLACE.COOKIE and intersect(
                        PLACE.COOKIE, conf.skip, True) not in ([], None))

                    skip &= not (place == PLACE.UA and intersect(
                        USER_AGENT_ALIASES, conf.testParameter, True))
                    skip &= not (place == PLACE.REFERER and intersect(
                        REFERER_ALIASES, conf.testParameter, True))
                    skip &= not (place == PLACE.HOST and intersect(
                        HOST_ALIASES, conf.testParameter, True))

                    if skip:
                        continue

                    if not conf.paramDict.has_key(place):
                        continue

                    paramDict = conf.paramDict[place]

                    for parameter, value in paramDict.items():
                        if not proceed:
                            break

                        kb.vainRun = False
                        testSqlInj = True
                        paramKey = (conf.hostname, conf.path, place, parameter)

                        if paramKey in kb.testedParams:
                            testSqlInj = False

                            infoMsg = "skipping previously processed %s parameter '%s'" % (
                                place, parameter)
                            logger.info(infoMsg)

                        elif parameter in conf.testParameter:
                            pass

                        elif parameter == conf.rParam:
                            testSqlInj = False

                            infoMsg = "skipping randomizing %s parameter '%s'" % (
                                place, parameter)
                            logger.info(infoMsg)

                        elif parameter in conf.skip:
                            testSqlInj = False

                            infoMsg = "skipping %s parameter '%s'" % (
                                place, parameter)
                            logger.info(infoMsg)

                        # Ignore session-like parameters for --level < 4
                        elif conf.level < 4 and parameter.upper(
                        ) in IGNORE_PARAMETERS:
                            testSqlInj = False

                            infoMsg = "ignoring %s parameter '%s'" % (
                                place, parameter)
                            logger.info(infoMsg)

                        elif conf.realTest:
                            pass

                        elif PAYLOAD.TECHNIQUE.BOOLEAN in conf.tech:
                            if not checkDynParam(place, parameter, value):
                                warnMsg = "%s parameter '%s' appears to be not dynamic" % (
                                    place, parameter)
                                logger.warn(warnMsg)

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

                        kb.testedParams.add(paramKey)

                        if testSqlInj:
                            check = heuristicCheckSqlInjection(
                                place, parameter)

                            if not check:
                                if conf.smart or conf.realTest and not simpletonCheckSqlInjection(
                                        place, parameter, value):
                                    infoMsg = "skipping %s parameter '%s'" % (
                                        place, parameter)
                                    logger.info(infoMsg)
                                    continue

                            infoMsg = "testing for SQL injection on %s " % place
                            infoMsg += "parameter '%s'" % parameter
                            logger.info(infoMsg)

                            injection = checkSqlInjection(
                                place, parameter, value)
                            proceed = not kb.endDetection

                            if injection is not None and injection.place is not None:
                                kb.injections.append(injection)

                                # In case when user wants to end detection phase (Ctrl+C)
                                if not proceed:
                                    break

                                msg = "%s parameter '%s' " % (
                                    injection.place, injection.parameter)
                                msg += "is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
                                test = readInput(msg, default="N")

                                if test[0] not in ("y", "Y"):
                                    proceed = False
                                    paramKey = (conf.hostname, conf.path, None,
                                                None)
                                    kb.testedParams.add(paramKey)
                            else:
                                warnMsg = "%s parameter '%s' is not " % (
                                    place, parameter)
                                warnMsg += "injectable"
                                logger.warn(warnMsg)

            if len(kb.injections) == 0 or (len(kb.injections) == 1
                                           and kb.injections[0].place is None):
                if kb.vainRun and not conf.multipleTargets:
                    errMsg = "no parameter(s) found for testing in the provided data "
                    errMsg += "(e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')"
                    raise sqlmapNoneDataException, errMsg
                elif not conf.realTest:
                    errMsg = "all parameters appear to be not injectable."

                    if conf.level < 5 or conf.risk < 3:
                        errMsg += " Try to increase --level/--risk values "
                        errMsg += "to perform more tests."

                    if isinstance(conf.tech, list) and len(conf.tech) < 5:
                        errMsg += " Rerun without providing the option '--technique'."

                    if not conf.textOnly and kb.originalPage:
                        percent = (
                            100.0 *
                            len(getFilteredPageContent(kb.originalPage)) /
                            len(kb.originalPage))

                        if kb.dynamicParameters:
                            errMsg += " You can give it a go with the --text-only "
                            errMsg += "switch if the target page has a low percentage "
                            errMsg += "of textual content (~%.2f%% of " % percent
                            errMsg += "page content is text)."
                        elif percent < LOW_TEXT_PERCENT and not kb.errorIsNone:
                            errMsg += " Please retry with the --text-only switch "
                            errMsg += "(along with --technique=BU) as this case "
                            errMsg += "looks like a perfect candidate "
                            errMsg += "(low textual content along with inability "
                            errMsg += "of comparison engine to detect at least "
                            errMsg += "one dynamic parameter)."

                    if kb.heuristicTest:
                        errMsg += " As heuristic test turned out positive you are "
                        errMsg += "strongly advised to continue on with the tests. "
                        errMsg += "Please, consider usage of tampering scripts as "
                        errMsg += "your target might filter the queries."

                    if not conf.string and not conf.regexp:
                        errMsg += " Also, you can try to rerun by providing "
                        errMsg += "either a valid --string "
                        errMsg += "or a valid --regexp, refer to the user's "
                        errMsg += "manual for details"
                    elif conf.string:
                        errMsg += " Also, you can try to rerun by providing a "
                        errMsg += "valid --string as perhaps the string you "
                        errMsg += "have choosen does not match "
                        errMsg += "exclusively True responses"
                    elif conf.regexp:
                        errMsg += " Also, you can try to rerun by providing a "
                        errMsg += "valid --regexp as perhaps the regular "
                        errMsg += "expression that you have choosen "
                        errMsg += "does not match exclusively True responses"

                    raise sqlmapNotVulnerableException, errMsg
                else:
                    errMsg = "it seems that all parameters are not injectable"
                    raise sqlmapNotVulnerableException, errMsg
            else:
                # Flush the flag
                kb.testMode = False

                __saveToResultsFile()
                __saveToHashDB()
                __showInjections()
                __selectInjection()

            if kb.injection.place is not None and kb.injection.parameter is not None:
                if kb.testQueryCount == 0 and conf.realTest:
                    condition = False
                elif conf.multipleTargets:
                    message = "do you want to exploit this SQL injection? [Y/n] "
                    exploit = readInput(message, default="Y")

                    condition = not exploit or exploit[0] in ("y", "Y")
                else:
                    condition = True

                if condition:
                    action()

        except KeyboardInterrupt:
            if conf.multipleTargets:
                warnMsg = "user aborted in multiple target mode"
                logger.warn(warnMsg)

                message = "do you want to skip to the next target in list? [Y/n/q]"
                test = readInput(message, default="Y")

                if not test or test[0] in ("y", "Y"):
                    pass
                elif test[0] in ("n", "N"):
                    return False
                elif test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
            else:
                raise

        except sqlmapUserQuitException:
            raise

        except sqlmapSilentQuitException:
            raise

        except exceptionsTuple, e:
            e = getUnicode(e)

            if conf.multipleTargets:
                e += ", skipping to the next %s" % ("form"
                                                    if conf.forms else "url")
                logger.error(e)
            else:
                logger.critical(e)
                return False

        finally:
Пример #12
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    __testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key("GET") and conf.parameters["GET"]:
        parameters = conf.parameters["GET"]
        __paramDict = paramToDict("GET", parameters)

        if __paramDict:
            conf.paramDict["GET"] = __paramDict
            __testableParameters = True

    # Perform checks on POST parameters
    if conf.method == "POST" and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        urlDecodedData = urldecode(conf.data).replace("%", "%%")
        conf.parameters["POST"] = urlDecodedData
        __paramDict = paramToDict("POST", urlDecodedData)

        if __paramDict:
            conf.paramDict["POST"] = __paramDict
            __testableParameters = True

    # Perform checks on Cookie parameters
    if conf.cookie:
        # TODO: sure about decoding the cookie?
        #urlDecodedCookie = urldecode(conf.cookie).replace("%", "%%")
        urlDecodedCookie = conf.cookie.replace("%", "%%")
        conf.parameters["Cookie"] = urlDecodedCookie
        __paramDict = paramToDict("Cookie", urlDecodedCookie)

        if __paramDict:
            conf.paramDict["Cookie"] = __paramDict
            __testableParameters = True

    # Perform checks on User-Agent header value
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            if httpHeader == "User-Agent":
                conf.parameters["User-Agent"] = urldecode(headerValue).replace(
                    "%", "%%")

                condition = not conf.testParameter
                condition |= "User-Agent" in conf.testParameter
                condition |= "user-agent" in conf.testParameter
                condition |= "useragent" in conf.testParameter
                condition |= "ua" in conf.testParameter

                if condition:
                    conf.paramDict["User-Agent"] = {"User-Agent": headerValue}
                    __testableParameters = True

    if not conf.parameters:
        errMsg = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent header"
        raise sqlmapGenericException, errMsg

    elif not __testableParameters:
        errMsg = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg
Пример #13
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    if conf.direct:
        conf.parameters[None] = "direct connection"
        return

    __testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
        parameters = conf.parameters[PLACE.GET]
        __paramDict = paramToDict(PLACE.GET, parameters)

        if __paramDict:
            conf.paramDict[PLACE.GET] = __paramDict
            __testableParameters = True

    # Perform checks on POST parameters
    if conf.method == HTTPMETHOD.POST and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        if hasattr(conf.data, UNENCODED_ORIGINAL_VALUE):
            original = getattr(conf.data, UNENCODED_ORIGINAL_VALUE)
            conf.data = type(conf.data)(conf.data.replace("\n", " "))
            setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
        else:
            conf.data = conf.data.replace("\n", " ")

        # Check if POST data is in xml syntax
        if re.match(SOAP_REGEX, conf.data, re.I | re.M):
            place = PLACE.SOAP
        else:
            place = PLACE.POST

        conf.parameters[place] = conf.data
        __paramDict = paramToDict(place, conf.data)

        if __paramDict:
            conf.paramDict[place] = __paramDict
            __testableParameters = True

        conf.method = HTTPMETHOD.POST

    if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(map(lambda place: place in conf.parameters, [PLACE.GET, PLACE.POST])):
        warnMsg  = "you've provided target url without any GET "
        warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
        warnMsg += "and without providing any POST parameters "
        warnMsg += "through --data option"
        logger.warn(warnMsg)

        message = "do you want to try URI injections "
        message += "in the target url itself? [Y/n/q] "
        test = readInput(message, default="Y")

        if not test or test[0] in ("y", "Y"):
            conf.url = "%s%s" % (conf.url, URI_INJECTION_MARK_CHAR)
        elif test[0] in ("n", "N"):
            pass
        elif test[0] in ("q", "Q"):
            raise sqlmapUserQuitException

    if URI_INJECTION_MARK_CHAR in conf.url:
        conf.parameters[PLACE.URI] = conf.url
        conf.paramDict[PLACE.URI] = {}
        parts = conf.url.split(URI_INJECTION_MARK_CHAR)

        for i in xrange(len(parts)-1):
            result = str()

            for j in xrange(len(parts)):
                result += parts[j]

                if i == j:
                    result += URI_INJECTION_MARK_CHAR

            conf.paramDict[PLACE.URI]["#%d%s" % (i+1, URI_INJECTION_MARK_CHAR)] = result

        conf.url = conf.url.replace(URI_INJECTION_MARK_CHAR, str())
        __testableParameters = True

    # Perform checks on Cookie parameters
    if conf.cookie:
        conf.parameters[PLACE.COOKIE] = conf.cookie
        __paramDict = paramToDict(PLACE.COOKIE, conf.cookie)

        if __paramDict:
            conf.paramDict[PLACE.COOKIE] = __paramDict
            __testableParameters = True

    # Perform checks on User-Agent header value
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            if httpHeader == PLACE.UA:
                # No need for url encoding/decoding the user agent
                conf.parameters[PLACE.UA] = urldecode(headerValue)

                condition = any([not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES)])

                if condition:
                    conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
                    __testableParameters = True

            elif httpHeader == PLACE.REFERER:
                # No need for url encoding/decoding the referer
                conf.parameters[PLACE.REFERER] = urldecode(headerValue)

                condition = any([not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES)])

                if condition:
                    conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
                    __testableParameters = True

    if not conf.parameters:
        errMsg = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent or Referer header"
        raise sqlmapGenericException, errMsg

    elif not __testableParameters:
        errMsg = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg
Пример #14
0
def start():
    """
    This function calls a function that performs checks on both URL
    stability and all GET, POST, Cookie and User-Agent parameters to
    check if they are dynamic and SQL injection affected
    """

    if not conf.start:
        return False

    if conf.direct:
        initTargetEnv()
        setupTargetEnv()
        action()
        return True

    if conf.url and not conf.forms:
        kb.targetUrls.add((conf.url, conf.method, conf.data, conf.cookie))

    if conf.configFile and not kb.targetUrls:
        errMsg = "you did not edit the configuration file properly, set "
        errMsg += "the target url, list of targets or google dork"
        logger.error(errMsg)
        return False

    if kb.targetUrls and len(kb.targetUrls) > 1:
        infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
        logger.info(infoMsg)

    hostCount = 0
    cookieStr = ""
    setCookieAsInjectable = True

    for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
        try:
            conf.url = targetUrl
            conf.method = targetMethod
            conf.data = targetData
            conf.cookie = targetCookie

            initTargetEnv()
            parseTargetUrl()

            testSqlInj = False
            if PLACE.GET in conf.parameters:
                for parameter in re.findall(r"([^=]+)=[^&]+&?",
                                            conf.parameters[PLACE.GET]):
                    paramKey = (conf.hostname, conf.path, PLACE.GET, parameter)
                    if paramKey not in kb.testedParams:
                        testSqlInj = True
                        break
            else:
                paramKey = (conf.hostname, conf.path, None, None)
                if paramKey not in kb.testedParams:
                    testSqlInj = True

            testSqlInj &= (conf.hostname, conf.path, None,
                           None) not in kb.testedParams

            if not testSqlInj:
                infoMsg = "skipping '%s'" % targetUrl
                logger.info(infoMsg)
                continue

            if conf.multipleTargets:
                hostCount += 1
                if conf.forms:
                    message = "[#%d] form:\n%s %s" % (
                        hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
                else:
                    message = "url %d:\n%s %s%s" % (
                        hostCount, conf.method or HTTPMETHOD.GET, targetUrl,
                        " (PageRank: %s)" % get_pagerank(targetUrl)
                        if conf.googleDork and conf.pageRank else "")

                if conf.cookie:
                    message += "\nCookie: %s" % conf.cookie

                if conf.data:
                    message += "\nPOST data: %s" % urlencode(
                        conf.data) if conf.data else ""

                if conf.forms:
                    if conf.method == HTTPMETHOD.GET and targetUrl.find(
                            "?") == -1:
                        continue

                    message += "\ndo you want to test this form? [Y/n/q] "
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        if conf.method == HTTPMETHOD.POST:
                            message = "Edit POST data [default: %s]%s: " % (
                                urlencode(conf.data) if conf.data else "None",
                                " (Warning: blank fields detected)"
                                if conf.data and extractRegexResult(
                                    EMPTY_FORM_FIELDS_REGEX, conf.data) else
                                "")
                            conf.data = readInput(message, default=conf.data)
                            if extractRegexResult(EMPTY_FORM_FIELDS_REGEX,
                                                  conf.data):
                                message = "do you want to fill blank fields with random values? [Y/n] "
                                test = readInput(message, default="Y")
                                if not test or test[0] in ("y", "Y"):
                                    while extractRegexResult(
                                            EMPTY_FORM_FIELDS_REGEX,
                                            conf.data):
                                        item = extractRegexResult(
                                            EMPTY_FORM_FIELDS_REGEX, conf.data)
                                        if item[-1] == '&':
                                            conf.data = conf.data.replace(
                                                item, "%s%s&" %
                                                (item[:-1], randomStr()))
                                        else:
                                            conf.data = conf.data.replace(
                                                item,
                                                "%s%s" % (item, randomStr()))
                            conf.data = urldecode(conf.data)

                        elif conf.method == HTTPMETHOD.GET:
                            if conf.url.find("?") > -1:
                                firstPart = conf.url[:conf.url.find("?")]
                                secondPart = conf.url[conf.url.find("?") + 1:]
                                message = "Edit GET data [default: %s]: " % secondPart
                                test = readInput(message, default=secondPart)
                                conf.url = "%s?%s" % (firstPart, test)

                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                elif conf.realTest:
                    logger.info(message)
                else:
                    message += "\ndo you want to test this url? [Y/n/q]"
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        pass
                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                    logMsg = "testing url %s" % targetUrl
                    logger.info(logMsg)

            setupTargetEnv()

            if not checkConnection(suppressOutput=conf.forms
                                   ) or not checkString() or not checkRegexp():
                continue

            if conf.nullConnection:
                checkNullConnection()

            if not conf.dropSetCookie and conf.cj:
                for _, cookie in enumerate(conf.cj):
                    cookie = getUnicode(cookie)
                    index = cookie.index(" for ")

                    cookieStr += "%s;" % cookie[8:index]

                if cookieStr:
                    cookieStr = cookieStr[:-1]

                    if PLACE.COOKIE in conf.parameters:
                        message = "you provided an HTTP Cookie header value. "
                        message += "The target url provided its own Cookie within "
                        message += "the HTTP Set-Cookie header. Do you want to "
                        message += "continue using the HTTP Cookie values that "
                        message += "you provided? [Y/n] "
                        test = readInput(message, default="Y")

                        if not test or test[0] in ("y", "Y"):
                            setCookieAsInjectable = False

                    if setCookieAsInjectable:
                        conf.httpHeaders.append(("Cookie", cookieStr))
                        conf.parameters[PLACE.COOKIE] = cookieStr
                        __paramDict = paramToDict(PLACE.COOKIE, cookieStr)

                        if __paramDict:
                            conf.paramDict[PLACE.COOKIE] = __paramDict
                            # TODO: consider the following line in __setRequestParams()
                            # __testableParameters = True

            if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
                and (kb.injection.place is None or kb.injection.parameter is None):
                if not conf.string and not conf.regexp:
                    # NOTE: this is not needed anymore, leaving only to display
                    # a warning message to the user in case the page is not stable
                    checkStability()

                # Do a little prioritization reorder of a testable parameter list
                parameters = conf.parameters.keys()

                # Order of testing list (last to first)
                orderList = (PLACE.URI, PLACE.GET, PLACE.POST)

                for place in orderList:
                    if place in parameters:
                        parameters.remove(place)
                        parameters.insert(0, place)

                proceed = True

                for place in parameters:
                    # Test User-Agent and Referer headers only if
                    # --level >= 3
                    skip = (place == PLACE.UA and conf.level < 3)
                    skip |= (place == PLACE.REFERER and conf.level < 3)

                    # Test Cookie header only if --level >= 2
                    skip |= (place == PLACE.COOKIE and conf.level < 2)

                    skip &= not (place == PLACE.UA and intersect(
                        USER_AGENT_ALIASES, conf.testParameter))
                    skip &= not (place == PLACE.REFERER and intersect(
                        REFERER_ALIASES, conf.testParameter))

                    if skip:
                        continue

                    if not conf.paramDict.has_key(place):
                        continue

                    paramDict = conf.paramDict[place]
                    for parameter, value in paramDict.items():
                        if not proceed:
                            break

                        testSqlInj = True

                        paramKey = (conf.hostname, conf.path, place, parameter)

                        if paramKey in kb.testedParams:
                            testSqlInj = False

                            infoMsg = "skipping previously processed %s parameter '%s'" % (
                                place, parameter)
                            logger.info(infoMsg)

                        # Avoid dinamicity test if the user provided the
                        # parameter manually
                        elif parameter in conf.testParameter or conf.realTest:
                            pass

                        elif not checkDynParam(place, parameter, value):
                            warnMsg = "%s parameter '%s' is not dynamic" % (
                                place, parameter)
                            logger.warn(warnMsg)

                        else:
                            logMsg = "%s parameter '%s' is dynamic" % (
                                place, parameter)
                            logger.info(logMsg)

                        kb.testedParams.add(paramKey)

                        if testSqlInj:
                            check = heuristicCheckSqlInjection(
                                place, parameter)
                            if not check and conf.realTest and\
                              not simpletonCheckSqlInjection(place, parameter, value):
                                continue

                            logMsg = "testing sql injection on %s " % place
                            logMsg += "parameter '%s'" % parameter
                            logger.info(logMsg)

                            injection = checkSqlInjection(
                                place, parameter, value)
                            proceed = not kb.endDetection

                            if injection is not None and injection.place is not None:
                                kb.injections.append(injection)

                                # In case when user wants to end detection phase (Ctrl+C)
                                if not proceed:
                                    break

                                msg = "%s parameter '%s' " % (
                                    injection.place, injection.parameter)
                                msg += "is vulnerable. Do you want to keep testing the others? [y/N] "
                                test = readInput(msg, default="N")

                                if test[0] in ("n", "N"):
                                    proceed = False
                                    paramKey = (conf.hostname, conf.path, None,
                                                None)
                                    kb.testedParams.add(paramKey)
                            else:
                                warnMsg = "%s parameter '%s' is not " % (
                                    place, parameter)
                                warnMsg += "injectable"
                                logger.warn(warnMsg)

            if len(kb.injections) == 0 or (len(kb.injections) == 1
                                           and kb.injections[0].place is None):
                if not conf.realTest:
                    errMsg = "all parameters are not injectable, try to "
                    errMsg += "increase --level/--risk values to perform "
                    errMsg += "more tests."

                    if isinstance(conf.tech, list) and len(conf.tech) > 0:
                        errMsg += " Rerun without providing the --technique switch."

                    if not conf.textOnly and kb.originalPage:
                        percent = (
                            100.0 *
                            len(getFilteredPageContent(kb.originalPage)) /
                            len(kb.originalPage))
                        errMsg += " Give it a go with the --text-only switch "
                        errMsg += "if the target page has a low percentage of "
                        errMsg += "textual content (~%.2f%% of " % percent
                        errMsg += "page content is text)"

                    raise sqlmapNotVulnerableException, errMsg
                else:
                    errMsg = "it seems that all parameters are not injectable"
                    raise sqlmapNotVulnerableException, errMsg
            else:
                # Flush the flag
                kb.testMode = False

                __saveToSessionFile()
                __showInjections()
                __selectInjection()

            if kb.injection.place is not None and kb.injection.parameter is not None:
                if kb.testQueryCount == 0 and conf.realTest:
                    condition = False
                elif conf.multipleTargets:
                    message = "do you want to exploit this SQL injection? [Y/n] "
                    exploit = readInput(message, default="Y")

                    condition = not exploit or exploit[0] in ("y", "Y")
                else:
                    condition = True

                if condition:
                    action()

        except KeyboardInterrupt:
            if conf.multipleTargets:
                warnMsg = "user aborted in multiple target mode"
                logger.warn(warnMsg)

                message = "do you want to skip to the next target in list? [Y/n/q]"
                test = readInput(message, default="Y")

                if not test or test[0] in ("y", "Y"):
                    pass
                elif test[0] in ("n", "N"):
                    return False
                elif test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
            else:
                raise

        except sqlmapUserQuitException:
            raise

        except sqlmapSilentQuitException:
            raise

        except exceptionsTuple, e:
            e = getUnicode(e)

            if conf.multipleTargets:
                e += ", skipping to the next %s" % ("form"
                                                    if conf.forms else "url")
                logger.error(e)
            else:
                logger.critical(e)
                return False

        finally:
Пример #15
0
def start():
    """
    This function calls a function that performs checks on both URL
    stability and all GET, POST, Cookie and User-Agent parameters to
    check if they are dynamic and SQL injection affected
    """

    if not conf.start:
        return False

    if conf.direct:
        initTargetEnv()
        setupTargetEnv()
        action()
        return True

    if conf.url and not conf.forms:
        kb.targetUrls.add(( conf.url, conf.method, conf.data, conf.cookie ))

    if conf.configFile and not kb.targetUrls:
        errMsg  = "you did not edit the configuration file properly, set "
        errMsg += "the target url, list of targets or google dork"
        logger.error(errMsg)
        return False

    if kb.targetUrls and len(kb.targetUrls) > 1:
        infoMsg = "sqlmap got a total of %d targets" % len(kb.targetUrls)
        logger.info(infoMsg)

    hostCount             = 0
    cookieStr             = ""
    setCookieAsInjectable = True

    for targetUrl, targetMethod, targetData, targetCookie in kb.targetUrls:
        try:
            conf.url    = targetUrl
            conf.method = targetMethod
            conf.data   = targetData
            conf.cookie = targetCookie

            initTargetEnv()
            parseTargetUrl()

            testSqlInj = False
            if PLACE.GET in conf.parameters:
                for parameter in re.findall(r"([^=]+)=[^&]+&?", conf.parameters[PLACE.GET]):
                    paramKey = (conf.hostname, conf.path, PLACE.GET, parameter)
                    if paramKey not in kb.testedParams:
                        testSqlInj = True
                        break
            else:
                paramKey = (conf.hostname, conf.path, None, None)
                if paramKey not in kb.testedParams:
                    testSqlInj = True

            testSqlInj &= (conf.hostname, conf.path, None, None) not in kb.testedParams

            if not testSqlInj:
                infoMsg = "skipping '%s'" % targetUrl
                logger.info(infoMsg)
                continue

            if conf.multipleTargets:
                hostCount += 1
                if conf.forms:
                    message = "[#%d] form:\n%s %s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl)
                else:
                    message = "url %d:\n%s %s%s" % (hostCount, conf.method or HTTPMETHOD.GET, targetUrl,  " (PageRank: %s)" % get_pagerank(targetUrl) if conf.googleDork and conf.pageRank else "")

                if conf.cookie:
                    message += "\nCookie: %s" % conf.cookie

                if conf.data:
                    message += "\nPOST data: %s" % urlencode(conf.data) if conf.data else ""

                if conf.forms:
                    if conf.method == HTTPMETHOD.GET and targetUrl.find("?") == -1:
                        continue

                    message += "\ndo you want to test this form? [Y/n/q] "
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        if conf.method == HTTPMETHOD.POST:
                            message = "Edit POST data [default: %s]%s: " % (urlencode(conf.data) if conf.data else "None", " (Warning: blank fields detected)" if conf.data and extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data) else "")
                            conf.data = readInput(message, default=conf.data)
                            if extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
                                message = "do you want to fill blank fields with random values? [Y/n] "
                                test = readInput(message, default="Y")
                                if not test or test[0] in ("y", "Y"):
                                    while extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data):
                                        item = extractRegexResult(EMPTY_FORM_FIELDS_REGEX, conf.data)
                                        if item[-1] == '&':
                                            conf.data = conf.data.replace(item, "%s%s&" % (item[:-1], randomStr()))
                                        else:
                                            conf.data = conf.data.replace(item, "%s%s" % (item, randomStr()))
                            conf.data = urldecode(conf.data)

                        elif conf.method == HTTPMETHOD.GET:
                            if conf.url.find("?") > -1:
                                firstPart = conf.url[:conf.url.find("?")]
                                secondPart = conf.url[conf.url.find("?")+1:]
                                message = "Edit GET data [default: %s]: " % secondPart
                                test = readInput(message, default=secondPart)
                                conf.url = "%s?%s" % (firstPart, test)

                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                elif conf.realTest:
                    logger.info(message)
                else:
                    message += "\ndo you want to test this url? [Y/n/q]"
                    test = readInput(message, default="Y")

                    if not test or test[0] in ("y", "Y"):
                        pass
                    elif test[0] in ("n", "N"):
                        continue
                    elif test[0] in ("q", "Q"):
                        break

                    logMsg = "testing url %s" % targetUrl
                    logger.info(logMsg)

            setupTargetEnv()

            if not checkConnection(suppressOutput=conf.forms) or not checkString() or not checkRegexp():
                continue

            if conf.nullConnection:
                checkNullConnection()

            if not conf.dropSetCookie and conf.cj:
                for _, cookie in enumerate(conf.cj):
                    cookie = getUnicode(cookie)
                    index  = cookie.index(" for ")

                    cookieStr += "%s;" % cookie[8:index]

                if cookieStr:
                    cookieStr = cookieStr[:-1]

                    if PLACE.COOKIE in conf.parameters:
                        message  = "you provided an HTTP Cookie header value. "
                        message += "The target url provided its own Cookie within "
                        message += "the HTTP Set-Cookie header. Do you want to "
                        message += "continue using the HTTP Cookie values that "
                        message += "you provided? [Y/n] "
                        test = readInput(message, default="Y")

                        if not test or test[0] in ("y", "Y"):
                            setCookieAsInjectable = False

                    if setCookieAsInjectable:
                        conf.httpHeaders.append(("Cookie", cookieStr))
                        conf.parameters[PLACE.COOKIE] = cookieStr
                        __paramDict = paramToDict(PLACE.COOKIE, cookieStr)

                        if __paramDict:
                            conf.paramDict[PLACE.COOKIE] = __paramDict
                            # TODO: consider the following line in __setRequestParams()
                            # __testableParameters = True

            if (len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None)) \
                and (kb.injection.place is None or kb.injection.parameter is None):
                if not conf.string and not conf.regexp:
                    # NOTE: this is not needed anymore, leaving only to display
                    # a warning message to the user in case the page is not stable
                    checkStability()

                # Do a little prioritization reorder of a testable parameter list 
                parameters = conf.parameters.keys()

                # Order of testing list (last to first)
                orderList = (PLACE.URI, PLACE.GET, PLACE.POST)

                for place in orderList:
                    if place in parameters:
                        parameters.remove(place)
                        parameters.insert(0, place)

                proceed = True

                for place in parameters:
                    # Test User-Agent and Referer headers only if
                    # --level >= 3
                    skip = (place == PLACE.UA and conf.level < 3)
                    skip |= (place == PLACE.REFERER and conf.level < 3)

                    # Test Cookie header only if --level >= 2
                    skip |= (place == PLACE.COOKIE and conf.level < 2)

                    skip &= not (place == PLACE.UA and intersect(USER_AGENT_ALIASES, conf.testParameter))
                    skip &= not (place == PLACE.REFERER and intersect(REFERER_ALIASES, conf.testParameter))

                    if skip:
                        continue

                    if not conf.paramDict.has_key(place):
                        continue

                    paramDict = conf.paramDict[place]
                    for parameter, value in paramDict.items():
                        if not proceed:
                            break

                        testSqlInj = True

                        paramKey = (conf.hostname, conf.path, place, parameter)

                        if paramKey in kb.testedParams:
                            testSqlInj = False

                            infoMsg = "skipping previously processed %s parameter '%s'" % (place, parameter)
                            logger.info(infoMsg)

                        # Avoid dinamicity test if the user provided the
                        # parameter manually
                        elif parameter in conf.testParameter or conf.realTest:
                            pass

                        elif not checkDynParam(place, parameter, value):
                            warnMsg = "%s parameter '%s' is not dynamic" % (place, parameter)
                            logger.warn(warnMsg)

                        else:
                            logMsg = "%s parameter '%s' is dynamic" % (place, parameter)
                            logger.info(logMsg)

                        kb.testedParams.add(paramKey)

                        if testSqlInj:
                            check = heuristicCheckSqlInjection(place, parameter)
                            if not check and conf.realTest and\
                              not simpletonCheckSqlInjection(place, parameter, value):
                                continue

                            logMsg = "testing sql injection on %s " % place
                            logMsg += "parameter '%s'" % parameter
                            logger.info(logMsg)

                            injection = checkSqlInjection(place, parameter, value)
                            proceed = not kb.endDetection

                            if injection is not None and injection.place is not None:
                                kb.injections.append(injection)

                                # In case when user wants to end detection phase (Ctrl+C)
                                if not proceed:
                                    break

                                msg = "%s parameter '%s' " % (injection.place, injection.parameter)
                                msg += "is vulnerable. Do you want to keep testing the others? [y/N] "
                                test = readInput(msg, default="N")

                                if test[0] in ("n", "N"):
                                    proceed = False
                                    paramKey = (conf.hostname, conf.path, None, None)
                                    kb.testedParams.add(paramKey)
                            else:
                                warnMsg = "%s parameter '%s' is not " % (place, parameter)
                                warnMsg += "injectable"
                                logger.warn(warnMsg)

            if len(kb.injections) == 0 or (len(kb.injections) == 1 and kb.injections[0].place is None):
                if not conf.realTest:
                    errMsg = "all parameters are not injectable, try to "
                    errMsg += "increase --level/--risk values to perform "
                    errMsg += "more tests."

                    if isinstance(conf.tech, list) and len(conf.tech) > 0:
                        errMsg += " Rerun without providing the --technique switch."

                    if not conf.textOnly and kb.originalPage:
                        percent = (100.0 * len(getFilteredPageContent(kb.originalPage)) / len(kb.originalPage))
                        errMsg += " Give it a go with the --text-only switch "
                        errMsg += "if the target page has a low percentage of "
                        errMsg += "textual content (~%.2f%% of " % percent
                        errMsg += "page content is text)"

                    raise sqlmapNotVulnerableException, errMsg
                else:
                    errMsg = "it seems that all parameters are not injectable"
                    raise sqlmapNotVulnerableException, errMsg
            else:
                # Flush the flag
                kb.testMode = False

                __saveToSessionFile()
                __showInjections()
                __selectInjection()

            if kb.injection.place is not None and kb.injection.parameter is not None:
                if kb.testQueryCount == 0 and conf.realTest:
                    condition = False
                elif conf.multipleTargets:
                    message = "do you want to exploit this SQL injection? [Y/n] "
                    exploit = readInput(message, default="Y")

                    condition = not exploit or exploit[0] in ("y", "Y")
                else:
                    condition = True

                if condition:
                    action()

        except KeyboardInterrupt:
            if conf.multipleTargets:
                warnMsg = "user aborted in multiple target mode"
                logger.warn(warnMsg)

                message = "do you want to skip to the next target in list? [Y/n/q]"
                test = readInput(message, default="Y")

                if not test or test[0] in ("y", "Y"):
                    pass
                elif test[0] in ("n", "N"):
                    return False
                elif test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
            else:
                raise

        except sqlmapUserQuitException:
            raise

        except sqlmapSilentQuitException:
            raise

        except exceptionsTuple, e:
            e = getUnicode(e)

            if conf.multipleTargets:
                e += ", skipping to the next %s" % ("form" if conf.forms else "url")
                logger.error(e)
            else:
                logger.critical(e)
                return False

        finally:
Пример #16
0
def __setRequestParams():
    """
    Check and set the parameters and perform checks on 'data' option for
    HTTP method POST.
    """

    if conf.direct:
        conf.parameters[None] = "direct connection"
        return

    testableParameters = False

    # Perform checks on GET parameters
    if conf.parameters.has_key(PLACE.GET) and conf.parameters[PLACE.GET]:
        parameters = conf.parameters[PLACE.GET]
        paramDict = paramToDict(PLACE.GET, parameters)

        if paramDict:
            conf.paramDict[PLACE.GET] = paramDict
            testableParameters = True

    # Perform checks on POST parameters
    if conf.method == HTTPMETHOD.POST and not conf.data:
        errMsg = "HTTP POST method depends on HTTP data value to be posted"
        raise sqlmapSyntaxException, errMsg

    if conf.data:
        if hasattr(conf.data, UNENCODED_ORIGINAL_VALUE):
            original = getattr(conf.data, UNENCODED_ORIGINAL_VALUE)
            conf.data = type(conf.data)(conf.data.replace("\n", " "))
            setattr(conf.data, UNENCODED_ORIGINAL_VALUE, original)
        else:
            conf.data = conf.data.replace("\n", " ")

        if re.match(SOAP_REGEX, conf.data, re.I | re.M):
            place = PLACE.SOAP
        else:
            place = PLACE.POST

        conf.parameters[place] = conf.data
        paramDict = paramToDict(place, conf.data)

        if paramDict:
            conf.paramDict[place] = paramDict
            testableParameters = True

        conf.method = HTTPMETHOD.POST

    if re.search(URI_INJECTABLE_REGEX, conf.url, re.I) and not any(map(lambda place: place in conf.parameters, [PLACE.GET, PLACE.POST])):
        warnMsg  = "you've provided target url without any GET "
        warnMsg += "parameters (e.g. www.site.com/article.php?id=1) "
        warnMsg += "and without providing any POST parameters "
        warnMsg += "through --data option"
        logger.warn(warnMsg)

        message = "do you want to try URI injections "
        message += "in the target url itself? [Y/n/q] "
        test = readInput(message, default="Y")

        if not test or test[0] not in ("n", "N"):
            conf.url = "%s%s" % (conf.url, CUSTOM_INJECTION_MARK_CHAR)
            kb.processUserMarks = True
        elif test[0] in ("q", "Q"):
            raise sqlmapUserQuitException

    for place, value in ((PLACE.URI, conf.url), (PLACE.CUSTOM_POST, conf.data)):
        if CUSTOM_INJECTION_MARK_CHAR in (value or ""):
            if kb.processUserMarks is None:
                message = "custom injection mark ('%s') found in " % CUSTOM_INJECTION_MARK_CHAR
                message += "'%s'. Do you want to process it? [Y/n/q] " % {PLACE.URI: '-u', PLACE.CUSTOM_POST: '--data'}[place]
                test = readInput(message, default="Y")
                if test and test[0] in ("q", "Q"):
                    raise sqlmapUserQuitException
                else:
                    kb.processUserMarks = not test or test[0] not in ("n", "N")

            if not kb.processUserMarks:
                continue

            conf.parameters[place] = value
            conf.paramDict[place] = {}
            parts = value.split(CUSTOM_INJECTION_MARK_CHAR)

            for i in xrange(len(parts) - 1):
                conf.paramDict[place]["#%d%s" % (i + 1, CUSTOM_INJECTION_MARK_CHAR)] = "".join("%s%s" % (parts[j], CUSTOM_INJECTION_MARK_CHAR if i == j else "") for j in xrange(len(parts)))

            if place == PLACE.URI and PLACE.GET in conf.paramDict:
                del conf.paramDict[PLACE.GET]
            elif place == PLACE.CUSTOM_POST and PLACE.POST in conf.paramDict:
                del conf.paramDict[PLACE.POST]

            testableParameters = True

    if kb.processUserMarks:
        conf.url = conf.url.replace(CUSTOM_INJECTION_MARK_CHAR, "")
        conf.data = conf.data.replace(CUSTOM_INJECTION_MARK_CHAR, "") if conf.data else conf.data

    # Perform checks on Cookie parameters
    if conf.cookie:
        conf.parameters[PLACE.COOKIE] = conf.cookie
        paramDict = paramToDict(PLACE.COOKIE, conf.cookie)

        if paramDict:
            conf.paramDict[PLACE.COOKIE] = paramDict
            testableParameters = True

    # Perform checks on header values
    if conf.httpHeaders:
        for httpHeader, headerValue in conf.httpHeaders:
            # Url encoding of the header values should be avoided
            # Reference: http://stackoverflow.com/questions/5085904/is-ok-to-urlencode-the-value-in-headerlocation-value

            if httpHeader == PLACE.UA:
                conf.parameters[PLACE.UA] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, USER_AGENT_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.UA] = { PLACE.UA: headerValue }
                    testableParameters = True

            elif httpHeader == PLACE.REFERER:
                conf.parameters[PLACE.REFERER] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, REFERER_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.REFERER] = { PLACE.REFERER: headerValue }
                    testableParameters = True

            elif httpHeader == PLACE.HOST:
                conf.parameters[PLACE.HOST] = urldecode(headerValue)

                condition = any((not conf.testParameter, intersect(conf.testParameter, HOST_ALIASES)))

                if condition:
                    conf.paramDict[PLACE.HOST] = { PLACE.HOST: headerValue }
                    testableParameters = True

    if not conf.parameters:
        errMsg = "you did not provide any GET, POST and Cookie "
        errMsg += "parameter, neither an User-Agent, Referer or Host header value"
        raise sqlmapGenericException, errMsg

    elif not testableParameters:
        errMsg = "all testable parameters you provided are not present "
        errMsg += "within the GET, POST and Cookie parameters"
        raise sqlmapGenericException, errMsg