Exemple #1
0
    def run(self, info):

        # Parse original URL
        m_url = info.url
        m_url_parts = info.parsed_url

        # If file is a javascript, css or image, do not run
        if info.parsed_url.extension[1:] in (
                'css', 'js', 'jpeg', 'jpg', 'png', 'gif',
                'svg') or not m_url_parts.extension:
            Logger.log_more_verbose("Skipping URL: %s" % m_url)
            return

        Logger.log_more_verbose("Bruteforcing URL: %s" % m_url)

        #
        # Load wordlist for changing directories
        #
        # COMMON
        m_urls = make_url_changing_folder_name(m_url_parts)

        # Generates the error page
        m_error_response = get_error_page(m_url)

        # Create the matching analyzer
        try:
            m_store_info = MatchingAnalyzer(m_error_response.raw_data,
                                            min_ratio=0.65)
        except ValueError, e:
            Logger.log_error(
                "There is not information for analyze when creating the matcher: '%s'"
                % e)
            return
Exemple #2
0
    def recv_info(self, info):

        # Parse original URL
        m_url = info.url
        m_url_parts = info.parsed_url

        # If file is a javascript, css or image, do not run
        if info.parsed_url.extension[1:] in ('css', 'js', 'jpeg', 'jpg', 'png', 'gif', 'svg') or not m_url_parts.extension:
            Logger.log_more_verbose("Skipping URL: %s" % m_url)
            return

        Logger.log_more_verbose("Bruteforcing URL: %s" % m_url)

        #
        # Load wordlist for changing directories
        #
        # COMMON
        m_urls = make_url_changing_folder_name(m_url_parts)

        # Generates the error page
        m_error_response = get_error_page(m_url)

        # Create the matching analyzer
        try:
            m_store_info = MatchingAnalyzer(m_error_response.raw_data, min_ratio=0.65)
        except ValueError, e:
            Logger.log_error("There is not information for analyze when creating the matcher: '%s'" % e)
            return
Exemple #3
0
    def __detect_wordpress_installation(self, url, wordpress_urls):
        """
        Try to detect a wordpress instalation in the current path.

        :param url: URL where try to find the WordPress installation.
        :type url: str

        :param wordpress_urls: string with wordlist name with WordPress URLs.
        :type wordpress_urls: str

        :return: True if wordpress installation found. False otherwise.
        :rtype: bool
        """
        Logger.log_more_verbose(
            "Detecting Wordpress instalation in URI: '%s'." % url)
        total_urls = 0
        urls_found = 0

        error_page = get_error_page(url).raw_data

        for u in WordListLoader.get_wordlist(wordpress_urls):
            total_urls += 1
            tmp_url = urljoin(url, u)

            r = HTTP.get_url(tmp_url, use_cache=False)
            if r.status == "200":

                # Try to detect non-default error pages
                ratio = get_diff_ratio(r.raw_response, error_page)
                if ratio < 0.35:
                    urls_found += 1

            discard_data(r)

        # If Oks > 85% continue
        if (urls_found / float(total_urls)) < 0.85:

            # If all fails, make another last test
            url_wp_admin = urljoin(url, "wp-admin/")

            try:
                p = HTTP.get_url(url_wp_admin,
                                 use_cache=False,
                                 allow_redirects=False)
                if p:
                    discard_data(p)
            except Exception, e:
                return False

            if p.status == "302" and "wp-login.php?redirect_to=" in p.headers.get(
                    "Location", ""):
                return True
            else:
                return False
Exemple #4
0
    def __detect_wordpress_installation(self, url, wordpress_urls):
        """
        Try to detect a wordpress instalation in the current path.

        :param url: URL where try to find the WordPress installation.
        :type url: str

        :param wordpress_urls: string with wordlist name with WordPress URLs.
        :type wordpress_urls: str

        :return: True if wordpress installation found. False otherwise.
        :rtype: bool
        """
        Logger.log_more_verbose("Detecting Wordpress instalation in URI: '%s'." % url)
        total_urls = 0
        urls_found = 0

        error_page = get_error_page(url).raw_data

        for u in WordListLoader.get_wordlist(wordpress_urls):
            total_urls += 1
            tmp_url = urljoin(url, u)

            r = HTTP.get_url(tmp_url, use_cache=False)
            if r.status == "200":

                # Try to detect non-default error pages
                ratio = get_diff_ratio(r.raw_response, error_page)
                if ratio < 0.35:
                    urls_found += 1

            discard_data(r)

        # If Oks > 85% continue
        if (urls_found / float(total_urls)) < 0.85:

            # If all fails, make another last test
            url_wp_admin = urljoin(url, "wp-admin/")

            try:
                p = HTTP.get_url(url_wp_admin, use_cache=False, allow_redirects=False)
                if p:
                    discard_data(p)
            except Exception, e:
                return False

            if p.status == "302" and "wp-login.php?redirect_to=" in p.headers.get("Location", ""):
                return True
            else:
                return False
Exemple #5
0
            for l_wo in l_loaded_wordlist:
                try:
                    l_wo = l_wo[1:] if l_wo.startswith("/") else l_wo
                    tmp_u = urljoin(m_url, l_wo)
                except ValueError, e:
                    Logger.log_error(
                        "Failed to parse key, from wordlist, '%s'" % tmp_u)
                    continue

                m_urls_update(tmp_u)

        Logger.log_verbose("Loaded %s URLs to test." % len(urls))

        # Generates the error page
        error_response = get_error_page(m_url)

        # Create the matching analyzer
        try:
            store_info = MatchingAnalyzer(error_response.raw_data,
                                          min_ratio=0.65)
        except ValueError, e:
            Logger.log_error(
                "There is not information for analyze when creating the matcher: '%s'"
                % e)
            return

        # Create the partial funs
        _f = partial(process_url, severity_vectors['predictables'],
                     get_http_method(m_url), store_info, self.update_status,
                     len(urls))
Exemple #6
0
    def __find_plugins(self, url, plugins_wordlist, update_func):
        """
        Try to find available plugins

        :param url: base URL to test.
        :type url: str

        :param plugins_wordlist: path to wordlist with plugins lists.
        :type plugins_wordlist: str

        :param update_func: function to update plugin status.
        :type update_func: function

        :return: list of lists as format:
                 list([PLUGIN_NAME, PLUGIN_URL, PLUGIN_INSTALLED_VERSION, PLUGIN_LAST_VERSION, [CVE1, CVE2...]])
        :type: list(list())
        """
        results = []
        urls_to_test = {
            "readme.txt": r"(Stable tag:[\svV]*)([0-9\.]+)",
            "README.txt": r"(Stable tag:[\svV]*)([0-9\.]+)",
        }

        # Generates the error page
        error_response = get_error_page(url).raw_data

        # Load plugins info
        plugins = []
        plugins_append = plugins.append
        with open(plugins_wordlist, "rU") as f:
            for x in f:
                plugins_append(x.replace("\n", ""))

        # Calculate sizes
        total_plugins = len(plugins)

        # Load CSV info
        csv_info = csv.reader(plugins)

        # Process the URLs
        for i, plugin_row in enumerate(csv_info):

            # Plugin properties
            plugin_URI = plugin_row[0]
            plugin_name = plugin_row[1]
            plugin_last_version = plugin_row[2]
            plugin_CVEs = [] if plugin_row[3] == "" else plugin_row[3].split("|")

            # Update status
            update_func((float(i) * 100.0) / float(total_plugins))

            # Make plugin URL
            partial_plugin_url = "%s/%s" % (url, "wp-content/plugins/%s" % plugin_URI)

            # Test each URL with possible plugin version info
            for target, regex in urls_to_test.iteritems():

                plugin_url = "%s/%s" % (partial_plugin_url, target)

                # Try to get plugin
                p = None
                try:
                    p = HTTP.get_url(plugin_url, use_cache=False)
                    if p:
                        discard_data(p)
                except Exception, e:
                    Logger.log_error_more_verbose("Error while download: '%s': %s" % (plugin_url, str(e)))
                    continue

                plugin_installed_version = None

                if p.status == "403":  # Installed, but inaccesible
                    plugin_installed_version = "Unknown"

                elif p.status == "200":

                    # Check if page is and non-generic not found page with 404 code
                    if get_diff_ratio(error_response, p.raw_response) < 0.52:

                        # Find the version
                        tmp_version = re.search(regex, p.raw_response)

                        if tmp_version is not None:
                            plugin_installed_version = tmp_version.group(2)

                # Store info
                if plugin_installed_version is not None:
                    Logger.log("Discovered plugin: '%s (installed version: %s)' (latest version: %s)" %
                                (plugin_name, plugin_installed_version, plugin_last_version))
                    results.append([
                        plugin_name,
                        plugin_url,
                        plugin_installed_version,
                        plugin_last_version,
                        plugin_CVEs
                    ])

                    # Plugin found -> not more URL test for this plugin
                    break
            l_loaded_wordlist = WordListLoader.get_wordlist_as_list(l_w)

            for l_wo in l_loaded_wordlist:
                try:
                    l_wo = l_wo[1:] if l_wo.startswith("/") else l_wo
                    tmp_u = urljoin(m_url, l_wo)
                except ValueError, e:
                    Logger.log_error("Failed to parse key, from wordlist, '%s'" % tmp_u)
                    continue

                urls.add(tmp_u)

        Logger.log_verbose("Loaded %s URLs to test." % len(urls))

        # Generates the error page
        error_response = get_error_page(m_url)
        
        # Create the matching analyzer
        try:
            store_info = MatchingAnalyzer(error_response.raw_data, min_ratio=0.0)
        except ValueError, e:
            Logger.log_error("There is not information for analyze when creating the matcher: '%s'" % e)
            return

        # Create the partial funs
        _f = partial(process_url,
                     4,
                     get_http_method(m_url),
                     store_info,
                     self.update_status,
                     len(urls))
Exemple #8
0
    def __find_plugins(self, url, plugins_wordlist, update_func):
        """
        Try to find available plugins

        :param url: base URL to test.
        :type url: str

        :param plugins_wordlist: path to wordlist with plugins lists.
        :type plugins_wordlist: str

        :param update_func: function to update plugin status.
        :type update_func: function

        :return: list of lists as format:
                 list([PLUGIN_NAME, PLUGIN_URL, PLUGIN_INSTALLED_VERSION, PLUGIN_LAST_VERSION, [CVE1, CVE2...]])
        :type: list(list())
        """
        results = []
        urls_to_test = {
            "readme.txt": r"(Stable tag:[\svV]*)([0-9\.]+)",
            "README.txt": r"(Stable tag:[\svV]*)([0-9\.]+)",
        }

        # Generates the error page
        error_response = get_error_page(url).raw_data

        # Load plugins info
        plugins = []
        plugins_append = plugins.append
        with open(plugins_wordlist, "rU") as f:
            for x in f:
                plugins_append(x.replace("\n", ""))

        # Calculate sizes
        total_plugins = len(plugins)

        # Load CSV info
        csv_info = csv.reader(plugins)

        # Process the URLs
        for i, plugin_row in enumerate(csv_info):

            # Plugin properties
            plugin_URI = plugin_row[0]
            plugin_name = plugin_row[1]
            plugin_last_version = plugin_row[2]
            plugin_CVEs = [] if plugin_row[3] == "" else plugin_row[3].split(
                "|")

            # Update status
            update_func((float(i) * 100.0) / float(total_plugins))

            # Make plugin URL
            partial_plugin_url = "%s/%s" % (url, "wp-content/plugins/%s" %
                                            plugin_URI)

            # Test each URL with possible plugin version info
            for target, regex in urls_to_test.iteritems():

                plugin_url = "%s/%s" % (partial_plugin_url, target)

                # Try to get plugin
                p = None
                try:
                    p = HTTP.get_url(plugin_url, use_cache=False)
                    if p:
                        discard_data(p)
                except Exception, e:
                    Logger.log_error_more_verbose(
                        "Error while download: '%s': %s" %
                        (plugin_url, str(e)))
                    continue

                plugin_installed_version = None

                if p.status == "403":  # Installed, but inaccesible
                    plugin_installed_version = "Unknown"

                elif p.status == "200":

                    # Check if page is and non-generic not found page with 404 code
                    if get_diff_ratio(error_response, p.raw_response) < 0.52:

                        # Find the version
                        tmp_version = re.search(regex, p.raw_response)

                        if tmp_version is not None:
                            plugin_installed_version = tmp_version.group(2)

                # Store info
                if plugin_installed_version is not None:
                    Logger.log(
                        "Discovered plugin: '%s (installed version: %s)' (latest version: %s)"
                        % (plugin_name, plugin_installed_version,
                           plugin_last_version))
                    results.append([
                        plugin_name, plugin_url, plugin_installed_version,
                        plugin_last_version, plugin_CVEs
                    ])

                    # Plugin found -> not more URL test for this plugin
                    break