Exemplo n.º 1
0
    def delay_for(self, delay, original_wait_time):
        """
        Sends a request to the remote end that "should" delay the response in
        `delay` seconds.

        :param original_wait_time: The time that it takes to perform the
                                   request without adding any delays.

        :return: (True, response) if there was a delay. In order to make
                 things right we first send some requests to measure the
                 original wait time.
        """
        delay_str = self.delay_obj.get_string_for_delay(delay)
        mutant = self.mutant.copy()
        mutant.set_token_value(delay_str)

        # Set the upper and lower bounds
        delta = original_wait_time * self.DELTA_PERCENT

        upper_bound = (delay * 2) + original_wait_time + delta
        lower_bound = original_wait_time + delay - delta

        # Send, it is important to notice that we don't use the cache
        # to avoid any interference
        try:
            response = self.uri_opener.send_mutant(mutant, cache=False, timeout=upper_bound * 10)
        except HTTPRequestException, hre:
            # NOTE: In some cases where the remote web server timeouts we reach
            #       this code section. The handling of that situation is done
            #       with the new_no_content_resp() below.
            return False, new_no_content_resp(self.mutant.get_uri())
Exemplo n.º 2
0
    def default_open(self, req):
        """
        If blacklisted return an empty response, else return None, which means
        that this handler was unable to handle the request and the next one
        needs to be called. With this we want to indicate that the keepalive
        handler will be called.
        """
        if self._blacklist_urls is None:
            # This happens only during the first HTTP request
            self._read_configuration_settings()

        uri = req.url_object

        if not self._is_blacklisted(uri):
            # This means: I don't know how to handle this, call the next opener
            return None

        msg = ('%s was included in the HTTP request blacklist, the scan'
               ' engine is NOT sending the HTTP request and is instead'
               ' returning an empty response to the plugin.')
        om.out.debug(msg % uri)

        # Return a 204 response
        no_content = new_no_content_resp(req.url_object)
        no_content = http_response_to_httplib(no_content)
        return no_content
Exemplo n.º 3
0
    def delay_for(self, delay, original_wait_time):
        """
        Sends a request to the remote end that "should" delay the response in
        `delay` seconds.

        :param original_wait_time: The time that it takes to perform the
                                   request without adding any delays.

        :return: (True, response) if there was a delay. In order to make
                 things right we first send some requests to measure the
                 original wait time.
        """
        delay_str = self.delay_obj.get_string_for_delay(delay)
        mutant = self.mutant.copy()
        mutant.set_token_value(delay_str)

        # Set the upper and lower bounds
        delta = original_wait_time * self.DELTA_PERCENT

        upper_bound = (delay * 2) + original_wait_time + delta
        lower_bound = original_wait_time + delay - delta

        # Send, it is important to notice that we don't use the cache
        # to avoid any interference
        try:
            response = self.uri_opener.send_mutant(mutant,
                                                   cache=False,
                                                   timeout=upper_bound * 10)
        except HTTPRequestException, hre:
            # NOTE: In some cases where the remote web server timeouts we reach
            #       this code section. The handling of that situation is done
            #       with the new_no_content_resp() below.
            return False, new_no_content_resp(self.mutant.get_uri())
Exemplo n.º 4
0
    def handle_url_error(self, uri, http_exception):
        """
        Handle UrlError exceptions raised when requests are made.
        Subclasses should redefine this method for a more refined
        behavior and must respect the return value format.

        :param http_exception: HTTPRequestException exception instance

        :return: A tuple containing:
            * re_raise: Boolean value that indicates the caller if the original
                        exception should be re-raised after this error handling
                        method.

            * result: The result to be returned to the caller. This only makes
                      sense if re_raise is False.
        """
        no_content_resp = new_no_content_resp(uri, add_id=True)

        msg = ('The %s plugin got an error while requesting "%s".'
               ' Exception: "%s".'
               ' Generated 204 "No Content" response (id:%s)')
        args = (self.get_name(), uri, http_exception, no_content_resp.id)
        om.out.error(msg % args)

        return False, no_content_resp
Exemplo n.º 5
0
    def handle_url_error(self, uri, http_exception):
        """
        Handle UrlError exceptions raised when requests are made.
        Subclasses should redefine this method for a more refined
        behavior and must respect the return value format.

        :param http_exception: HTTPRequestException exception instance

        :return: A tuple containing:
            * re_raise: Boolean value that indicates the caller if the original
                        exception should be re-raised after this error handling
                        method.

            * result: The result to be returned to the caller. This only makes
                      sense if re_raise is False.
        """
        no_content_resp = new_no_content_resp(uri, add_id=True)
        
        msg = ('The %s plugin got an error while requesting "%s".'
               ' Exception: "%s".'
               ' Generated 204 "No Content" response (id:%s)')
        args = (self.get_name(),
                uri,
                http_exception,
                no_content_resp.id)
        om.out.error(msg % args)

        return False, no_content_resp
Exemplo n.º 6
0
    def default_open(self, req):
        """
        If blacklisted return an empty response, else return None, which means
        that this handler was unable to handle the request and the next one
        needs to be called. With this we want to indicate that the keepalive
        handler will be called.
        """
        if self._is_blacklisted(req.url_object):
            nncr = new_no_content_resp(req.url_object)
            addinfo_inst = http_response_to_httplib(nncr)

            return addinfo_inst

        # This means: I don't know how to handle this, call the next opener        
        return None
Exemplo n.º 7
0
    def default_open(self, req):
        """
        If blacklisted return an empty response, else return None, which means
        that this handler was unable to handle the request and the next one
        needs to be called. With this we want to indicate that the keepalive
        handler will be called.
        """
        if self._is_blacklisted(req.url_object):
            nncr = new_no_content_resp(req.url_object)
            addinfo_inst = http_response_to_httplib(nncr)
            
            return addinfo_inst

        # This means: I don't know how to handle this, call the next opener        
        return None
Exemplo n.º 8
0
    def delay_for(self, delay, original_wait_time, grep, reverse=False):
        """
        Sends a request to the remote end that "should" delay the response in
        `delay` seconds.

        :param delay: The delay object
        :param original_wait_time: The time that it takes to perform the
                                   request without adding any delays.
        :param grep: Should the framework grep the HTTP response sent for testing?
        :param reverse: Should we reverse the delay_str before sending it?

        :return: (True, response) if there was a delay. In order to make
                 things right we first send some requests to measure the
                 original wait time.
        """
        delay_str = self.delay_obj.get_string_for_delay(delay)
        delay_str = delay_str if not reverse else delay_str[::-1]

        mutant = self.mutant.copy()
        mutant.set_token_value(delay_str)

        # Set the upper and lower bounds
        delta = original_wait_time * self.DELTA_PERCENT

        # Upper bound is the highest number we'll wait for a response, it
        # doesn't mean that it is the highest delay that might happen on
        # the application.
        #
        # So, for example if the application logic (for some reason) runs
        # our payload three times, and we send:
        #
        #   sleep(10)
        #
        # The delay will be of 30 seconds, but we don't want to wait all
        # that time (using high timeouts for HTTP requests is *very* bad when
        # scanning slow apps).
        #
        # We just wait until `upper_bound` is reached
        upper_bound = original_wait_time + delta + delay * 2

        # The lower_bound is the lowest number of seconds we require for this
        # HTTP response to be considered "delayed".
        #
        # I tried with different variations of this, the first one included
        # original_wait_time and delta, but that failed in this scenario:
        #
        #   * RTT (which defines original_wait_time) is inaccurately high: 3 seconds
        #     instead of 1 second which was the expected result. This could be
        #     because of outliers in the measurement
        #
        #           https://github.com/andresriancho/w3af/issues/16902
        #
        #   * lower_bound is then set to original_wait_time - delta + delay
        #
        #   * The payload is sent and the response is delayed for 4 seconds
        #
        #   * The delay_for method yields false because of the bad RTT
        lower_bound = delay

        # Send, it is important to notice that we don't use the cache
        # to avoid any interference
        try:
            response = self.uri_opener.send_mutant(
                mutant,
                grep=grep,
                cache=False,
                timeout=upper_bound,
                debugging_id=self.get_debugging_id())
        except HTTPRequestException:
            #
            # We reach this part of the code when the server response times out
            #
            # Note that in the timeout parameter of send_mutant we're sending
            # the upper bound, so we reach this code if that upper bound is
            # exceeded. That can be because of:
            #
            #   * Network delays unrelated to our payload
            #
            #   * Our payload having an effect on the server, delaying the
            #     response so much that it triggers the timeout
            #
            args = (id(self), upper_bound, lower_bound, delay, upper_bound)
            msg = (u'[id: %s] HTTP response delay was %.2f.'
                   u' (lower, expected, upper): %.2f, %.2f, %.2f.')
            out.debug(msg % args)

            return True, new_no_content_resp(self.mutant.get_uri())

        # We reach this code when the HTTP timeout wasn't reached, but we might still
        # have a working delay. This is most of the cases I've seen.
        current_response_wait_time = response.get_wait_time()
        args = (id(self), current_response_wait_time, lower_bound, delay,
                upper_bound)
        msg = (u'[id: %s] HTTP response delay was %.2f.'
               u' (lower, expected, upper): %.2f, %.2f, %.2f.')
        out.debug(msg % args)

        if current_response_wait_time > lower_bound:
            return True, response

        return False, response
Exemplo n.º 9
0
    def delay_for(self, delay, original_wait_time, grep, reverse=False):
        """
        Sends a request to the remote end that "should" delay the response in
        `delay` seconds.

        :param delay: The delay object
        :param original_wait_time: The time that it takes to perform the
                                   request without adding any delays.
        :param grep: Should the framework grep the HTTP response sent for testing?
        :param reverse: Should we reverse the delay_str before sending it?

        :return: (True, response) if there was a delay. In order to make
                 things right we first send some requests to measure the
                 original wait time.
        """
        delay_str = self.delay_obj.get_string_for_delay(delay)
        delay_str = delay_str if not reverse else delay_str[::-1]

        mutant = self.mutant.copy()
        mutant.set_token_value(delay_str)

        # Set the upper and lower bounds
        delta = original_wait_time * self.DELTA_PERCENT

        # Upper bound is the highest number we'll wait for a response, it
        # doesn't mean that it is the highest delay that might happen on
        # the application.
        #
        # So, for example if the application logic (for some reason) runs
        # our payload three times, and we send:
        #
        #   sleep(10)
        #
        # The delay will be of 30 seconds, but we don't want to wait all
        # that time (using high timeouts for HTTP requests is *very* bad when
        # scanning slow apps).
        #
        # We just wait until `upper_bound` is reached
        upper_bound = original_wait_time + delta + delay * 2

        # The lower_bound is the lowest number of seconds we require for this
        # HTTP response to be considered "delayed".
        #
        # I tried with different variations of this, the first one included
        # original_wait_time and delta, but that failed in this scenario:
        #
        #   * RTT (which defines original_wait_time) is inaccurately high: 3 seconds
        #     instead of 1 second which was the expected result. This could be
        #     because of outliers in the measurement
        #
        #           https://github.com/andresriancho/w3af/issues/16902
        #
        #   * lower_bound is then set to original_wait_time - delta + delay
        #
        #   * The payload is sent and the response is delayed for 4 seconds
        #
        #   * The delay_for method yields false because of the bad RTT
        lower_bound = delay

        # Send, it is important to notice that we don't use the cache
        # to avoid any interference
        try:
            response = self.uri_opener.send_mutant(mutant,
                                                   grep=grep,
                                                   cache=False,
                                                   timeout=upper_bound,
                                                   debugging_id=self.get_debugging_id())
        except HTTPRequestException:
            #
            # We reach this part of the code when the server response times out
            #
            # Note that in the timeout parameter of send_mutant we're sending
            # the upper bound, so we reach this code if that upper bound is
            # exceeded. That can be because of:
            #
            #   * Network delays unrelated to our payload
            #
            #   * Our payload having an effect on the server, delaying the
            #     response so much that it triggers the timeout
            #
            args = (id(self), upper_bound, lower_bound, delay, upper_bound)
            msg = (u'[id: %s] HTTP response delay was %.2f.'
                   u' (lower, expected, upper): %.2f, %.2f, %.2f.')
            out.debug(msg % args)

            return True, new_no_content_resp(self.mutant.get_uri())

        # We reach this code when the HTTP timeout wasn't reached, but we might still
        # have a working delay. This is most of the cases I've seen.
        current_response_wait_time = response.get_wait_time()
        args = (id(self), current_response_wait_time, lower_bound, delay, upper_bound)
        msg = (u'[id: %s] HTTP response delay was %.2f.'
               u' (lower, expected, upper): %.2f, %.2f, %.2f.')
        out.debug(msg % args)

        if current_response_wait_time > lower_bound:
            return True, response

        return False, response