Example #1
0
    def check_is_open_web_socket(self, web_socket_url, web_socket_version):
        """
        Note that this method only makes sense if called in a loop with the
        other check_* methods.

        :param web_socket_url: The URL of the web socket
        :param web_socket_version: The protocol version

        :return: True if the web socket is open:
                    * Any Origin can connect
                    * No cookies required for authentication
                    * No basic auth required for authentication
        """
        upgrade_request = build_ws_upgrade_request(web_socket_url,
                                                   web_socket_version=web_socket_version,
                                                   origin=self.W3AF_ORIGIN)
        upgrade_response = self._uri_opener.send_mutant(upgrade_request,
                                                        cookies=False,
                                                        use_basic_auth=False)

        if not is_successful_upgrade(upgrade_response):
            return False

        msg = ('An HTML5 WebSocket which allows connections from any origin'
               ' without authentication was found at "%s"')
        msg %= web_socket_url

        v = Vuln.from_fr('Open WebSocket', msg, severity.LOW,
                         upgrade_response.id, self.get_name(), upgrade_request)
        self.kb_append_uniq(self, 'websocket_hijacking', v)
        return True
Example #2
0
    def check_is_restricted_by_origin_with_match_bug(self, web_socket_url,
                                                     web_socket_version):
        """
        Note that this method only makes sense if called in a loop with the
        other check_* methods.

        :param web_socket_url: The URL of the web socket
        :param web_socket_version: The protocol version

        :return: True if the web socket checks the origin for connections but
                 there is a bug in the matching process
        """
        #
        # Keep in mind that we get here only if the websocket is NOT an open
        # (accepts any origin) socket. So we're in a situation where the socket
        # is either verifying by Origin+Cookies, Origin+Basic Auth or just
        # Origin.
        #
        # We want to check for the "just Origin" now, with a twist, we're
        # checking if there is a mistake in the Origin domain match process
        #
        # This is the trick:
        origin_domain = web_socket_url.get_domain()
        origin_domain += '.%s' % self.W3AF_DOMAIN

        for scheme in {'http', 'https'}:
            origin = '%s://%s' % (scheme, origin_domain)
            upgrade_request = build_ws_upgrade_request(web_socket_url,
                                                       web_socket_version=web_socket_version,
                                                       origin=origin)
            upgrade_response = self._uri_opener.send_mutant(upgrade_request,
                                                            cookies=False,
                                                            use_basic_auth=False)

            if not is_successful_upgrade(upgrade_response):
                continue

            msg = ('An HTML5 WebSocket which restricts connections based on the'
                   ' Origin header was found to be vulnerable because of an'
                   ' incorrect matching algorithm. The "%s" Origin was allowed'
                   ' to connect to "%s".')
            msg %= (origin_domain, web_socket_url)

            v = Vuln.from_fr('Insecure WebSocket Origin filter', msg,
                             severity.MEDIUM, upgrade_response.id,
                             self.get_name(), upgrade_request)
            self.kb_append_uniq(self, 'websocket_hijacking', v)
            return True

        return False
Example #3
0
    def check_is_restricted_by_origin(self, web_socket_url, web_socket_version):
        """
        Note that this method only makes sense if called in a loop with the
        other check_* methods.

        :param web_socket_url: The URL of the web socket
        :param web_socket_version: The protocol version

        :return: True if the web socket checks the origin for connections:
                    * Only the same origin can connect
                    * Send any cookie/basic auth known to the scanner
        """
        #
        # Keep in mind that we get here only if the websocket is NOT an open
        # (accepts any origin) socket. So we're in a situation where the socket
        # is either verifying by Origin+Cookies, Origin+Basic Auth or just
        # Origin.
        #
        # We want to check for the "just Origin" now
        #
        origin_domain = web_socket_url.get_domain()

        for scheme in {'http', 'https'}:
            origin = '%s://%s' % (scheme, origin_domain)
            upgrade_request = build_ws_upgrade_request(web_socket_url,
                                                       web_socket_version=web_socket_version,
                                                       origin=origin)
            upgrade_response = self._uri_opener.send_mutant(upgrade_request,
                                                            cookies=False,
                                                            use_basic_auth=False)

            if not is_successful_upgrade(upgrade_response):
                continue

            msg = ('An HTML5 WebSocket which allows connections only when the'
                   ' origin is set to "%s" was found at "%s"')
            msg %= (origin_domain, web_socket_url)

            v = Vuln.from_fr('Origin restricted WebSocket', msg, severity.LOW,
                             upgrade_response.id, self.get_name(),
                             upgrade_request)
            self.kb_append_uniq(self, 'websocket_hijacking', v)
            return True

        return False
Example #4
0
    def check_need_cookie_origin_not_restricted(self, web_socket_url,
                                                web_socket_version):
        """
        Note that this method only makes sense if called in a loop with the
        other check_* methods.

        :param web_socket_url: The URL of the web socket
        :param web_socket_version: The protocol version

        :return: True if the web socket does NOT check the origin for
                 connections but DOES require cookies to connect
        """
        #
        # Keep in mind that we get here only if:
        #   * The websocket is NOT an open (accepts any origin) socket
        #   * The websocket is NOT verifying by Origin
        #
        # So we're in one of these cases:
        #   * The websocket authenticates by cookie
        #   * The websocket authenticates by basic auth
        #
        # We want to check for the "authenticates by cookie"
        #
        upgrade_request = build_ws_upgrade_request(web_socket_url,
                                                   web_socket_version=web_socket_version,
                                                   origin=self.W3AF_ORIGIN)
        upgrade_response = self._uri_opener.send_mutant(upgrade_request,
                                                        # Note the True here!
                                                        cookies=True,
                                                        use_basic_auth=False)

        if not is_successful_upgrade(upgrade_response):
            return False

        msg = 'Cross-Site WebSocket Hijacking has been found at "%s"'
        msg %= web_socket_url

        v = Vuln.from_fr('Websockets CSRF vulnerability', msg,
                         severity.HIGH, upgrade_response.id,
                         self.get_name(), upgrade_request)
        self.kb_append_uniq(self, 'websocket_hijacking', v)
        return True