Exemplo n.º 1
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)
Exemplo n.º 2
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)
Exemplo n.º 3
0
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
Exemplo n.º 4
0
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
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
    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])
Exemplo n.º 8
0
    def test_get_file_from_template_false(self):
        success, file_content, file_name = get_file_from_template('swf')

        self.assertFalse(success)
        self.assertTrue(file_name.endswith('.swf'), file_name)
Exemplo n.º 9
0
    def test_get_file_from_template_true(self):
        success, file_content, file_name = get_file_from_template('gif')

        self.assertTrue(success)
        self.assertIn('GIF', file_content)
        self.assertTrue(file_name.endswith('.gif'), file_name)
Exemplo n.º 10
0
    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])