Exemplo n.º 1
0
    def _mutate(self, data):
        '''
        Add a random parameter.

        :param data: A dict-like object.
        :return: The same object with one new key-value.
        '''
        key = rand_alnum(5)
        value = rand_alnum(8)
        data[key] = value
        return data
Exemplo n.º 2
0
    def _single_404_check(self, http_response, html_body):
        '''
        Performs a very simple check to verify if this response is a 404 or not.

        It takes the original URL and modifies it by pre-pending a "not-" to the
        filename, then performs a request to that URL and compares the original
        response with the modified one. If they are equal then the original
        request is a 404.

        :param http_response: The original HTTP response
        :param html_body: The original HTML body after passing it by a cleaner

        :return: True if the original response was a 404 !
        '''
        response_url = http_response.get_url()
        filename = response_url.get_file_name()
        if not filename:
            relative_url = '../%s/' % rand_alnum(8)
            url_404 = response_url.url_join(relative_url)
        else:
            relative_url = 'not-%s' % filename
            url_404 = response_url.url_join(relative_url)

        response_404 = self._send_404(url_404, store=False)
        clean_response_404_body = get_clean_body(response_404)

        if response_404.get_code() == 404 and \
                url_404.get_domain_path() not in self._directory_uses_404_codes:
            self._directory_uses_404_codes.add(url_404.get_domain_path())

        return relative_distance_ge(clean_response_404_body, html_body, IS_EQUAL_RATIO)
Exemplo n.º 3
0
    def _single_404_check(self, http_response, html_body):
        '''
        Performs a very simple check to verify if this response is a 404 or not.

        It takes the original URL and modifies it by pre-pending a "not-" to the
        filename, then performs a request to that URL and compares the original
        response with the modified one. If they are equal then the original
        request is a 404.

        :param http_response: The original HTTP response
        :param html_body: The original HTML body after passing it by a cleaner

        :return: True if the original response was a 404 !
        '''
        response_url = http_response.get_url()
        filename = response_url.get_file_name()
        if not filename:
            relative_url = '../%s/' % rand_alnum(8)
            url_404 = response_url.url_join(relative_url)
        else:
            relative_url = 'not-%s' % filename
            url_404 = response_url.url_join(relative_url)

        response_404 = self._send_404(url_404, store=False)
        clean_response_404_body = get_clean_body(response_404)

        if response_404.get_code() == 404 and \
                url_404.get_domain_path() not in self._directory_uses_404_codes:
            self._directory_uses_404_codes.add(url_404.get_domain_path())

        return relative_distance_ge(clean_response_404_body, html_body,
                                    IS_EQUAL_RATIO)
Exemplo n.º 4
0
Arquivo: rfi.py Projeto: daemon13/w3af
 def _gen_url_to_include(self, file_content, extension):
     '''
     Generate the URL to include, based on the configuration it will return a
     URL pointing to a XSS bug, or our local webserver.
     '''
     if self._use_XSS_vuln and self._xss_vuln:
         url = self._xss_vuln.get_url().uri2url()
         data_container = self._xss_vuln.get_dc()
         data_container = data_container.copy()
         data_container[self._xss_vuln.get_var()] = file_content
         url_to_include = url + '?' + str(data_container)
         return url_to_include
     else:
         # Write the php to the webroot
         filename = rand_alnum()
         filepath = os.path.join(get_home_dir(), 'webroot', filename)
         try:
             file_handler = open(filepath, 'w')
             file_handler.write(file_content)
             file_handler.close()
         except:
             raise w3afException('Could not create file in webroot.')
         else:
             url_to_include = 'http://%s:%s/%s' % (
                 self._listen_address, self._listen_port, filename)
             return url_to_include
Exemplo n.º 5
0
    def _create_files(self):
        """
        If the extension is in the templates dir, open it and return the handler.
        If the extension isn't in the templates dir, create a file with random
        content, open it and return the handler.

        :return: A list of tuples with (file handler, file name)
        """
        result = []

        for ext in self._extensions:
            # Open target
            temp_dir = get_temp_dir()
            low_level_fd, file_name = tempfile.mkstemp(prefix="w3af_", suffix="." + ext, dir=temp_dir)
            file_handler = os.fdopen(low_level_fd, "w+b")

            template_filename = "template." + ext
            if template_filename in os.listdir(self.TEMPLATE_DIR):
                content = file(os.path.join(self.TEMPLATE_DIR, template_filename)).read()
            else:
                # Since I don't have a template for this file extension, I'll simply
                # put some random alnum inside the file
                content = rand_alnum(64)

            # Write content to target
            file_handler.write(content)
            file_handler.close()

            # Open the target again, should never fail.
            file_handler = file(file_name, "r")
            _, file_name = os.path.split(file_name)
            result.append((file_handler, file_name))

        return result
Exemplo n.º 6
0
    def test_find(self):
        find_id = random.randint(1, 499)
        url = URL("http://w3af.org/a/b/foobar.php?foo=123")
        tag_value = rand_alnum(10)
        for i in xrange(0, 500):
            request = HTTPRequest(url, data="a=1")
            code = 200
            if i == find_id:
                code = 302

            hdr = Headers([("Content-Type", "text/html")])
            res = HTTPResponse(code, "<html>", hdr, url, url)
            h1 = HistoryItem()
            h1.request = request
            res.set_id(i)
            h1.response = res
            if i == find_id:
                h1.toggle_mark()
                h1.update_tag(tag_value)
            h1.save()
        h2 = HistoryItem()
        self.assertEqual(len(h2.find([("tag", "%" + tag_value + "%", "like")])), 1)
        self.assertEqual(len(h2.find([("code", 302, "=")])), 1)
        self.assertEqual(len(h2.find([("mark", 1, "=")])), 1)
        self.assertEqual(len(h2.find([("has_qs", 1, "=")])), 500)
        self.assertEqual(len(h2.find([("has_qs", 1, "=")], result_limit=10)), 10)
        results = h2.find([("has_qs", 1, "=")], result_limit=1, orderData=[("id", "desc")])
        self.assertEqual(results[0].id, 499)
        search_data = []
        search_data.append(("id", find_id + 1, "<"))
        search_data.append(("id", find_id - 1, ">"))
        self.assertEqual(len(h2.find(search_data)), 1)
Exemplo n.º 7
0
Arquivo: rfi.py Projeto: HamzaKo/w3af
 def _gen_url_to_include(self, file_content, extension):
     '''
     Generate the URL to include, based on the configuration it will return a
     URL pointing to a XSS bug, or our local webserver.
     '''
     if self._use_XSS_vuln and self._xss_vuln:
         url = self._xss_vuln.get_url().uri2url()
         data_container = self._xss_vuln.get_dc()
         data_container = data_container.copy()
         data_container[self._xss_vuln.get_var()] = file_content
         url_to_include = url + '?' + str(data_container)
         return url_to_include
     else:
         # Write the php to the webroot
         filename = rand_alnum()
         filepath = os.path.join(get_home_dir(), 'webroot', filename)
         try:
             file_handler = open(filepath, 'w')
             file_handler.write(file_content)
             file_handler.close()
         except:
             raise w3afException('Could not create file in webroot.')
         else:
             url_to_include = 'http://%s:%s/%s' % (self._listen_address,
                                                   self._listen_port,
                                                   filename)
             return url_to_include
Exemplo n.º 8
0
def create_crash_file(exception):
    filename = "w3af_crash-" + rand_alnum(5) + ".txt"
    filename = os.path.join(gettempdir(), filename)
    crash_dump = file(filename, "w")
    crash_dump.write(_('Submit this bug here: https://sourceforge.net/apps/trac/w3af/newticket \n'))
    crash_dump.write(get_versions())
    crash_dump.write(exception)
    crash_dump.close()
    return filename
Exemplo n.º 9
0
def create_crash_file(exception):
    filename = "w3af_crash-" + rand_alnum(5) + ".txt"
    filename = os.path.join(gettempdir(), filename)
    crash_dump = file(filename, "w")
    crash_dump.write(
        _('Submit this bug here: https://sourceforge.net/apps/trac/w3af/newticket \n'
          ))
    crash_dump.write(get_versions())
    crash_dump.write(exception)
    crash_dump.close()
    return filename
Exemplo n.º 10
0
    def _PUT(self, domain_path):
        '''
        Tests PUT method.
        '''
        # upload
        url = domain_path.url_join(rand_alpha(5))
        rnd_content = rand_alnum(6)
        put_response = self._uri_opener.PUT(url, data=rnd_content)

        # check if uploaded
        res = self._uri_opener.GET(url, cache=True)
        if res.get_body() == rnd_content:
            msg = 'File upload with HTTP PUT method was found at resource:' \
                  ' "%s". A test file was uploaded to: "%s".'
            msg = msg % (domain_path, res.get_url())

            v = Vuln('Insecure DAV configuration', msg, severity.HIGH,
                     [put_response.id, res.id], self.get_name())

            v.set_url(url)
            v.set_method('PUT')

            self.kb_append(self, 'dav', v)

        # Report some common errors
        elif put_response.get_code() == 500:
            msg = 'DAV seems to be incorrectly configured. The web server' \
                  ' answered with a 500 error code. In most cases, this means'\
                  ' that the DAV extension failed in some way. This error was'\
                  ' found at: "%s".' % put_response.get_url()

            i = Info('DAV incorrect configuration', msg, res.id,
                     self.get_name())

            i.set_url(url)
            i.set_method('PUT')

            self.kb_append(self, 'dav', i)

        # Report some common errors
        elif put_response.get_code() == 403:
            msg = 'DAV seems to be correctly configured and allowing you to'\
                  ' use the PUT method but the directory does not have the'\
                  ' correct permissions that would allow the web server to'\
                  ' write to it. This error was found at: "%s".'
            msg = msg % put_response.get_url()

            i = Info('DAV incorrect configuration', msg,
                     [put_response.id, res.id], self.get_name())

            i.set_url(url)
            i.set_method('PUT')

            self.kb_append(self, 'dav', i)
Exemplo n.º 11
0
    def _PUT(self, domain_path):
        '''
        Tests PUT method.
        '''
        # upload
        url = domain_path.url_join(rand_alpha(5))
        rnd_content = rand_alnum(6)
        put_response = self._uri_opener.PUT(url, data=rnd_content)

        # check if uploaded
        res = self._uri_opener.GET(url, cache=True)
        if res.get_body() == rnd_content:
            msg = 'File upload with HTTP PUT method was found at resource:' \
                  ' "%s". A test file was uploaded to: "%s".'
            msg = msg % (domain_path, res.get_url())
            
            v = Vuln('Insecure DAV configuration', msg, severity.HIGH,
                     [put_response.id, res.id], self.get_name())

            v.set_url(url)
            v.set_method('PUT')
            
            self.kb_append(self, 'dav', v)

        # Report some common errors
        elif put_response.get_code() == 500:
            msg = 'DAV seems to be incorrectly configured. The web server' \
                  ' answered with a 500 error code. In most cases, this means'\
                  ' that the DAV extension failed in some way. This error was'\
                  ' found at: "%s".' % put_response.get_url()

            i = Info('DAV incorrect configuration', msg, res.id, self.get_name())

            i.set_url(url)
            i.set_method('PUT')
            
            self.kb_append(self, 'dav', i)

        # Report some common errors
        elif put_response.get_code() == 403:
            msg = 'DAV seems to be correctly configured and allowing you to'\
                  ' use the PUT method but the directory does not have the'\
                  ' correct permissions that would allow the web server to'\
                  ' write to it. This error was found at: "%s".'
            msg = msg % put_response.get_url()
            
            i = Info('DAV incorrect configuration', msg,
                     [put_response.id, res.id], self.get_name())

            i.set_url(url)
            i.set_method('PUT')
            
            self.kb_append(self, 'dav', i)
Exemplo n.º 12
0
def get_file_from_template(extension):
    file_name = "%s.%s" % (rand_alpha(7), extension)

    template_file = os.path.join(TEMPLATE_DIR, 'template.%s' % extension)
    if os.path.exists(template_file):
        file_content = file(template_file).read()
        success = True
    else:
        file_content = rand_alnum(64)
        success = False

    return success, file_content, file_name
Exemplo n.º 13
0
 def _replace_JUNK(self, query):
     '''
     Replace the JUNK(x) variable with random alphanum.
     '''
     match_obj = self._junk_re.search(query)
     
     if match_obj is not None:
         if match_obj.group(1).isdigit():
             
             length = int(match_obj.group(1))
             query = self._junk_re.sub(rand_alnum(length), query)
             
     return query
Exemplo n.º 14
0
    def _create_file(self):
        '''
        Create random name file php with random php content. To be used in the
        remote file inclusion test.

        :return: The file content to be served via the webserver.

        Please note that the generated code works both in PHP and JSP without
        any issues, since PHP will run everything between "<?" and "?>" and
        JSP will run code between "<%" and "%>".

        TODO: make this code compatible with: asp/aspx, jsp, js (nodejs), pl,
              py, rb, etc. Some code snippets that might help to achieve this
              task:

        asp_code = 'response.write("%s");\n response.write("%s");' % (
            rand1, rand2)
        asp_code = '<% \n '+asp_code+'\n %>'
        '''
        with self._plugin_lock:
            # First, generate the php file to be included.
            rfi_result_part_1 = rand1 = rand_alnum(9)
            rfi_result_part_2 = rand2 = rand_alnum(9)
            rfi_result = rand1 + rand2

            filename = rand_alnum(8)
            php_jsp_code = '<? echo "%s"; echo "%s"; ?>'
            php_jsp_code += '<%% out.print("%s"); out.print("%s"); %%>'
            php_jsp_code = php_jsp_code % (rand1, rand2, rand1, rand2)

            # Define the required parameters
            netloc = self._listen_address + ':' + str(self._listen_port)
            path = '/' + filename
            rfi_url = URL.from_parts('http', netloc, path, None, None, None)

            rfi_data = RFIData(
                rfi_url, rfi_result_part_1, rfi_result_part_2, rfi_result)

            return php_jsp_code, rfi_data
Exemplo n.º 15
0
    def _id_failed_login_page(self, freq, user_field, passwd_field):
        '''
        Generate TWO different response bodies that are the result of failed
        logins.

        The first result is for logins with filled user and password fields;
        the second one is for a filled user and a blank passwd.
        '''
        # The result is going to be stored here
        login_failed_result_list = []

        data_container = freq.get_dc()
        data_container = self._true_extra_fields(data_container, user_field,
                                                 passwd_field)

        # The first tuple is an invalid username and a password
        # The second tuple is an invalid username with a blank password
        tests = [(rand_alnum(8), rand_alnum(8)), (rand_alnum(8), '')]

        for user, passwd in tests:
            # Setup the data_container
            # Remember that we can have password only forms!
            if user_field is not None:
                data_container[user_field][0] = user
            data_container[passwd_field][0] = passwd
            freq.set_dc(data_container)

            response = self._uri_opener.send_mutant(freq, grep=False)

            body = response.get_body()
            body = body.replace(user, '')
            body = body.replace(passwd, '')

            # Save it
            login_failed_result_list.append(body)

        # Now I perform a self test, before starting with the actual bruteforcing
        # The first tuple is an invalid username and a password
        # The second tuple is an invalid username with a blank password
        tests = [(rand_alnum(8), rand_alnum(8)), (rand_alnum(8), '')]

        for user, passwd in tests:
            # Now I do a self test of the result I just created.
            #   Remember that we can have password only forms!
            if user_field is not None:
                data_container[user_field][0] = user
            data_container[passwd_field][0] = passwd
            freq.set_dc(data_container)
            response = self._uri_opener.send_mutant(freq, grep=False)

            body = response.get_body()
            body = body.replace(user, '')
            body = body.replace(passwd, '')

            if not self._matches_failed_login(body, login_failed_result_list):
                raise w3afException('Failed to generate a response that '
                                    'matches the failed login page.')

        return login_failed_result_list
Exemplo n.º 16
0
Arquivo: rfi.py Projeto: weisst/w3af
    def _create_file(self):
        '''
        Create random name file php with random php content. To be used in the
        remote file inclusion test.

        :return: The file content to be served via the webserver.

        Please note that the generated code works both in PHP and JSP without
        any issues, since PHP will run everything between "<?" and "?>" and
        JSP will run code between "<%" and "%>".

        TODO: make this code compatible with: asp/aspx, jsp, js (nodejs), pl,
              py, rb, etc. Some code snippets that might help to achieve this
              task:

        asp_code = 'response.write("%s");\n response.write("%s");' % (
            rand1, rand2)
        asp_code = '<% \n '+asp_code+'\n %>'
        '''
        with self._plugin_lock:
            # First, generate the php file to be included.
            rfi_result_part_1 = rand1 = rand_alnum(9)
            rfi_result_part_2 = rand2 = rand_alnum(9)
            rfi_result = rand1 + rand2

            filename = rand_alnum(8)
            php_jsp_code = '<? echo "%s"; echo "%s"; ?>'
            php_jsp_code += '<%% out.print("%s"); out.print("%s"); %%>'
            php_jsp_code = php_jsp_code % (rand1, rand2, rand1, rand2)

            # Define the required parameters
            netloc = self._listen_address + ':' + str(self._listen_port)
            path = '/' + filename
            rfi_url = URL.from_parts('http', netloc, path, None, None, None)

            rfi_data = RFIData(rfi_url, rfi_result_part_1, rfi_result_part_2,
                               rfi_result)

            return php_jsp_code, rfi_data
Exemplo n.º 17
0
    def _replace_JUNK(self, query):
        '''
        Replace the JUNK(x) variable with random alphanum.
        '''
        match_obj = self._junk_re.search(query)

        if match_obj is not None:
            if match_obj.group(1).isdigit():

                length = int(match_obj.group(1))
                query = self._junk_re.sub(rand_alnum(length), query)

        return query
Exemplo n.º 18
0
    def _send_requests(self, fuzzable_request):
        '''
        Actually send the requests that might be blocked.
        :param fuzzable_request: The FuzzableRequest to modify in order to
                                     see if it's blocked
        '''
        rnd_param = rand_alnum(7)
        rnd_value = rand_alnum(7)
        fmt = '%s?%s=%s'
        original_url_str = fmt % (fuzzable_request.get_url(),
                                  rnd_param, rnd_value)
        original_url = URL(original_url_str)

        try:
            http_resp = self._uri_opener.GET(original_url, cache=True)
        except w3afException:
            msg = 'Active filter detection plugin failed to receive a'\
                  ' response for the first request. Can not perform analysis.'
            om.out.error(msg)
        else:
            original_response_body = http_resp.get_body()
            original_response_body = original_response_body.replace(
                rnd_param, '')
            original_response_body = original_response_body.replace(
                rnd_value, '')

            tests = []
            for offending_string in self._get_offending_strings():
                offending_URL = fmt % (fuzzable_request.get_url(),
                                       rnd_param,
                                       offending_string)
                offending_URL = URL(offending_URL)
                tests.append((offending_string, offending_URL,
                              original_response_body, rnd_param))

            self.worker_pool.map_multi_args(self._send_and_analyze, tests)

            return self._filtered, self._not_filtered
Exemplo n.º 19
0
Arquivo: afd.py Projeto: weisst/w3af
    def _send_requests(self, fuzzable_request):
        '''
        Actually send the requests that might be blocked.
        :param fuzzable_request: The FuzzableRequest to modify in order to
                                     see if it's blocked
        '''
        rnd_param = rand_alnum(7)
        rnd_value = rand_alnum(7)
        fmt = '%s?%s=%s'
        original_url_str = fmt % (fuzzable_request.get_url(), rnd_param,
                                  rnd_value)
        original_url = URL(original_url_str)

        try:
            http_resp = self._uri_opener.GET(original_url, cache=True)
        except w3afException:
            msg = 'Active filter detection plugin failed to receive a'\
                  ' response for the first request. Can not perform analysis.'
            om.out.error(msg)
        else:
            original_response_body = http_resp.get_body()
            original_response_body = original_response_body.replace(
                rnd_param, '')
            original_response_body = original_response_body.replace(
                rnd_value, '')

            tests = []
            for offending_string in self._get_offending_strings():
                offending_URL = fmt % (fuzzable_request.get_url(), rnd_param,
                                       offending_string)
                offending_URL = URL(offending_URL)
                tests.append((offending_string, offending_URL,
                              original_response_body, rnd_param))

            self.worker_pool.map_multi_args(self._send_and_analyze, tests)

            return self._filtered, self._not_filtered
Exemplo n.º 20
0
def get_remote_temp_file(exec_method):
    '''
    :return: The name of a file in the remote file system that the user that I'm
             executing commands with can write, read and execute. The normal
             responses for this are files in /tmp/ or %TEMP% depending on the
             remote OS.
    '''
    os = os_detection_exec(exec_method)
    if os == 'windows':
        _filename = exec_method('echo %TEMP%').strip() + '\\'
        _filename += rand_alnum(6)

        # verify exists
        dir_res = exec_method('dir ' + _filename).strip().lower()
        if 'not found' in dir_res:
            return _filename
        else:
            # Shit, the file exists, run again and see what we can do
            return get_remote_temp_file(exec_method)

        return _filename

    elif os == 'linux':
        _filename = '/tmp/' + rand_alnum(6)

        # verify exists
        ls_res = exec_method('ls ' + _filename).strip()
        if 'No such file' in ls_res:
            return _filename
        else:
            # Shit, the file exists, run again and see what we can do
            return get_remote_temp_file(exec_method)

    else:
        msg = 'Failed to create filename for a temporary file in the remote host.'
        raise w3afException(msg)
Exemplo n.º 21
0
    def _return_without_eval(self, uri):
        '''
        This method tries to lower the false positives.
        '''
        if not uri.has_query_string():
            return False

        uri.set_file_name(uri.get_file_name() + rand_alnum(7))

        try:
            response = self._uri_opener.GET(uri, cache=True,
                                            headers=self._headers)
        except w3afException, e:
            msg = 'An exception was raised while requesting "%s", the error'
            msg += 'message is: "%s"'
            om.out.error(msg % (uri, e))
Exemplo n.º 22
0
    def test_rand_alnum(self):
        x = rand_alnum(length=10)
        self.assertEqual(len(x), 10)

        x = rand_alnum(length=20)
        self.assertEqual(len(x), 20)

        x = rand_alnum(length=5)
        y = rand_alnum(length=5)
        z = rand_alnum(length=5)
        w = rand_alnum(length=5)
        self.assertTrue(x != y != z != w)
Exemplo n.º 23
0
 def test_rand_alnum(self):
     x = rand_alnum(length=10)
     self.assertEqual(len(x), 10)
     
     x = rand_alnum( length=20 )
     self.assertEqual(len(x), 20)
     
     x = rand_alnum( length=5 )
     y = rand_alnum( length=5 )
     z = rand_alnum( length=5 )
     w = rand_alnum( length=5 )
     self.assertTrue(x != y != z != w)
Exemplo n.º 24
0
    def test_tag(self):
        tag_id = random.randint(501, 999)
        tag_value = rand_alnum(10)
        url = URL("http://w3af.org/a/b/c.php")

        for i in xrange(501, 1000):
            request = HTTPRequest(url, data="a=1")
            hdr = Headers([("Content-Type", "text/html")])
            res = HTTPResponse(200, "<html>", hdr, url, url)
            h1 = HistoryItem()
            h1.request = request
            res.set_id(i)
            h1.response = res
            if i == tag_id:
                h1.update_tag(tag_value)
            h1.save()

        h2 = HistoryItem()
        h2.load(tag_id)
        self.assertEqual(h2.tag, tag_value)
Exemplo n.º 25
0
    def _get_limit_response(self, m):
        '''
        We request the limit (something that doesn't exist)
            - If http://localhost/a.php?b=1 ; then I should request b=12938795
                                                                 (random number)
            - If http://localhost/a.php?b=abc ; then I should request b=hnv98yks
                                                                    (random alnum)

        :return: The limit response object
        '''
        # Copy the dc, needed to make a good vuln report
        dc = copy.deepcopy(m.get_dc())

        if m.get_original_value().isdigit():
            m.set_mod_value(rand_number(length=8))
        else:
            m.set_mod_value(rand_alnum(length=8))
        limit_response = self._uri_opener.send_mutant(m)

        # restore the dc
        m.set_dc(dc)
        return limit_response
Exemplo n.º 26
0
    def _get_limit_response(self, m):
        '''
        We request the limit (something that doesn't exist)
            - If http://localhost/a.php?b=1 ; then I should request b=12938795
                                                                 (random number)
            - If http://localhost/a.php?b=abc ; then I should request b=hnv98yks
                                                                    (random alnum)

        :return: The limit response object
        '''
        # Copy the dc, needed to make a good vuln report
        dc = copy.deepcopy(m.get_dc())

        if m.get_original_value().isdigit():
            m.set_mod_value(rand_number(length=8))
        else:
            m.set_mod_value(rand_alnum(length=8))
        limit_response = self._uri_opener.send_mutant(m)

        # restore the dc
        m.set_dc(dc)
        return limit_response
Exemplo n.º 27
0
    def modify_request(self, request):
        '''
        Mangles the request

        :param request: HTTPRequest instance that is going to be modified by
                        the evasion plugin
        :return: The modified request
        '''
        # We mangle the URL
        path = request.url_object.get_path()
        if re.match('^/', path):
            random_alnum = rand_alnum()
            path = '/' + random_alnum + '/..' + path

        # Finally, we set all the mutants to the request in order to return it
        new_url = request.url_object.copy()
        new_url.set_path(path)

        # Finally, we set all the mutants to the request in order to return it
        new_req = HTTPRequest(new_url, request.data, request.headers,
                              request.get_origin_req_host())

        return new_req
Exemplo n.º 28
0
    def _create_files(self):
        '''
        If the extension is in the templates dir, open it and return the handler.
        If the extension isn't in the templates dir, create a file with random
        content, open it and return the handler.

        :return: A list of tuples with (file handler, file name)
        '''
        result = []

        for ext in self._extensions:
            # Open target
            temp_dir = get_temp_dir()
            low_level_fd, file_name = tempfile.mkstemp(prefix='w3af_',
                                                       suffix='.' + ext,
                                                       dir=temp_dir)
            file_handler = os.fdopen(low_level_fd, "w+b")

            template_filename = 'template.' + ext
            if template_filename in os.listdir(self.TEMPLATE_DIR):
                content = file(
                    os.path.join(self.TEMPLATE_DIR, template_filename)).read()
            else:
                # Since I don't have a template for this file extension, I'll simply
                # put some random alnum inside the file
                content = rand_alnum(64)

            # Write content to target
            file_handler.write(content)
            file_handler.close()

            # Open the target again, should never fail.
            file_handler = file(file_name, 'r')
            _, file_name = os.path.split(file_name)
            result.append((file_handler, file_name))

        return result
Exemplo n.º 29
0
    def generate_404_knowledge(self, url):
        '''
        Based on a URL, request something that we know is going to be a 404.
        Afterwards analyze the 404's and summarise them.

        :return: A list with 404 bodies.
        '''
        #
        #    This is the case when nobody has properly configured
        #    the object in order to use it.
        #
        if self._uri_opener is None:
            msg = '404 fingerprint database was incorrectly initialized.'
            raise RuntimeError(msg)

        # Get the filename extension and create a 404 for it
        extension = url.get_extension()
        domain_path = url.get_domain_path()

        # the result
        self._response_body_list = []

        #
        #   This is a list of the most common handlers, in some configurations, the 404
        #   depends on the handler, so I want to make sure that I catch the 404 for each one
        #
        handlers = set()
        handlers.update(
            ['py', 'php', 'asp', 'aspx', 'do', 'jsp', 'rb', 'do'])
        handlers.update(
            ['gif', 'htm', 'pl', 'cgi', 'xhtml', 'htmls', 'foobar'])
        if extension:
            handlers.add(extension)

        args_list = []

        for extension in handlers:
            rand_alnum_file = rand_alnum(8) + '.' + extension
            url404 = domain_path.url_join(rand_alnum_file)
            args_list.append(url404)

        self._worker_pool.map(self._send_404, args_list)

        #
        #   I have the bodies in self._response_body_list , but maybe they
        #   all look the same, so I'll filter the ones that look alike.
        #
        result = [self._response_body_list[0], ]
        for i in self._response_body_list:
            for j in self._response_body_list:

                if relative_distance_ge(i, j, IS_EQUAL_RATIO):
                    # They are equal, we are ok with that
                    continue
                else:
                    # They are no equal, this means that we'll have to add this to the list
                    result.append(j)

        # I don't need these anymore
        self._response_body_list = None

        # And I return the ones I need
        result = list(set(result))
        om.out.debug('The 404 body result database has a length of ' +
                     str(len(result)) + '.')

        self._404_bodies = result
        self._already_analyzed = True
        self._fingerprinted_paths.add(domain_path)
Exemplo n.º 30
0
        Performs a GET and verifies that the response is not a 404.

        :return: None, data is stored in self.output_queue
        '''
        try:
            http_response = self._uri_opener.GET(dir_url, cache=False)
        except:
            pass
        else:
            if is_404(http_response):
                return
            #
            #   Looking good, but lets see if this is a false positive
            #   or not...
            #
            dir_url = base_path.url_join(directory_name + rand_alnum(5) + '/')

            invalid_http_response = self._uri_opener.GET(dir_url,
                                                         cache=False)

            if is_404(invalid_http_response):
                #
                #    Good, the directory_name + rand_alnum(5) return a
                #    404, the original directory_name is not a false positive.
                #
                for fr in self._create_fuzzable_requests(http_response):
                    self.output_queue.put(fr)

                msg = 'dir_file_brute plugin found "%s" with HTTP response ' \
                      'code %s and Content-Length: %s.' \
                
Exemplo n.º 31
0
 def _get_non_exist(self, fuzzable_request):
     base_url = fuzzable_request.get_url().base_url()
     non_existant_domain = 'iDoNotExistPleaseGoAwayNowOrDie' + rand_alnum(4)
     return self._http_get_vhost(base_url, non_existant_domain)
Exemplo n.º 32
0
    def generate_404_knowledge(self, url):
        '''
        Based on a URL, request something that we know is going to be a 404.
        Afterwards analyze the 404's and summarise them.

        :return: A list with 404 bodies.
        '''
        #
        #    This is the case when nobody has properly configured
        #    the object in order to use it.
        #
        if self._uri_opener is None:
            msg = '404 fingerprint database was incorrectly initialized.'
            raise RuntimeError(msg)

        # Get the filename extension and create a 404 for it
        extension = url.get_extension()
        domain_path = url.get_domain_path()

        # the result
        self._response_body_list = []

        #
        #   This is a list of the most common handlers, in some configurations, the 404
        #   depends on the handler, so I want to make sure that I catch the 404 for each one
        #
        handlers = set()
        handlers.update(['py', 'php', 'asp', 'aspx', 'do', 'jsp', 'rb', 'do'])
        handlers.update(
            ['gif', 'htm', 'pl', 'cgi', 'xhtml', 'htmls', 'foobar'])
        if extension:
            handlers.add(extension)

        args_list = []

        for extension in handlers:
            rand_alnum_file = rand_alnum(8) + '.' + extension
            url404 = domain_path.url_join(rand_alnum_file)
            args_list.append(url404)

        self._worker_pool.map(self._send_404, args_list)

        #
        #   I have the bodies in self._response_body_list , but maybe they
        #   all look the same, so I'll filter the ones that look alike.
        #
        result = [
            self._response_body_list[0],
        ]
        for i in self._response_body_list:
            for j in self._response_body_list:

                if relative_distance_ge(i, j, IS_EQUAL_RATIO):
                    # They are equal, we are ok with that
                    continue
                else:
                    # They are no equal, this means that we'll have to add this to the list
                    result.append(j)

        # I don't need these anymore
        self._response_body_list = None

        # And I return the ones I need
        result = list(set(result))
        om.out.debug('The 404 body result database has a length of ' +
                     str(len(result)) + '.')

        self._404_bodies = result
        self._already_analyzed = True
        self._fingerprinted_paths.add(domain_path)
Exemplo n.º 33
0
 def _get_non_exist(self, fuzzable_request):
     base_url = fuzzable_request.get_url().base_url()
     non_existant_domain = 'iDoNotExistPleaseGoAwayNowOrDie' + rand_alnum(4)
     return self._http_get_vhost(base_url, non_existant_domain)
Exemplo n.º 34
0
    def _brute_worker(self, freq, user_field, passwd_field,
                      login_failed_result_list, combination):
        '''
        :param freq: A FuzzableRequest
        :param combination: A tuple with (user, pass) or a pass if this is a
                                password only form.
        '''
        if freq.get_url() not in self._found or not self._stop_on_first:
            freq = freq.copy()
            data_container = freq.get_dc()
            data_container = self._true_extra_fields(data_container,
                                                     user_field, passwd_field)

            # Handle password-only forms!
            if user_field is not None:
                user, pwd = combination
                data_container[user_field][0] = user
                data_container[passwd_field][0] = pwd
            else:
                user = '******'
                pwd = combination
                data_container[passwd_field][0] = pwd

            freq.set_dc(data_container)

            try:
                resp = self._uri_opener.send_mutant(freq,
                                                    cookies=False,
                                                    grep=False)
            except w3afMustStopOnUrlError:
                return
            else:
                body = resp.get_body()
                body = body.replace(user, '').replace(pwd, '')

                if not self._matches_failed_login(body,
                                                  login_failed_result_list):
                    # Ok, this might be a valid combination.
                    # Now test with a new invalid password to ensure our
                    # previous possible found credentials are valid
                    data_container[passwd_field][0] = rand_alnum(8)
                    freq.set_dc(data_container)
                    verif_resp = self._uri_opener.send_mutant(freq,
                                                              cookies=False,
                                                              grep=False)
                    body = verif_resp.get_body()
                    body = body.replace(user, '').replace(pwd, '')

                    if self._matches_failed_login(body,
                                                  login_failed_result_list):
                        freq_url = freq.get_url()
                        self._found.add(freq_url)

                        if user_field is not None:
                            desc = (
                                'Found authentication credentials to: '
                                '"%s". A correct user and password combination'
                                ' is: %s/%s' % (freq_url, user, pwd))
                        else:
                            # There is no user field!
                            desc = ('Found authentication credentials to: '
                                    '"%s". The correct password is: "%s".' %
                                    (freq_url, pwd))

                        v = Vuln.from_fr('Guessable credentials',
                                         desc, severity.HIGH, resp.id,
                                         self.get_name(), freq)
                        v['user'] = user
                        v['pass'] = pwd
                        v['response'] = resp

                        kb.kb.append(self, 'auth', v)

                        om.out.vulnerability(desc, severity=severity.HIGH)
                        return
Exemplo n.º 35
0
def replace_randomize(data):
    return data.replace("RANDOMIZE", rand_alnum(5))