コード例 #1
0
    def test_encode_two_files(self):
        _files = [('file1', NamedStringIO('hello world', name='test1.txt')),
                  ('file2', NamedStringIO('bye bye', name='test2.txt'))]

        _, encoded = multipart_encode((), _files, boundary='fakeboundary')

        EXPECTED = '--fakeboundary\r\nContent-Disposition: form-data;' \
                   ' name="file1"; filename="test1.txt"\r\n' \
                   'Content-Type: text/plain\r\n\r\nhello world\r\n' \
                   '--fakeboundary\r\nContent-Disposition: form-data;' \
                   ' name="file2"; filename="test2.txt"\r\n' \
                   'Content-Type: text/plain\r\n\r\nbye bye\r\n' \
                   '--fakeboundary--\r\n\r\n'
        self.assertEqual(EXPECTED, encoded)
コード例 #2
0
    def _upload_shell_and_confirm_exec(self, vuln_obj, file_content,
                                       file_name):
        """
        :return: True if we were able to upload and the remote server actually
                 executes the remote file.
        """
        # The vuln was saved to the kb as a vuln object
        method = vuln_obj.get_method()
        exploit_dc = vuln_obj.get_dc()

        # Create a file that will be uploaded
        file_handler = NamedStringIO(file_content, file_name)

        for file_var_name in vuln_obj['file_vars']:
            # the [0] was added here to support repeated parameter names
            exploit_dc[file_var_name][0] = file_handler

        # Upload the file
        http_method = getattr(self._uri_opener, method)
        http_method(vuln_obj.get_url(), exploit_dc)

        # Call the uploaded script with an empty value in cmd parameter
        # this will return the shell_handler.SHELL_IDENTIFIER if success
        dst = vuln_obj['file_dest']
        self._exploit = dst.get_domain_path().url_join(file_name)
        self._exploit.querystring = u'cmd='
        response = self._uri_opener.GET(self._exploit)

        if shell_handler.SHELL_IDENTIFIER in response.get_body():
            return True

        return False
コード例 #3
0
ファイル: file_upload.py プロジェクト: chenbremer/w3af-1
    def audit(self, freq, orig_response, debugging_id):
        """
        Searches for file upload vulns.

        :param freq: A FuzzableRequest
        :param orig_response: The HTTP response associated with the fuzzable request
        :param debugging_id: A unique identifier for this call to audit()
        """
        if freq.get_method().upper() != 'POST' or not freq.get_file_vars():
            return

        # Unique payload for the files we upload
        payload = rand_alnum(239)

        for file_parameter in freq.get_file_vars():
            for extension in self._extensions:

                _, file_content, file_name = get_template_with_payload(
                    extension, payload)

                # Only file handlers are passed to the create_mutants functions
                named_stringio = NamedStringIO(file_content, file_name)
                mutants = create_mutants(freq, [named_stringio],
                                         fuzzable_param_list=[file_parameter])

                for mutant in mutants:
                    mutant.uploaded_file_name = file_name
                    mutant.extension = extension
                    mutant.file_content = file_content
                    mutant.file_payload = payload

                self._send_mutants_in_threads(self._uri_opener.send_mutant,
                                              mutants,
                                              self._analyze_result,
                                              debugging_id=debugging_id)
コード例 #4
0
 def test_file_stringio_upload(self):
     data = {
         "MAX_FILE_SIZE": "10000",
         "uploadedfile": NamedStringIO('file content', name='test.txt')
     }
     resp = self.opener.open(self.MOTH_FILE_UP_URL, data)
     self.assertTrue('was successfully uploaded' in resp.read())
コード例 #5
0
    def create_mutants(freq, mutant_str_list, fuzzable_param_list, append,
                       fuzzer_config):
        """
        This is a very important method which is called in order to create
        mutants. Usually called from fuzzer.py module.
        """
        if not 'fuzz_form_files' in fuzzer_config:
            return []

        if not isinstance(freq, HTTPPostDataRequest):
            return []

        file_vars = freq.get_file_vars()
        if not file_vars:
            return []

        fake_file_objs = []
        ext = fuzzer_config['fuzzed_files_extension']

        for mutant_str in mutant_str_list:
            if isinstance(mutant_str, basestring):
                # I have to create the NamedStringIO with a "name".
                # This is needed for MultipartPostHandler
                fname = "%s.%s" % (rand_alpha(7), ext)
                str_file = NamedStringIO(mutant_str, name=fname)
                fake_file_objs.append(str_file)

        res = Mutant._create_mutants_worker(freq, FileContentMutant,
                                            fake_file_objs, file_vars, append,
                                            fuzzer_config)
        return res
コード例 #6
0
ファイル: file_upload.py プロジェクト: binarever/tools
    def _upload_shell_and_confirm_exec(self, vuln_obj, file_content,
                                       file_name):
        """
        :return: True if we were able to upload and the remote server actually
                 executes the remote file.
        """
        mutant = vuln_obj.get_mutant()
        mutant = mutant.copy()

        # Create a file that will be uploaded
        file_handler = NamedStringIO(file_content, file_name)
        mutant.set_token_value(file_handler)

        # For the files which are not in the target, set something smart.
        mutant.get_dc().smart_fill()

        # Upload the file
        self._uri_opener.send_mutant(mutant)

        # Call the uploaded script with an empty value in cmd parameter
        # this will return the shell_handler.SHELL_IDENTIFIER if success
        dst = vuln_obj['file_dest']
        exploit_url = dst.get_domain_path().url_join(file_name)
        exploit_url.querystring = u'cmd='
        response = self._uri_opener.GET(exploit_url)

        if shell_handler.SHELL_IDENTIFIER in response.get_body():
            return exploit_url

        return None
コード例 #7
0
ファイル: file_upload.py プロジェクト: Adastra-thw/Tortazo
    def _verify_vuln(self, vuln_obj):
        """
        This command verifies a vuln. This is really hard work! :P

        :param vuln_obj: The vuln to exploit.
        :return : True if vuln can be exploited.
        """
        # The vuln was saved to the kb as a vuln object
        url = vuln_obj.get_url()
        method = vuln_obj.get_method()
        exploit_dc = vuln_obj.get_dc()

        # Create a file that will be uploaded
        extension = url.get_extension()
        path, file_name = self._create_file(extension)
        file_content = open(os.path.join(path, file_name), "r").read()
        file_handler = NamedStringIO(file_content, file_name)
        
        #   If there are files,
        if 'file_vars' in vuln_obj:
            #
            #   Upload the file
            #
            for file_var_name in vuln_obj['file_vars']:
                # the [0] was added here to support repeated parameter names
                exploit_dc[file_var_name][0] = file_handler
            http_method = getattr(self._uri_opener, method)
            response = http_method(vuln_obj.get_url(), exploit_dc)

            # Call the uploaded script with an empty value in cmd parameter
            # this will return the shell_handler.SHELL_IDENTIFIER if success
            dst = vuln_obj['file_dest']
            self._exploit = dst.get_domain_path().url_join(file_name)
            self._exploit.querystring = u'cmd='
            response = self._uri_opener.GET(self._exploit)

            # Clean-up
            file_handler.close()
            os.remove(os.path.join(path, file_name))

            if shell_handler.SHELL_IDENTIFIER in response.get_body():
                return True

        #   If we got here, there is nothing positive to report
        return False
コード例 #8
0
ファイル: file_upload.py プロジェクト: intfrr/Tortazo
    def _verify_vuln(self, vuln_obj):
        """
        This command verifies a vuln. This is really hard work! :P

        :param vuln_obj: The vuln to exploit.
        :return : True if vuln can be exploited.
        """
        # The vuln was saved to the kb as a vuln object
        url = vuln_obj.get_url()
        method = vuln_obj.get_method()
        exploit_dc = vuln_obj.get_dc()

        # Create a file that will be uploaded
        extension = url.get_extension()
        path, file_name = self._create_file(extension)
        file_content = open(os.path.join(path, file_name), "r").read()
        file_handler = NamedStringIO(file_content, file_name)

        #   If there are files,
        if 'file_vars' in vuln_obj:
            #
            #   Upload the file
            #
            for file_var_name in vuln_obj['file_vars']:
                # the [0] was added here to support repeated parameter names
                exploit_dc[file_var_name][0] = file_handler
            http_method = getattr(self._uri_opener, method)
            response = http_method(vuln_obj.get_url(), exploit_dc)

            # Call the uploaded script with an empty value in cmd parameter
            # this will return the shell_handler.SHELL_IDENTIFIER if success
            dst = vuln_obj['file_dest']
            self._exploit = dst.get_domain_path().url_join(file_name)
            self._exploit.querystring = u'cmd='
            response = self._uri_opener.GET(self._exploit)

            # Clean-up
            file_handler.close()
            os.remove(os.path.join(path, file_name))

            if shell_handler.SHELL_IDENTIFIER in response.get_body():
                return True

        #   If we got here, there is nothing positive to report
        return False
コード例 #9
0
    def test_encode_file_null(self):
        _files = [('file', NamedStringIO('\0hello world', name='test.txt'))]

        _, encoded = multipart_encode((), _files, boundary='fakeboundary')

        EXPECTED = '--fakeboundary\r\nContent-Disposition: form-data; name="file";'\
                   ' filename="test.txt"\r\nContent-Type: text/plain\r\n\r\n\x00'\
                   'hello world\r\n--fakeboundary--\r\n\r\n'
        self.assertEqual(EXPECTED, encoded)
コード例 #10
0
    def test_encode_vars_files(self):
        _vars = [('a', 'b')]
        _files = [('file', NamedStringIO('file content', name='test.txt'))]

        _, encoded = multipart_encode(_vars, _files, boundary='fakeboundary')

        EXPECTED = '--fakeboundary\r\nContent-Disposition: form-data; name="a"'\
                   '\r\n\r\nb\r\n--fakeboundary\r\nContent-Disposition: form-data;'\
                   ' name="file"; filename="test.txt"\r\nContent-Type: text/plain'\
                   '\r\n\r\nfile content\r\n--fakeboundary--\r\n\r\n'
        self.assertEqual(EXPECTED, encoded)
コード例 #11
0
ファイル: file_token.py プロジェクト: vasubesimple/w3af
    def build_file(self, value):

        if isinstance(value, basestring):
            _, file_content, fname = get_template_with_payload(
                self._extension, value)

            # I have to create the NamedStringIO with a "name",
            # required for MultipartContainer to properly encode this as
            # multipart/post
            return NamedStringIO(file_content, name=fname)

        return value
コード例 #12
0
def smart_fill_file(var_name, file_name):
    """
    This function will return a NamedStringIO, ready to use in multipart forms.

    The contents of the file and its extension are carefully chosen to try to
    go through any form filters the web application might be implementing.
    """
    extension = guess_extension(var_name, file_name)
    _, file_content, file_name = get_file_from_template(extension)

    # I have to create the NamedStringIO with a "name",
    # required for MultipartContainer to properly encode this as multipart/post
    return NamedStringIO(file_content, name=file_name)
コード例 #13
0
ファイル: mutant.py プロジェクト: intfrr/Tortazo
def mutant_smart_fill(freq, dc_copy, ignore_pname, ignore_index,
                      fuzzer_config):
    """
    :param freq: The fuzzable request (original request instance) we're fuzzing
    :param ignore_pname: A parameter name to ignore
    :param ignore_index: The index we want to ignore

    :return: A data container that has been filled using smart_fill, ignoring
             the parameters that I'm fuzzing and filling the file inputs with
             valid image file.
    """
    for var_name_dc in dc_copy:
        for element_index_dc, element_value_dc in enumerate(
                dc_copy[var_name_dc]):

            if (var_name_dc, element_index_dc) == (ignore_pname, ignore_index):
                continue

            if dc_copy.get_type(var_name_dc) in AVOID_FILLING_FORM_TYPES:
                continue

            #   Fill only if the parameter does NOT have a value set.
            #
            #   The reason of having this already set would be that the form
            #   has something like this:
            #
            #   <input type="text" name="p" value="foobar">
            #
            if dc_copy[var_name_dc][element_index_dc] == '':
                #
                #   Fill it smartly
                #
                dc_copy[var_name_dc][element_index_dc] = smart_fill(
                    var_name_dc)

    # Please see the comment above (search for __HERE__) for an explanation
    # of what we are doing here:
    for var_name in freq.get_file_vars():

        # Try to upload a valid file
        extension = fuzzer_config.get('fuzz_form_files') or 'gif'
        success, file_content, file_name = get_file_from_template(extension)

        # I have to create the NamedStringIO with a "name",
        # required for MultipartPostHandler
        str_file = NamedStringIO(file_content, name=file_name)

        # TODO: Is this hard-coded [0] enough?
        dc_copy[var_name][0] = str_file

    return dc_copy
コード例 #14
0
    def test_upload_file_using_fuzzable_request(self):
        form_params = FormParameters()
        form_params.add_file_input([('name', 'uploadedfile')])
        form_params['uploadedfile'][0] = NamedStringIO('file content',
                                                       name='test.txt')
        form_params.add_input([('name', 'MAX_FILE_SIZE'), ('type', 'hidden'),
                               ('value', '10000')])

        mpc = MultipartContainer(form_params)

        freq = FuzzableRequest(self.MOTH_FILE_UP_URL,
                               post_data=mpc,
                               method='POST')

        resp = self.opener.send_mutant(freq)

        self.assertIn('was successfully uploaded', resp.get_body())
コード例 #15
0
    def test_multipart_post_with_filename(self):
        fake_file = NamedStringIO('def', name='hello.txt')
        vars = [('a', 'bcd'), ]
        files = [('b', fake_file)]
        boundary, post_data = multipart_encode(vars, files)
        multipart_boundary = MultipartContainer.MULTIPART_HEADER

        headers = Headers([('content-length', str(len(post_data))),
                           ('content-type', multipart_boundary % boundary)])

        mpc = MultipartContainer.from_postdata(headers, post_data)

        self.assertIsInstance(mpc, MultipartContainer)
        self.assertIn('a', mpc)
        self.assertEqual(mpc['a'], ['bcd'])
        self.assertEqual(mpc.get_file_vars(), ['b'])
        self.assertEqual(mpc.get_parameter_type('a'), 'text')
        self.assertEqual(mpc.get_parameter_type('b'), 'file')
        self.assertEqual(mpc.get_file_name('b'), 'hello.txt')
コード例 #16
0
ファイル: file_token.py プロジェクト: llcoolj1/w3af-kali
    def build_file(self, value):
        #
        # We don't want to create a new file if value is already a NamedStringIO
        # but if it is a string, we should create a new NamedStringIO instance
        # and return it
        #
        # The last "not isinstance" is important due to the fact that
        # NamedStringIO is a basestring subclass
        #
        if isinstance(value, basestring) and not isinstance(value, NamedStringIO):
            _, file_content, fname = get_template_with_payload(self._extension,
                                                               value)

            # I have to create the NamedStringIO with a "name",
            # required for MultipartContainer to properly encode this as
            # multipart/post
            return NamedStringIO(file_content, name=fname)

        return value
コード例 #17
0
ファイル: file_upload.py プロジェクト: webvul/webfuzzer
    def audit(self, freq, orig_response):
        """
        Searches for file upload vulns.

        :param freq: A FuzzableRequest
        """
        if freq.get_method().upper() != 'POST' or not freq.get_file_vars():
            return

        for file_parameter in freq.get_file_vars():
            for extension in self._extensions:

                _, file_content, file_name = get_file_from_template(extension)

                # Only file handlers are passed to the create_mutants functions
                named_stringio = NamedStringIO(file_content, file_name)
                mutants = create_mutants(freq, [named_stringio],
                                         fuzzable_param_list=[file_parameter])

                for mutant in mutants:
                    mutant.uploaded_file_name = file_name

                self._send_mutants_in_threads(self._uri_opener.send_mutant,
                                              mutants, self._analyze_result)
コード例 #18
0
ファイル: test_mutant.py プロジェクト: webvul/webfuzzer
    def test_mutant_creation_post_data(self):
        form_params = FormParameters()
        form_params.add_field_by_attr_items([("name", "username"), ("value", "")])
        form_params.add_field_by_attr_items([("name", "address"), ("value", "")])
        form_params.add_field_by_attr_items([("name", "image"), ("type", "file")])

        form = MultipartContainer(form_params)
        freq = FuzzableRequest(self.url, post_data=form)

        ph = 'w3af.core.data.constants.file_templates.file_templates.rand_alpha'

        with patch(ph) as mock_rand_alpha:
            mock_rand_alpha.return_value = 'upload'
            generated_mutants = PostDataMutant.create_mutants(freq,
                                                              self.payloads, [],
                                                              False,
                                                              self.fuzzer_config)

        self.assertEqual(len(generated_mutants), 6, generated_mutants)

        _, gif_file_content, _ = get_file_from_template('gif')
        gif_named_stringio = NamedStringIO(gif_file_content, 'upload.gif')

        expected_forms = []

        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = [gif_named_stringio]
        form['username'] = ['def']
        form['address'] = ['Bonsai Street 123']
        expected_forms.append(form)

        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = [gif_named_stringio]
        form['username'] = ['abc']
        form['address'] = ['Bonsai Street 123']
        expected_forms.append(form)

        # TODO: Please note that these two multipart forms are a bug, since
        #       they should never be created by PostDataMutant.create_mutants
        #       (they are not setting the image as a file, just as a string)
        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = ['def']
        form['username'] = ['John8212']
        form['address'] = ['Bonsai Street 123']
        expected_forms.append(form)

        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = ['abc']
        form['username'] = ['John8212']
        form['address'] = ['Bonsai Street 123']
        expected_forms.append(form)
        #
        # TODO: /end
        #

        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = [gif_named_stringio]
        form['username'] = ['John8212']
        form['address'] = ['abc']
        expected_forms.append(form)

        form = MultipartContainer(copy.deepcopy(form_params))
        form['image'] = [gif_named_stringio]
        form['username'] = ['John8212']
        form['address'] = ['def']
        expected_forms.append(form)

        boundary = get_boundary()
        noop = '1' * len(boundary)

        expected_data = [encode_as_multipart(f, boundary) for f in expected_forms]
        expected_data = set([s.replace(boundary, noop) for s in expected_data])

        generated_forms = [m.get_dc() for m in generated_mutants]
        generated_data = [str(f).replace(f.boundary, noop) for f in generated_forms]

        self.assertEqual(expected_data, set(generated_data))

        str_file = generated_forms[0]['image'][0]
        self.assertIsInstance(str_file, NamedStringIO)
        self.assertEqual(str_file.name[-4:], '.gif')
        self.assertEqual(gif_file_content, str_file)

        str_file = generated_forms[1]['image'][0]
        self.assertIsInstance(str_file, NamedStringIO)
        self.assertEqual(str_file.name[-4:], '.gif')
        self.assertEqual(gif_file_content, str_file)

        self.assertIn('name="image"; filename="upload.gif"', generated_data[0])
コード例 #19
0
 def test_stringio_upload(self):
     _file = NamedStringIO('file content', name='test.txt')
     self.upload_file(_file)
コード例 #20
0
 def test_named_string_io(self):
     content = 'content'
     name = 'name'
     ns_io = NamedStringIO(content, name)
     self.assertEqual(str(ns_io), content)
コード例 #21
0
    def test_generate_all(self):
        fuzzer_config = {
            'fuzz_form_files': True,
            'fuzzed_files_extension': 'gif'
        }

        form_params = FormParameters()
        form_params.set_method('POST')
        form_params.set_action(self.url)
        form_params.add_field_by_attr_items([("name", "username"),
                                             ("value", "")])
        form_params.add_field_by_attr_items([("name", "address"),
                                             ("value", "")])
        form_params.add_field_by_attr_items([("name", "image"),
                                             ("type", "file")])

        form = MultipartContainer(form_params)
        freq = FuzzableRequest.from_form(form)

        ph = 'w3af.core.data.constants.file_templates.file_templates.rand_alpha'

        with patch(ph) as mock_rand_alpha:
            mock_rand_alpha.return_value = 'upload'
            generated_mutants = FileContentMutant.create_mutants(
                freq, self.payloads, [], False, fuzzer_config)

        self.assertEqual(len(generated_mutants), 2, generated_mutants)

        _, file_payload_abc, _ = get_template_with_payload('gif', 'abc')
        _, file_payload_def, _ = get_template_with_payload('gif', 'def')

        file_abc = NamedStringIO(file_payload_abc, 'upload.gif')
        file_def = NamedStringIO(file_payload_def, 'upload.gif')

        form_1 = MultipartContainer(copy.deepcopy(form_params))
        form_2 = MultipartContainer(copy.deepcopy(form_params))

        form_1['image'] = [file_abc]
        form_1['username'] = ['John8212']
        form_1['address'] = ['Bonsai Street 123']

        form_2['image'] = [file_def]
        form_2['username'] = ['John8212']
        form_2['address'] = ['Bonsai Street 123']

        expected_forms = [form_1, form_2]

        boundary = get_boundary()
        noop = '1' * len(boundary)

        expected_data = [
            encode_as_multipart(f, boundary) for f in expected_forms
        ]
        expected_data = set([s.replace(boundary, noop) for s in expected_data])

        generated_forms = [m.get_dc() for m in generated_mutants]
        generated_data = [
            str(f).replace(f.boundary, noop) for f in generated_forms
        ]

        self.assertEqual(expected_data, set(generated_data))

        str_file = generated_forms[0]['image'][0].get_value()
        self.assertIsInstance(str_file, NamedStringIO)
        self.assertEqual(str_file.name[-4:], '.gif')
        self.assertEqual(file_payload_abc, str_file)

        str_file = generated_forms[1]['image'][0].get_value()
        self.assertIsInstance(str_file, NamedStringIO)
        self.assertEqual(str_file.name[-4:], '.gif')
        self.assertEqual(file_payload_def, str_file)

        self.assertIn('name="image"; filename="upload.gif"', generated_data[0])