Example #1
0
    def _generic_vhosts(self, fuzzable_request):
        """
        Test some generic virtual hosts, only do this once.
        """
        # Get some responses to compare later
        base_url = fuzzable_request.get_url().base_url()
        original_response = self._uri_opener.GET(base_url, cache=True)
        orig_resp_body = original_response.get_body()

        non_existent_response = self._get_non_exist(fuzzable_request)
        nonexist_resp_body = non_existent_response.get_body()

        res = []
        vhosts = self._get_common_virtualhosts(base_url)

        for vhost, vhost_response in self._send_in_threads(base_url, vhosts):
            vhost_resp_body = vhost_response.get_body()

            # If they are *really* different (not just different by some chars)
            if fuzzy_not_equal(vhost_resp_body, orig_resp_body, 0.35) and fuzzy_not_equal(
                vhost_resp_body, nonexist_resp_body, 0.35
            ):
                res.append((vhost, vhost_response.id))

        return res
Example #2
0
    def _generic_vhosts(self, fuzzable_request):
        """
        Test some generic virtual hosts, only do this once.
        """
        # Get some responses to compare later
        base_url = fuzzable_request.get_url().base_url()
        original_response = self._uri_opener.GET(base_url, cache=True)
        orig_resp_body = original_response.get_body()

        non_existent_response = self._get_non_exist(fuzzable_request)
        non_existent_resp_body = non_existent_response.get_body()

        res = []
        vhosts = self._get_common_virtual_hosts(base_url)

        for vhost, vhost_response in self._send_in_threads(base_url, vhosts):
            vhost_resp_body = vhost_response.get_body()

            # If they are *really* different (not just different by some chars)
            if not fuzzy_not_equal(vhost_resp_body, orig_resp_body, 0.35):
                continue

            if not fuzzy_not_equal(vhost_resp_body, non_existent_resp_body, 0.35):
                continue

            res.append((vhost, vhost_response.id))

        return res
Example #3
0
    def _check_user_dir(self, mutated_url, user, user_desc, user_tag,
                        non_existent):
        """
        Perform the request and compare with non_existent

        :see _create_tests: For parameter description
        :return: The HTTP response id if the mutated_url is a web user
                 directory, None otherwise.
        """
        resp = self.http_get_and_parse(mutated_url)
        
        path = mutated_url.get_path()
        response_body = resp.get_body().replace(path, '')

        if fuzzy_not_equal(response_body, non_existent, 0.7):

            # Avoid duplicates
            known_users = [u['user'] for u in kb.kb.get('user_dir', 'users')]
            if user in known_users:
                return

            # Save the finding to the KB
            desc = 'An operating system user directory was found at: "%s"'
            desc = desc % resp.get_url()

            i = Info('Web user home directory', desc, resp.id, self.get_name())
            i.set_url(resp.get_url())
            i['user'] = user
            i['user_desc'] = user_desc
            i['user_tag'] = user_tag

            self.kb_append_uniq(self, 'users', i)

            # Analyze if we can get more information from this finding
            self._analyze_finding(i)
Example #4
0
    def _test_DNS(self, original_response, dns_wildcard_url):
        """
        Check if http://www.domain.tld/ == http://domain.tld/
        """
        headers = Headers([('Host', dns_wildcard_url.get_domain())])
        try:
            modified_response = self._uri_opener.GET(
                original_response.get_url(), cache=True, headers=headers)
        except BaseFrameworkException:
            return
        else:
            if fuzzy_not_equal(modified_response.get_body(),
                               original_response.get_body(), 0.35):
                desc = 'The target site has NO DNS wildcard, and the contents' \
                       ' of "%s" differ from the contents of "%s".'
                desc = desc % (dns_wildcard_url, original_response.get_url())

                i = Info('No DNS wildcard', desc, modified_response.id,
                         self.get_name())
                i.set_url(dns_wildcard_url)

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())
            else:
                desc = 'The target site has a DNS wildcard configuration, the' \
                       ' contents of "%s" are equal to the ones of "%s".'
                desc = desc % (dns_wildcard_url, original_response.get_url())

                i = Info('DNS wildcard', desc, modified_response.id,
                         self.get_name())
                i.set_url(original_response.get_url())

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())
Example #5
0
    def _do_request(self, mutated_url, user):
        """
        Perform the request and compare.

        :return: The HTTP response id if the mutated_url is a web user
                 directory, None otherwise.
        """
        response = self._uri_opener.GET(mutated_url, cache=True,
                                        headers=self._headers)
        
        path = mutated_url.get_path()
        response_body = response.get_body().replace(path, '')

        if fuzzy_not_equal(response_body, self._non_existent, 0.7):

            # Avoid duplicates
            if user not in [u['user'] for u in kb.kb.get('user_dir', 'users')]:
                desc = 'A user directory was found at: %s'
                desc = desc % response.get_url()
                
                i = Info('Web user home directory', desc, response.id,
                         self.get_name())
                i.set_url(response.get_url())
                i['user'] = user

                kb.kb.append(self, 'users', i)

                for fr in self._create_fuzzable_requests(response):
                    self.output_queue.put(fr)

            return response.id

        return None
    def _analyze_generic_vhosts(self, original_response):
        """
        Test some generic virtual hosts.
        """
        orig_resp_body = original_response.get_body()

        non_existent_response = self._get_non_exist()
        nonexist_resp_body = non_existent_response.get_body()

        res = []
        vhosts = self._get_common_virtualhosts()

        for vhost, vhost_response in self._send_in_threads(vhosts):
            vhost_resp_body = vhost_response.get_body()

            # If they are *really* different (not just different by some chars)
            if fuzzy_not_equal(vhost_resp_body, orig_resp_body, 0.35) and \
            fuzzy_not_equal(vhost_resp_body, nonexist_resp_body, 0.35):
                res.append((vhost, vhost_response.id))

        return res
Example #7
0
    def _check_existance(self, original_response, mutant):
        """
        Actually check if the mutated URL exists.

        :return: None, all important data is put() to self.output_queue
        """
        response = self._uri_opener.send_mutant(mutant)

        if not is_404(response) and \
        fuzzy_not_equal(original_response.body, response.body, 0.85):

            # Verify against something random
            rand = rand_alpha()
            rand_mutant = mutant.copy()
            rand_mutant.set_mod_value(rand)
            rand_response = self._uri_opener.send_mutant(rand_mutant)

            if fuzzy_not_equal(response.body, rand_response.body, 0.85):

                for fr in self._create_fuzzable_requests(response):
                    self.output_queue.put(fr)
Example #8
0
    def _check_existance(self, original_response, mutant):
        """
        Actually check if the mutated URL exists.

        :return: None, all important data is put() to self.output_queue
        """
        response = self._uri_opener.send_mutant(mutant)
        
        if not is_404(response) and \
        fuzzy_not_equal(original_response.body, response.body, 0.85):
            
            # Verify against something random
            rand = rand_alpha()
            rand_mutant = mutant.copy()
            rand_mutant.set_mod_value(rand)
            rand_response = self._uri_opener.send_mutant(rand_mutant)
            
            if fuzzy_not_equal(response.body, rand_response.body, 0.85):
                
                for fr in self._create_fuzzable_requests(response):
                    self.output_queue.put(fr)
Example #9
0
    def _do_request(self, fuzzable_request, original_resp, headers):
        """
        Send the request.

        :param fuzzable_request: The modified fuzzable request
        :param original_resp: The response for the original request that was
                              sent.
        """
        response = self._uri_opener.GET(fuzzable_request.get_uri(),
                                        cache=True,
                                        headers=headers)

        add = False

        if not is_404(response):
            # We have different cases:
            #    - If the URLs are different, then there is nothing to think
            #      about, we simply found something new!
            if response.get_url() != original_resp.get_url():
                add = True

            #    - If the content type changed, then there is no doubt that
            #      we've found something new!
            elif response.doc_type != original_resp.doc_type:
                add = True

            #    - If we changed the query string parameters, we have to check
            #      the content
            elif fuzzy_not_equal(response.get_clear_text_body(),
                                 original_resp.get_clear_text_body(), 0.8):
                # In this case what might happen is that the number we changed
                # is "out of range" and when requesting that it will trigger an
                # error in the web application, or show us a non-interesting
                # response that holds no content.
                #
                # We choose to return these to the core because they might help
                # with the code coverage efforts. Think about something like:
                #     foo.aspx?id=OUT_OF_RANGE&foo=inject_here
                # vs.
                #     foo.aspx?id=IN_RANGE&foo=inject_here
                #
                # This relates to the EXPECTED_URLS in test_digit_sum.py
                add = True

        if add:
            for fr in self._create_fuzzable_requests(response):
                self.output_queue.put(fr)
Example #10
0
    def _do_request(self, fuzzable_request, original_resp, headers):
        """
        Send the request.

        :param fuzzable_request: The modified fuzzable request
        :param original_resp: The response for the original request that was
                              sent.
        """
        response = self._uri_opener.GET(fuzzable_request.get_uri(), cache=True, headers=headers)

        add = False

        if not is_404(response):
            # We have different cases:
            #    - If the URLs are different, then there is nothing to think
            #      about, we simply found something new!
            if response.get_url() != original_resp.get_url():
                add = True

            #    - If the content type changed, then there is no doubt that
            #      we've found something new!
            elif response.doc_type != original_resp.doc_type:
                add = True

            #    - If we changed the query string parameters, we have to check
            #      the content
            elif fuzzy_not_equal(response.get_clear_text_body(), original_resp.get_clear_text_body(), 0.8):
                # In this case what might happen is that the number we changed
                # is "out of range" and when requesting that it will trigger an
                # error in the web application, or show us a non-interesting
                # response that holds no content.
                #
                # We choose to return these to the core because they might help
                # with the code coverage efforts. Think about something like:
                #     foo.aspx?id=OUT_OF_RANGE&foo=inject_here
                # vs.
                #     foo.aspx?id=IN_RANGE&foo=inject_here
                #
                # This relates to the EXPECTED_URLS in test_digit_sum.py
                add = True

        if add:
            for fr in self._create_fuzzable_requests(response):
                self.output_queue.put(fr)
Example #11
0
    def _test_dns(self, original_response, dns_wildcard_url):
        """
        Check if http://www.domain.tld/ == http://domain.tld/
        """
        headers = Headers([('Host', dns_wildcard_url.get_domain())])

        try:
            modified_response = self._uri_opener.GET(original_response.get_url(),
                                                     cache=True,
                                                     headers=headers)
        except BaseFrameworkException as bfe:
            msg = ('An error occurred while fetching IP address URL in '
                   ' dns_wildcard plugin: "%s"')
            om.out.debug(msg % bfe)
            return

        if fuzzy_not_equal(modified_response.get_body(), original_response.get_body(), 0.35):
            desc = ('The target site has NO DNS wildcard, and the contents'
                    ' of "%s" differ from the contents of "%s".')
            desc %= (dns_wildcard_url, original_response.get_url())

            i = Info('No DNS wildcard',
                     desc,
                     [original_response.id, modified_response.id],
                     self.get_name())
            i.set_url(dns_wildcard_url)

            kb.kb.append(self, 'dns_wildcard', i)
            om.out.information(i.get_desc())
        else:
            desc = ('The target site has a DNS wildcard configuration, the'
                    ' contents of "%s" are equal to the ones of "%s".')
            desc %= (dns_wildcard_url, original_response.get_url())

            i = Info('DNS wildcard',
                     desc,
                     [original_response.id, modified_response.id],
                     self.get_name())
            i.set_url(original_response.get_url())

            kb.kb.append(self, 'dns_wildcard', i)
            om.out.information(i.get_desc())
Example #12
0
 def _analyze_response(self, original_resp, resp):
     """
     :param original_resp: The HTTPResponse object that holds the
                               ORIGINAL response.
     :param resp: The HTTPResponse object that holds the content of
                      the response to analyze.
     """
     if fuzzy_not_equal(original_resp.get_body(), resp.get_body(), 0.7):
         response_ids = [original_resp.id, resp.id]
         desc = '[Manual verification required] The response body for a ' \
               'request with a trailing dot in the domain, and the response ' \
               'body without a trailing dot in the domain differ. This could ' \
               'indicate a misconfiguration in the virtual host settings. In ' \
               'some cases, this misconfiguration permits the attacker to ' \
               'read the source code of the web application.'
         
         i = Info('Potential virtual host misconfiguration', desc,
                  response_ids, self.get_name())
         
         om.out.information(desc)
         kb.kb.append(self, 'domain_dot', i)
Example #13
0
File: afd.py Project: RON313/w3af
    def _send_and_analyze(self, offending_string, offending_url,
                          original_resp_body, rnd_param):
        """
        Actually send the HTTP request.

        :return: None, everything is saved to the self._filtered and
                 self._not_filtered lists.
        """
        try:
            resp_body = self._uri_opener.GET(offending_url,
                                             cache=False).get_body()
        except BaseFrameworkException:
            # I get here when the remote end closes the connection
            self._filtered.append(offending_url)
        else:
            # I get here when the remote end returns a 403 or something like
            # that... So I must analyze the response body
            resp_body = resp_body.replace(offending_string, '')
            resp_body = resp_body.replace(rnd_param, '')
            if fuzzy_not_equal(resp_body, original_resp_body, 0.15):
                self._filtered.append(offending_url)
            else:
                self._not_filtered.append(offending_url)
Example #14
0
    def _send_and_analyze(self, offending_string, offending_url,
                          original_resp_body, rnd_param):
        """
        Actually send the HTTP request.

        :return: None, everything is saved to the self._filtered and
                 self._not_filtered lists.
        """
        try:
            resp_body = self._uri_opener.GET(offending_url,
                                             cache=False).get_body()
        except BaseFrameworkException:
            # I get here when the remote end closes the connection
            self._filtered.append(offending_url)
        else:
            # I get here when the remote end returns a 403 or something like
            # that... So I must analyze the response body
            resp_body = resp_body.replace(offending_string, '')
            resp_body = resp_body.replace(rnd_param, '')
            if fuzzy_not_equal(resp_body, original_resp_body, 0.15):
                self._filtered.append(offending_url)
            else:
                self._not_filtered.append(offending_url)
Example #15
0
    def _test_DNS(self, original_response, dns_wildcard_url):
        """
        Check if http://www.domain.tld/ == http://domain.tld/
        """
        headers = Headers([('Host', dns_wildcard_url.get_domain())])
        try:
            modified_response = self._uri_opener.GET(
                original_response.get_url(),
                cache=True,
                headers=headers)
        except BaseFrameworkException:
            return
        else:
            if fuzzy_not_equal(modified_response.get_body(),
                                    original_response.get_body(), 0.35):
                desc = 'The target site has NO DNS wildcard, and the contents' \
                       ' of "%s" differ from the contents of "%s".'
                desc = desc % (dns_wildcard_url, original_response.get_url())
                
                i = Info('No DNS wildcard', desc, modified_response.id,
                         self.get_name())
                i.set_url(dns_wildcard_url)

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())
            else:
                desc = 'The target site has a DNS wildcard configuration, the'\
                      ' contents of "%s" are equal to the ones of "%s".'
                desc = desc % (dns_wildcard_url, original_response.get_url())
                
                i = Info('DNS wildcard', desc, modified_response.id,
                         self.get_name())
                i.set_url(original_response.get_url())

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())
        :return: None
        """
        if base_url == url:
            return

        http_response = self._uri_opener.GET(url, cache=False)
        http_response_code = http_response.get_code()
        if is_404(http_response) or http_response_code in (204, 301, 302, 404, 503):
            return

        # Looking good, but lets see if this is a false positive or not...
        url = base_url.url_join(path + rand_alnum(5) + '/')
        invalid_http_response = self._uri_opener.GET(url, cache=False)

        if is_404(invalid_http_response) or fuzzy_not_equal(http_response.get_body(), invalid_http_response.get_body(), 0.35):
            # Good, the path + rand_alnum(5) return a 404, the original path is not a false positive.
            desc = 'Path: "{}" found with HTTP "response code: {}" and "Content-Length: {}". ' \
                   'It might exposes private information and requires a manual review'.format(http_response.get_url(),
                                                                                              http_response_code,
                                                                                              len(http_response.get_body()))
            i = Info('.listing file found', desc, http_response.id, self.get_name())
            i.set_url(self._target_url)
            self.kb_append(self, 'wg_dir_file_bruter', i)

    def _bruteforce_directories(self, base_url):
        """
        :param base_url: The base path to use in the bruteforcing process,
                          can be something like http://host.tld/ or
                          http://host.tld/images/ .
        :return: None
Example #17
0
    def _get_dead_links(self, fuzzable_request):
        """
        Find every link on a HTML document verify if the domain is reachable or
        not; after that, verify if the web found a different name for the target
        site or if we found a new site that is linked. If the link points to a
        dead site then report it (it could be pointing to some private address
        or something...)
        """
        # Get some responses to compare later
        base_url = fuzzable_request.get_url().base_url()
        original_response = self._uri_opener.GET(fuzzable_request.get_uri(),
                                                 cache=True)
        base_response = self._uri_opener.GET(base_url, cache=True)
        base_resp_body = base_response.get_body()

        try:
            dp = parser_cache.dpc.get_document_parser_for(original_response)
        except BaseFrameworkException:
            # Failed to find a suitable parser for the document
            return []

        # Set the non existent response
        non_existent_response = self._get_non_exist(fuzzable_request)
        nonexist_resp_body = non_existent_response.get_body()

        # Note:
        # - With parsed_references I'm 100% that it's really something in the
        #   HTML that the developer intended to add.
        #
        # - The re_references are the result of regular expressions, which in
        #   some cases are just false positives.
        #
        # In this case, and because I'm only going to use the domain name of the
        # URL I'm going to trust the re_references also.
        parsed_references, re_references = dp.get_references()
        parsed_references.extend(re_references)

        res = []

        vhosts = self._verify_link_domain(parsed_references)

        for domain, vhost_response in self._send_in_threads(base_url, vhosts):

            vhost_resp_body = vhost_response.get_body()

            if fuzzy_not_equal(vhost_resp_body, base_resp_body, 0.35) and \
            fuzzy_not_equal(vhost_resp_body, nonexist_resp_body, 0.35):
                res.append((domain, vhost_response.id))
            else:
                desc = 'The content of "%s" references a non existent domain:'\
                       ' "%s". This can be a broken link, or an internal'\
                       ' domain name.'
                desc = desc % (fuzzable_request.get_url(), domain)
                
                i = Info('Internal hostname in HTML link', desc,
                         original_response.id, self.get_name())
                i.set_url(fuzzable_request.get_url())
                
                kb.kb.append(self, 'find_vhosts', i)
                om.out.information(i.get_desc())

        return res
Example #18
0
            ip_address = socket.gethostbyname(domain)
        except:
            return

        url = original_response.get_url()
        ip_url = url.copy()
        ip_url.set_domain(ip_address)

        try:
            modified_response = self._uri_opener.GET(ip_url, cache=True)
        except BaseFrameworkException, w3:
            msg = 'An error occurred while fetching IP address URL in ' \
                  ' dns_wildcard plugin: "%s"' % w3
            om.out.debug(msg)
        else:
            if fuzzy_not_equal(modified_response.get_body(),
                                    original_response.get_body(), 0.35):

                desc = 'The contents of %s and %s differ.' 
                desc = desc % (modified_response.get_uri(),
                               original_response.get_uri())
                
                i = Info('Default virtual host', desc, modified_response.id,
                         self.get_name())
                i.set_url(modified_response.get_url())

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())

    def _test_DNS(self, original_response, dns_wildcard_url):
        """
        Check if http://www.domain.tld/ == http://domain.tld/
Example #19
0
    def audit(self, freq, orig_response):
        """
        Tests an URL for memcache injection vulnerabilities.
        """

        # first checking error response
        fake_mutants = create_mutants(freq, ['', ])

        for mutant in fake_mutants:

            orig_body = orig_response.get_body()

            #trying to break normal execution flow with error1 payload
            mutant.set_token_value(self.mci.error_1)
            error_1_response, body_error_1_response = self._uri_opener.send_clean(mutant)

            if fuzzy_equal(orig_body, body_error_1_response, self._eq_limit):
                #
                # if we manage to break execution flow, there is a potential
                # injection otherwise - no injection!
                #
                continue

            # trying the correct injection request, to confirm that we've found
            # it!

            mutant.set_token_value(self.mci.ok)
            ok_response, body_ok_response = self._uri_opener.send_clean(mutant)

            if fuzzy_not_equal(orig_body, body_ok_response, self._eq_limit):
                #
                #  now requests should be equal, otherwise injection failed!
                #
                continue

            #error2 request to just make sure that wasn't random bytes

            mutant.set_token_value(self.mci.error_2)
            error_2_response, body_error_2_response = self._uri_opener.send_clean(mutant)

            if fuzzy_equal(orig_body, body_error_2_response, self._eq_limit):
                #
                # now requests should be different again, otherwise injection
                # is not confirmed
                #
                continue

            response_ids = [error_1_response.id,
                            ok_response.id,
                            error_2_response.id,]

            desc = 'Memcache injection was found at: "%s", using'\
                   ' HTTP method %s. The injectable parameter is: "%s"'
            desc = desc % (mutant.get_url(),
                           mutant.get_method(),
                           mutant.get_token_name())

            v = Vuln.from_mutant('Memcache injection vulnerability', desc,
                                 severity.HIGH, response_ids, 'memcachei',
                                 mutant)

            self.debug(v.get_desc())

            v['ok_html'] = ok_response.get_body()
            v['error_1_html'] = error_1_response.get_body()
            v['error_2_html'] = error_2_response.get_body()

            self.kb_append_uniq(self, 'memcachei', v)

        return
Example #20
0
            ip_address = socket.gethostbyname(domain)
        except:
            return

        url = original_response.get_url()
        ip_url = url.copy()
        ip_url.set_domain(ip_address)

        try:
            modified_response = self._uri_opener.GET(ip_url, cache=True)
        except BaseFrameworkException, w3:
            msg = 'An error occurred while fetching IP address URL in ' \
                  ' dns_wildcard plugin: "%s"' % w3
            om.out.debug(msg)
        else:
            if fuzzy_not_equal(modified_response.get_body(),
                               original_response.get_body(), 0.35):
                desc = 'The contents of %s and %s differ.'
                desc = desc % (modified_response.get_uri(),
                               original_response.get_uri())

                i = Info('Default virtual host', desc, modified_response.id,
                         self.get_name())
                i.set_url(modified_response.get_url())

                kb.kb.append(self, 'dns_wildcard', i)
                om.out.information(i.get_desc())

    def _test_DNS(self, original_response, dns_wildcard_url):
        """
        Check if http://www.domain.tld/ == http://domain.tld/
        """
Example #21
0
    def batch_injection_test(self, freq, orig_response):
        """
        Uses the batch injection technique to find memcache injections
        """
        # shortcut
        send_clean = self._uri_opener.send_clean

        # first checking error response
        fake_mutants = create_mutants(freq, [
            '',
        ])

        for mutant in fake_mutants:

            orig_body = orig_response.get_body()

            # trying to break normal execution flow with error1 payload
            mutant.set_token_value(self.mci.error_1)
            error_1_response, body_error_1_response = send_clean(mutant)

            if fuzzy_equal(orig_body, body_error_1_response, self._eq_limit):
                #
                # if we manage to break execution flow, there is a potential
                # injection otherwise - no injection!
                #
                continue

            # trying the correct injection request, to confirm that we've found
            # it!

            mutant.set_token_value(self.mci.ok)
            ok_response, body_ok_response = send_clean(mutant)

            if fuzzy_not_equal(orig_body, body_ok_response, self._eq_limit):
                #
                #  now requests should be equal, otherwise injection failed!
                #
                continue

            # error2 request to just make sure that wasn't random bytes

            mutant.set_token_value(self.mci.error_2)
            error_2_response, body_error_2_response = send_clean(mutant)

            if fuzzy_equal(orig_body, body_error_2_response, self._eq_limit):
                #
                # now requests should be different again, otherwise injection
                # is not confirmed
                #
                continue

            response_ids = [
                error_1_response.id, ok_response.id, error_2_response.id
            ]

            desc = 'Memcache injection was found at: "%s", using' \
                   ' HTTP method %s. The injectable parameter is: "%s"'
            desc = desc % (mutant.get_url(), mutant.get_method(),
                           mutant.get_token_name())

            v = Vuln.from_mutant('Memcache injection vulnerability', desc,
                                 severity.HIGH, response_ids, 'memcachei',
                                 mutant)

            v['ok_html'] = ok_response.get_body()
            v['error_1_html'] = error_1_response.get_body()
            v['error_2_html'] = error_2_response.get_body()

            self.kb_append_uniq(self, 'memcachei', v)

        return
Example #22
0
    def _get_dead_links(self, fuzzable_request):
        """
        Find every link on a HTML document verify if the domain is reachable or
        not; after that, verify if the web found a different name for the target
        site or if we found a new site that is linked. If the link points to a
        dead site then report it (it could be pointing to some private address
        or something...)
        """
        # Get some responses to compare later
        base_url = fuzzable_request.get_url().base_url()
        original_response = self._uri_opener.GET(fuzzable_request.get_uri(),
                                                 cache=True)
        base_response = self._uri_opener.GET(base_url, cache=True)
        base_resp_body = base_response.get_body()

        try:
            dp = parser_cache.dpc.get_document_parser_for(original_response)
        except BaseFrameworkException:
            # Failed to find a suitable parser for the document
            return []

        # Set the non existent response
        non_existent_response = self._get_non_exist(fuzzable_request)
        nonexist_resp_body = non_existent_response.get_body()

        # Note:
        # - With parsed_references I'm 100% that it's really something in the
        #   HTML that the developer intended to add.
        #
        # - The re_references are the result of regular expressions, which in
        #   some cases are just false positives.
        #
        # In this case, and because I'm only going to use the domain name of the
        # URL I'm going to trust the re_references also.
        parsed_references, re_references = dp.get_references()
        parsed_references.extend(re_references)

        res = []

        vhosts = self._verify_link_domain(parsed_references)

        for domain, vhost_response in self._send_in_threads(base_url, vhosts):

            vhost_resp_body = vhost_response.get_body()

            if fuzzy_not_equal(vhost_resp_body, base_resp_body, 0.35) and \
            fuzzy_not_equal(vhost_resp_body, nonexist_resp_body, 0.35):
                res.append((domain, vhost_response.id))
            else:
                desc = u'The content of "%s" references a non existent domain:'\
                       u' "%s". This can be a broken link, or an internal'\
                       u' domain name.'
                desc %= (fuzzable_request.get_url(), domain)
                
                i = Info(u'Internal hostname in HTML link', desc,
                         original_response.id, self.get_name())
                i.set_url(fuzzable_request.get_url())
                
                kb.kb.append(self, 'find_vhosts', i)
                om.out.information(i.get_desc())

        return res