예제 #1
0
    def __init__(self, targets=None, payloads=None, num_threads=10,
                 time_per_url=10, request_timeout=10, proxy_list=None,
                 hadoop_reporting=False, depreciated=None):
        """ Initialize this WebFuzzer object.

        targets             list of Target objects. Default [].
        payloads            list of Payload objects. Default [].
        num_threads         Number of threads/processes to launch as an int.
                                Default 10.
        time_per_url        Time in seconds to spend on each Target.
                                Default 10.
        request_timeout     Time in seconds to wait for a connection before
                                giving up. Default 10.
        proxy_list          list of proxies specified as dicts. Default empty.
        hadoop_reporting    Output info for hadoop if True. Default False.
        payload_groups      UNUSED. list of groups of Payload objects.
                                Default [].
        """
        super(WebFuzzer, self).__init__()
        # do this because we may need to create more MassRequest objects in
        #  checks (like bsqli), needs to be configured the same
        self.mreq_config_dict = {"num_threads": num_threads,
                                 "time_per_url": time_per_url,
                                 "request_timeout": request_timeout,
                                 "proxy_list": proxy_list or [{}],
                                 "hadoop_reporting": hadoop_reporting}
        self.mreq = MassRequest(**self.mreq_config_dict)
        self.targets = targets or []
        self.payloads = payloads or []
        self.mxi_check = MXICheck()
        self.osci_check = OSCICheck()
        self.sqli_check = SQLICheck()
        self.trav_check = TravCheck()
        self.xpathi_check = XPathICheck()
        self.xss_check = XSSCheck()
        self.hadoop_reporting = hadoop_reporting
        if self.hadoop_reporting:
            logger.info("Hadoop reporting set in fuzzer")
        self.fuzzy_targets = []
예제 #2
0
class WebFuzzer(iFuzzer):
    """ Fuzzy a generated list of Targets.

    Generates lists of targets with associated payloads and runs them against
    the target systems.
    """

    def __init__(self, targets=None, payloads=None, num_threads=10,
                 time_per_url=10, request_timeout=10, proxy_list=None,
                 hadoop_reporting=False, depreciated=None):
        """ Initialize this WebFuzzer object.

        targets             list of Target objects. Default [].
        payloads            list of Payload objects. Default [].
        num_threads         Number of threads/processes to launch as an int.
                                Default 10.
        time_per_url        Time in seconds to spend on each Target.
                                Default 10.
        request_timeout     Time in seconds to wait for a connection before
                                giving up. Default 10.
        proxy_list          list of proxies specified as dicts. Default empty.
        hadoop_reporting    Output info for hadoop if True. Default False.
        payload_groups      UNUSED. list of groups of Payload objects.
                                Default [].
        """
        super(WebFuzzer, self).__init__()
        # do this because we may need to create more MassRequest objects in
        #  checks (like bsqli), needs to be configured the same
        self.mreq_config_dict = {"num_threads": num_threads,
                                 "time_per_url": time_per_url,
                                 "request_timeout": request_timeout,
                                 "proxy_list": proxy_list or [{}],
                                 "hadoop_reporting": hadoop_reporting}
        self.mreq = MassRequest(**self.mreq_config_dict)
        self.targets = targets or []
        self.payloads = payloads or []
        self.mxi_check = MXICheck()
        self.osci_check = OSCICheck()
        self.sqli_check = SQLICheck()
        self.trav_check = TravCheck()
        self.xpathi_check = XPathICheck()
        self.xss_check = XSSCheck()
        self.hadoop_reporting = hadoop_reporting
        if self.hadoop_reporting:
            logger.info("Hadoop reporting set in fuzzer")
        self.fuzzy_targets = []

    def __generate_fuzzy_target_get(self, target):
        """ Associate fuzzing data for GET requests with the target.

        target  Target object.
        returns list of Targets with fuzzing data.
        """
        url = target.url
        parsed_url = urlparse(url)
        parsed_url_query = parsed_url.query
        url_q_dic = parse_qs(parsed_url_query)
        fuzzy_targets = []
        for query_param, _ in url_q_dic.iteritems():
            for payload in self.payloads:
                fuzzy_url = (self.replace_param_value(url, query_param,
                                                      str(payload)))
                fuzzy_target = FuzzyTarget(fuzzy_url, url, query_param, GET,
                                           payload=payload)
                logger.debug("GET fuzzy_target type: %s", type(fuzzy_target))
                fuzzy_targets.append(fuzzy_target)
        return fuzzy_targets

    def __generate_fuzzy_target_post(self, target):
        """ Associate fuzzing data for POST requests with the target.

        target  Target object.
        returns list of Targets with fuzzing data.
        """
        url = target.url
        fuzzy_targets = []
        post_keys = target.data.keys()
        for key in post_keys:
            data_copy = target.data.copy()
            for payload in self.payloads:
                data_copy[key] = str(payload)
                fuzzy_target = FuzzyTarget(url, url, key, POST,
                                           data=data_copy.copy(),
                                           payload=payload,
                                           unfuzzed_data=target.data)
                logger.debug("POST fuzzy_target type: %s", type(fuzzy_target))
                fuzzy_targets.append(fuzzy_target)
        return fuzzy_targets

    def generate_fuzzy_targets(self):
        """ Associate fuzzing data with the targets. """
        if self.hadoop_reporting:
            logger.info("Generating fuzzy targets")
        # If no targets then raise an exception
        if len(self.targets) == 0:
            raise ValueError("Targets list must not be empty!")
        self.fuzzy_targets = []
        for target in self.targets:
            logger.debug("input target type: %s", type(target))
            if target.ttype == "get":
                fuzzy_target_list = self.__generate_fuzzy_target_get(target)
                self.fuzzy_targets += fuzzy_target_list
            if target.ttype == "post":
                fuzzy_target_list = self.__generate_fuzzy_target_post(target)
                self.fuzzy_targets += fuzzy_target_list
        if not self.fuzzy_targets:
            raise ValueError("fuzzy_targets is empty. No targets generated"
                             " from: %s",
                             ','.join([str(x) for x in self.targets]))
        return self.fuzzy_targets

    def fuzz(self):
        """ Fuzz all the targets and return the results.

        returns     list of Result objects.
        """
        self.mreq.request_targets(self.fuzzy_targets)
        results = []
        for target, response in self.mreq.results:
            #FIXME: Clarify with alex: !not yet multithreaded, should it be?
            logger.debug("target type: %s", type(target))
            try:
                result = self.analyze_response(target, response)
            except (TypeError, AttributeError) as err:
                # If request failed and str is returned instead of Response obj
                #  could save some cycles here not analyzing response
                if self.hadoop_reporting:
                    logger.info("Marking target as failed due to exception: ", exc_info=True)
                logger.debug(err)
                try:
                    result = self._make_failed_result(target, "__PNK_FAILED_RESPONSE")
                except TypeError as err:
                    logger.debug("Failed to make a failed result for %s.", target)
                    logger.warn(err.message, exc_info=True)
                    continue
            results.append(result)
        return results

    def _make_failed_result(self, target, result_dic=None):
        """ Macro to make a failed Result. """
        if not result_dic:
            result_dic = {}
            for check_type in target.payload.check_type_list:
                result_dic[check_type] = False
        return Result(target, result_dic)

    def analyze_response(self, ftarget, response):
        """ Analyze the results of the request and return the info gathered.

        ftargeet    FuzzyTarget object.
        response    requests.Response object.

        returns     Result object.
        raises      TypeError or AttributeError when non requests.Response is given as response.

        """
        #FIXME: Clarify with alex: !function is a mess, response is of type
        #    text or non-text, trying to read blah blah
        result_dic = {}
        check_type_list = ftarget.payload.check_type_list
        if self.hadoop_reporting:
            logger.info("Response is of type %s for target %s.",
                        response.__class__.__name__, ftarget)
        worthy = parse_worthy(response,
                              hadoop_reporting=self.hadoop_reporting)
        if worthy:
            logger.info("FuzzyTarget %s looks worth checking for vulnerabilities.",
                        ftarget)
        else:
            logger.info("Response deemed non-parse-worthy. Setting all checks "
                        "in result_dic to False for %s", ftarget)
            return self._make_failed_result(ftarget)
        result_dic = self._run_checks(response, result_dic, check_type_list)
        return Result(ftarget, result_dic)

    def _run_checks(self, response, result_dic, check_type_list):
        """ Check reponse output with the specified checkers.

        response        requests.Response object.
        result_dic      dict with checker names as keys.
        check_type_list list of names of checkers to check with.
        """
        #FIXME: Make me work on a dict of checker IDs and methods to call
        #   instead of an if statement cascade
        if "mxi" in check_type_list:
            mxi_result = self.mxi_check.check(response.text)
            result_dic["mxi"] = mxi_result
        if "sqli" in check_type_list:
            sqli_result = self.sqli_check.check(response.text)
            result_dic["sqli"] = sqli_result
        if "xpathi" in check_type_list:
            xpathi_result = self.xpathi_check.check(response.text)
            result_dic["xpathi"] = xpathi_result
        if "trav" in check_type_list:
            trav_result = self.trav_check.check(response.text)
            result_dic["trav"] = trav_result
        if "osci" in check_type_list:
            osci_result = self.osci_check.check(response.text)
            result_dic["osci"] = osci_result
        if "xss" in check_type_list:
            xss_result = self.xss_check.check(response.text)
            result_dic["xss"] = xss_result
        return result_dic