def create_form_params_helper(form_data): """ Creates a dc.Form object from a dict container :param form_data: A list containing dicts representing a form's internal structure :return: A dc.Form object from `form_data` """ new_form_params = FormParameters() for elem_data in form_data: elem_type = elem_data['tagname'] attrs = elem_data.items() if elem_type == 'input': _type = elem_data['type'] if _type == 'radio': new_form_params.add_radio(attrs) elif _type == 'checkbox': new_form_params.add_check_box(attrs) elif _type in ('text', 'hidden'): new_form_params.add_input(attrs) elif elem_type == 'select': new_form_params.add_select(elem_data['name'], elem_data['options']) return new_form_params
def _handle_go_tag_start(self, tag, tag_name, attrs): self._inside_form = True method = attrs.get('method', 'GET').upper() action = attrs.get('href', None) if action is None: action = self._source_url else: action = self._decode_url(action) try: action = self._base_url.url_join(action, encoding=self._encoding) except ValueError: # The URL in the action is invalid, the best thing we can do # is to guess, and our best guess is that the URL will be the # current one. action = self._source_url # Create the form f = FormParameters(encoding=self._encoding, attributes=attrs, hosted_at_url=self._source_url) f.set_method(method) f.set_action(action) self._forms.append(f)
def test_keep_sync(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("type", "text")]) form_params.add_input([("name", "pwd"), ("type", "password")]) form = Form(form_params) self.assertNotIn('address', form_params) self.assertNotIn('address', form) # Add to the form_params form_params['address'] = [''] self.assertIn('address', form_params) self.assertIn('address', form) # Add to the Form object form['company'] = [''] self.assertIn('company', form_params) self.assertIn('company', form) # Del from the Form object del form['address'] self.assertNotIn('address', form) self.assertNotIn('address', form_params) # Del from the FormParams object del form_params['company'] self.assertNotIn('company', form) self.assertNotIn('company', form_params)
def test_mutant_creation_repeated_parameter_name(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "id"), ("value", "")]) form_params.add_field_by_attr_items([("name", "id"), ("value", "")]) form = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://w3af.com/?foo=3'), post_data=form, method='GET') created_mutants = PostDataMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) expected_dcs = [ 'id=def&id=3419', 'id=3419&id=def', 'id=3419&id=abc', 'id=abc&id=3419' ] created_dcs = [str(i.get_dc()) for i in created_mutants] self.assertEqual(set(created_dcs), set(expected_dcs)) token = created_mutants[0].get_token() self.assertEqual(token.get_name(), 'id') self.assertEqual(token.get_original_value(), '') token = created_mutants[2].get_token() self.assertEqual(token.get_name(), 'id') self.assertEqual(token.get_original_value(), '') for m in created_mutants: self.assertIsInstance(m, PostDataMutant) for m in created_mutants: self.assertEqual(m.get_method(), 'GET')
def test_multipart_post(self): boundary, post_data = multipart_encode([ ('a', 'bcd'), ], []) multipart_boundary = 'multipart/form-data; boundary=%s' headers = Headers([('content-length', str(len(post_data))), ('content-type', multipart_boundary % boundary)]) fr = FuzzableRequest.from_parts(self.url, headers=headers, post_data=post_data, method='POST') form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) expected_container = MultipartContainer(form_params) expected_headers = Headers([('content-type', multipart_boundary % boundary)]) self.assertEqual(fr.get_url(), self.url) self.assertEqual(fr.get_headers(), expected_headers) self.assertIn('multipart/form-data', fr.get_headers()['content-type']) self.assertEqual(fr.get_method(), 'POST') self.assertIsInstance(fr.get_raw_data(), MultipartContainer) self.assertEqual(fr.get_raw_data(), expected_container)
def test_multipart_post(self): boundary, post_data = multipart_encode([('a', 'bcd'), ], []) multipart_boundary = 'multipart/form-data; boundary=%s' headers = Headers([('content-length', str(len(post_data))), ('content-type', multipart_boundary % boundary)]) fr = FuzzableRequest.from_parts(self.url, headers=headers, post_data=post_data, method='POST') form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) expected_container = MultipartContainer(form_params) expected_headers = Headers([('content-type', multipart_boundary % boundary)]) self.assertEqual(fr.get_url(), self.url) self.assertEqual(fr.get_headers(), expected_headers) self.assertIn('multipart/form-data', fr.get_headers()['content-type']) self.assertEqual(fr.get_method(), 'POST') self.assertIsInstance(fr.get_raw_data(), MultipartContainer) self.assertEqual(fr.get_raw_data(), expected_container)
def test_login_form_utils(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("type", "text")]) form_params.add_input([("name", "pwd"), ("type", "password")]) form = Form(form_params) self.assertTrue(form.is_login_form()) self.assertFalse(form.is_registration_form()) self.assertFalse(form.is_password_change_form()) self.assertEqual(form.get_parameter_type_count(), (1, 1, 0)) user_token, pass_token = form.get_login_tokens() self.assertEqual(user_token.get_name(), 'username') self.assertEqual(pass_token.get_name(), 'pwd') self.assertEqual(user_token.get_value(), '') self.assertEqual(pass_token.get_value(), '') form.set_login_username('andres') self.assertEqual(form['username'][0], 'andres') self.assertEqual(form['pwd'][0], '') form.set_login_username('pablo') form.set_login_password('long-complex') self.assertEqual(form['username'][0], 'pablo') self.assertEqual(form['pwd'][0], 'long-complex') self.assertIs(form.get_form_params(), form_params)
def create_vuln(self): v = super(FileUploadTemplate, self).create_vuln() form_params = FormParameters() for file_var in self.file_vars: form_params.add_file_input([("name", file_var), ("type", "file")]) for token in self.data.iter_tokens(): if token.get_name() in self.file_vars: continue form_params.add_input([("name", token.get_value()), ("type", "text")]) mpc = MultipartContainer(form_params) freq = FuzzableRequest(self.url, method=self.method, post_data=mpc) mutant = PostDataMutant(freq) mutant.set_dc(mpc) mutant.set_token((self.vulnerable_parameter, 0)) # User configured settings v['file_vars'] = self.file_vars v['file_dest'] = self.file_dest v.set_mutant(mutant) return v
def test_mutant_creation_repeated_parameter_name(self): form_params = FormParameters() form_params.add_input([("name", "id"), ("value", "")]) form_params.add_input([("name", "id"), ("value", "")]) form = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://w3af.com/?foo=3'), post_data=form, method='GET') created_mutants = PostDataMutant.create_mutants(freq, self.payloads, [], False, self.fuzzer_config) expected_dcs = ['id=def&id=3419', 'id=3419&id=def', 'id=3419&id=abc', 'id=abc&id=3419'] created_dcs = [str(i.get_dc()) for i in created_mutants] self.assertEqual(set(created_dcs), set(expected_dcs)) token = created_mutants[0].get_token() self.assertEqual(token.get_name(), 'id') self.assertEqual(token.get_original_value(), '') token = created_mutants[2].get_token() self.assertEqual(token.get_name(), 'id') self.assertEqual(token.get_original_value(), '') for m in created_mutants: self.assertIsInstance(m, PostDataMutant) for m in created_mutants: self.assertEqual(m.get_method(), 'GET')
def test_login_form_utils(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'type': 'text'}) form_params.add_field_by_attrs({'name': 'pwd', 'type': 'password'}) form = Form(form_params) self.assertTrue(form.is_login_form()) self.assertFalse(form.is_registration_form()) self.assertFalse(form.is_password_change_form()) self.assertEqual(form.get_parameter_type_count(), (1, 1, 0)) user_token, pass_token = form.get_login_tokens() self.assertEqual(user_token.get_name(), 'username') self.assertEqual(pass_token.get_name(), 'pwd') self.assertEqual(user_token.get_value(), '') self.assertEqual(pass_token.get_value(), '') form.set_login_username('andres') self.assertEqual(form['username'][0], 'andres') self.assertEqual(form['pwd'][0], '') form.set_login_username('pablo') form.set_login_password('long-complex') self.assertEqual(form['username'][0], 'pablo') self.assertEqual(form['pwd'][0], 'long-complex') self.assertIs(form.get_form_params(), form_params)
def test_store_fuzzable_request_two(self): ds = DiskSet() # Add a simple fr, without post-data fr = FuzzableRequest(URL('http://example.com/?id=1')) ds.add(fr) # Add a fr with post-data form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "abc")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) fr = FuzzableRequest.from_form(form) ds.add(fr) # Compare stored_fr = ds[1] self.assertEqual(stored_fr, fr) self.assertIsNot(stored_fr, fr)
def _create_instance_from_form_params(data_container_cls, params): form_params = FormParameters() for param_name, param_value in params.iteritems(): form_params.add_field_by_attrs({'name': param_name, 'value': param_value}) return data_container_cls(form_params)
def test_keep_sync(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'type': 'text'}) form_params.add_field_by_attrs({'name': 'pwd', 'type': 'password'}) form = Form(form_params) self.assertNotIn('address', form_params) self.assertNotIn('address', form) # Add to the form_params form_params['address'] = [''] self.assertIn('address', form_params) self.assertIn('address', form) # Add to the Form object form['company'] = [''] self.assertIn('company', form_params) self.assertIn('company', form) # Del from the Form object del form['address'] self.assertNotIn('address', form) self.assertNotIn('address', form_params) # Del from the FormParams object del form_params['company'] self.assertNotIn('company', form) self.assertNotIn('company', form_params)
def test_is_suitable(self): url = URL('http://www.w3af.com/') headers = Headers([('content-type', 'text/html')]) res = HTTPResponse(200, 'body', headers, url, url) # False because no cookie is set and no QS nor post-data url = URL('http://moth/') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req, res) self.assertFalse(suitable) # False because no cookie is set url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req, res) self.assertFalse(suitable) url_sends_cookie = URL( get_w3af_moth_http('/w3af/core/cookie_handler/set-cookie.php')) self.uri_opener.GET(url_sends_cookie) # Still false because it doesn't have any QS or POST data url = URL('http://moth/') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req, res) self.assertFalse(suitable) self.csrf_plugin._strict_mode = True # Still false because of the strict mode url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req, res) self.assertFalse(suitable) # False, no items in post-data url = URL('http://moth/') req = FuzzableRequest(url, method='POST', post_data=URLEncodedForm()) suitable = self.csrf_plugin._is_suitable(req, res) self.assertFalse(suitable) # True, items in DC, POST (passes strict mode) and cookies url = URL('http://moth/') form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'test'), ('type', 'text')]) form = URLEncodedForm(form_params) req = FuzzableRequest(url, method='POST', post_data=form) suitable = self.csrf_plugin._is_suitable(req, res) self.assertTrue(suitable) self.csrf_plugin._strict_mode = False # True now that we have strict mode off, cookies and QS url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req, res) self.assertTrue(suitable)
def test_login_form_utils(self): form = FormParameters() form.add_input([("name", "username"), ("type", "text")]) form.add_input([("name", "pwd"), ("type", "password")]) self.assertTrue(form.is_login_form()) self.assertFalse(form.is_registration_form()) self.assertFalse(form.is_password_change_form()) self.assertEqual(form.get_parameter_type_count(), (1, 1, 0))
def test_sent_post_data(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", """d'z"0""")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form = dc_from_form_params(form_params) f = FuzzableRequest(URL('http://example.com/'), post_data=form) self.assertTrue(f.sent('d%5C%27z%5C%220'))
def test_login_form_utils(self): form = FormParameters() form.add_field_by_attrs({'name': 'username', 'type': 'text'}) form.add_field_by_attrs({'name': 'pwd', 'type': 'password'}) self.assertTrue(form.is_login_form()) self.assertFalse(form.is_registration_form()) self.assertFalse(form.is_password_change_form()) self.assertEqual(form.get_parameter_type_count(), (1, 1, 0))
def _create_instance_from_form_params(data_container_cls, params): form_params = FormParameters() for param_name, param_value in params.iteritems(): form_params.add_field_by_attrs({ 'name': param_name, 'value': param_value }) return data_container_cls(form_params)
def test_cpickle_simple(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'type': 'text'}) form_params.add_field_by_attrs({'name': 'pwd', 'type': 'password'}) form = Form(form_params) pickled_form = cPickle.loads(cPickle.dumps(form)) self.assertEqual(pickled_form.items(), form.items())
def test_cpickle_simple(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("type", "text")]) form_params.add_input([("name", "pwd"), ("type", "password")]) form = Form(form_params) pickled_form = cPickle.loads(cPickle.dumps(form)) self.assertEqual(pickled_form.items(), form.items())
def create_simple_fuzzable_request(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "abc")]) form_params.add_input([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) return FuzzableRequest.from_form(form)
def test_dc_from_form_params_without_files_nor_enctype(self): form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) urlencode_dc = dc_from_form_params(form_params) self.assertIsInstance(urlencode_dc, URLEncodedForm) self.assertEqual(urlencode_dc.get_file_vars(), []) self.assertEqual(urlencode_dc['a'], ['bcd'])
def upload_file(self, _file): form_params = FormParameters() form_params.add_file_input([("name", "uploadedfile")]) form_params.add_input([("name", "MAX_FILE_SIZE"), ("type", "hidden"), ("value", "10000")]) mpc = MultipartContainer(form_params) mpc["uploadedfile"][0] = _file resp = self.opener.POST(self.MOTH_FILE_UP_URL, data=str(mpc), headers=Headers(mpc.get_headers())) self.assertIn("was successfully uploaded", resp.get_body())
def test_is_suitable(self): # False because no cookie is set and no QS nor post-data url = URL('http://moth/') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req) self.assertFalse(suitable) # False because no cookie is set url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req) self.assertFalse(suitable) url_sends_cookie = URL( 'http://moth/w3af/core/cookie_handler/set-cookie.php') self.uri_opener.GET(url_sends_cookie) # Still false because it doesn't have any QS or POST data url = URL('http://moth/') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req) self.assertFalse(suitable) self.csrf_plugin._strict_mode = True # Still false because of the strict mode url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req) self.assertFalse(suitable) # False, no items in post-data url = URL('http://moth/') req = FuzzableRequest(url, method='POST', post_data=URLEncodedForm()) suitable = self.csrf_plugin._is_suitable(req) self.assertFalse(suitable) # True, items in DC, POST (passes strict mode) and cookies url = URL('http://moth/') form_params = FormParameters() form_params.add_input([('name', 'test'), ('type', 'text')]) form = URLEncodedForm(form_params) req = FuzzableRequest(url, method='POST', post_data=form) suitable = self.csrf_plugin._is_suitable(req) self.assertTrue(suitable) self.csrf_plugin._strict_mode = False # True now that we have strict mode off, cookies and QS url = URL('http://moth/?id=3') req = FuzzableRequest(url, method='GET') suitable = self.csrf_plugin._is_suitable(req) self.assertTrue(suitable)
def test_form_copy(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'type': 'text'}) form_params.add_field_by_attrs({'name': 'pwd', 'type': 'password'}) form = Form(form_params) form.set_token(('username', 0)) form_copy = copy.deepcopy(form) self.assertEqual(form.get_token(), form_copy.get_token()) self.assertIsNot(None, form_copy.get_token())
def test_form_copy(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("type", "text")]) form_params.add_input([("name", "pwd"), ("type", "password")]) form = Form(form_params) form.set_token(('username', 0)) form_copy = copy.deepcopy(form) self.assertEqual(form.get_token(), form_copy.get_token()) self.assertIsNot(None, form_copy.get_token())
def test_clean_form_fuzzable_request_form(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "abc")]) form_params.add_input([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) fr = FuzzableRequest.from_form(form) expected = u'(POST)-http://example.com/?id=number!username=string&address=string' self.assertEqual(self.vdb._clean_fuzzable_request(fr), expected)
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())
def test_dc_from_form_params_without_files_with_multipart_enctype(self): form_params = FormParameters() form_params.set_form_encoding('multipart/form-data') form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) mpdc = dc_from_form_params(form_params) self.assertIsInstance(mpdc, MultipartContainer) self.assertEqual(mpdc.get_file_vars(), []) self.assertEqual(mpdc['a'], ['bcd'])
def create_simple_fuzzable_request(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "abc")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) return FuzzableRequest.from_form(form)
def test_mutant_iter_bound_tokens(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'value': '', 'type': 'password'}) form_params.add_field_by_attrs({'name': 'address', 'value': ''}) form = Form(form_params) for form_copy, _ in form.iter_bound_tokens(): self.assertIsInstance(form_copy, Form) self.assertEquals(form_copy.items(), form.items()) self.assertEquals(form_copy.get_parameter_type('username'), INPUT_TYPE_PASSWD)
def test_mutant_smart_fill_simple(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "")]) form_params.add_input([("name", "address"), ("value", "")]) form_params['username'][0] = DataToken('username', '', ('username', 0)) form = Form(form_params) form.smart_fill() self.assertEqual(form['username'], ['', ]) self.assertEqual(form['address'], ['Bonsai Street 123', ]) self.assertIsInstance(form['username'][0], DataToken) self.assertIs(form.get_form_params(), form_params)
def test_mutant_smart_fill_simple(self): form_params = FormParameters() form_params.add_field_by_attrs({'name': 'username', 'value': ''}) form_params.add_field_by_attrs({'name': 'address', 'value': ''}) form_params['username'][0] = DataToken('username', '', ('username', 0)) form = Form(form_params) form.smart_fill() self.assertEqual(form['username'], ['', ]) self.assertEqual(form['address'], ['Bonsai Street 123', ]) self.assertIsInstance(form['username'][0], DataToken) self.assertIs(form.get_form_params(), form_params)
def test_mutant_iter_bound_tokens(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", ""), ("type", "password")]) form_params.add_input([("name", "address"), ("value", "")]) form = Form(form_params) for form_copy, _ in form.iter_bound_tokens(): self.assertIsInstance(form_copy, Form) self.assertEquals(form_copy.items(), form.items()) self.assertEquals(form_copy.get_parameter_type('username'), FormParameters.INPUT_TYPE_PASSWD)
def create_fuzzable_request(_id): url = 'http://example.com/product/1' form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username%s" % _id), ("value", "abc")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form_params.set_action(URL(url)) form_params.set_method('post') form = dc_from_form_params(form_params) return FuzzableRequest.from_form(form)
def create_form_params_helper(form_data): """ Creates a dc.Form object from a dict container :param form_data: A list containing dicts representing a form's internal structure :return: A dc.Form object from `form_data` """ new_form_params = FormParameters() for elem_data in form_data: new_form_params.add_field_by_attrs(elem_data) return new_form_params
def upload_file(self, _file): form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'uploadedfile')]) form_params.add_field_by_attr_items([('name', 'MAX_FILE_SIZE'), ('type', 'hidden'), ('value', '10000')]) mpc = MultipartContainer(form_params) mpc['uploadedfile'][0] = _file resp = self.opener.POST(self.MOTH_FILE_UP_URL, data=str(mpc), headers=Headers(mpc.get_headers())) self.assertIn('was successfully uploaded', resp.get_body())
def from_postdata(cls, headers, post_data): if not MultipartContainer.is_multipart(headers): raise ValueError('No multipart content-type header.') environ = {'REQUEST_METHOD': 'POST'} try: fs = cgi.FieldStorage(fp=StringIO.StringIO(post_data), headers=headers.to_dict(), environ=environ) except ValueError: raise ValueError('Failed to create MultipartContainer.') else: # Please note that the FormParameters is just a container for # the information. # # When the FuzzableRequest is sent the framework calls get_data() # which returns a string version of this object, properly encoded # using multipart/form-data # # To make sure the web application properly decodes the request, we # also include the headers in get_headers() which include the # boundary form_params = FormParameters() for key in fs.list: if key.filename is None: form_params.add_input([('name', key.name), ('type', 'text'), ('value', key.file.read())]) else: form_params.set_file_name(key.name, key.filename) form_params.add_file_input([('name', key.name)]) return cls(form_params)
def test_found_at(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "")]) form_params.add_input([("name", "address"), ("value", "")]) form = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://www.w3af.com/?id=3'), post_data=form, method='PUT') m = PostDataMutant(freq) m.get_dc().set_token(('username', 0)) expected = '"http://www.w3af.com/?id=3", using HTTP method PUT. '\ 'The sent post-data was: "username=&address=" '\ 'which modifies the "username" parameter.' self.assertEqual(m.found_at(), expected)
def test_from_form_POST(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "abc")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) fr = FuzzableRequest.from_form(form) self.assertIs(fr.get_uri(), form.get_action()) self.assertIs(fr.get_raw_data(), form) self.assertEqual(fr.get_method(), 'POST') self.assertEqual(fr.get_uri().querystring, QueryString([('id', ['1'])]))
def test_tmb_variants(self): # 'top-middle-bottom' mode variants def filter_tmb(values): if len(values) > 3: values = (values[0], values[len(values) / 2], values[-1]) return values bigform_data = form_with_radio + form_select_misc clean_data = get_gruped_data(bigform_data) new_bigform = create_form_params_helper(bigform_data) total_variants = 2 * 2 * 3 variants_set = set() for i, form_variant in enumerate(new_bigform.get_variants(mode="tmb")): if i == 0: # First element must be the created `new_bigform` self.assertEquals(id(new_bigform), id(form_variant)) continue for name, values in clean_data.items(): tmb_values = filter_tmb(values) msg = 'Failed to find "%s" in "%s"' % (form_variant[name][0], tmb_values) self.assertTrue(form_variant[name][0] in tmb_values, msg) variants_set.add(repr(form_variant)) # Ensure we actually got the expected number of variants f = FormParameters() expected = min(total_variants, f.TOP_VARIANTS) self.assertEquals(i, expected) # Variants shouldn't appear duplicated self.assertEquals(len(variants_set), expected)
def test_tmb_variants_large(self): """ Note that this test has several changes from test_tmb_variants: * It uses form_select_misc_large, which exceeds the form's TOP_VARIANTS = 15 * Doesn't use filter_tmb since variants are based on a "random pick" """ bigform_data = (form_with_radio + form_select_cars + form_select_misc_large) clean_data = get_grouped_data(bigform_data) new_bigform = create_form_params_helper(bigform_data) total_variants = 2 * 3 * 3 * 3 variants_set = set() variants = [v for v in new_bigform.get_variants(mode=MODE_TMB)] # Please note that this depends completely in form.SEED AND # form.TOP_VARIANTS RANDOM_PICKS = {1: ('volvo', 'black', 'd', 'female'), 2: ('volvo', 'blue', 'i', 'male'), 3: ('volvo', 'blue', 'f', 'female'), 4: ('volvo', 'black', 'g', 'female'), 5: ('volvo', 'black', 'm', 'male'), 6: ('volvo', 'black', 'l', 'male'), 7: ('volvo', 'blue', 'b', 'female'), 8: ('volvo', 'blue', 'e', 'female'), 9: ('volvo', 'black', 'c', 'male'), 10: ('volvo', 'black', 'a', 'female'), 11: ('volvo', 'blue', 'e', 'male'), 12: ('volvo', 'black', 'j', 'male'), 13: ('volvo', 'blue', 'c', 'male'), 14: ('volvo', 'black', 'a', 'male'), 15: ('volvo', 'black', 'i', 'female')} for i, form_variant in enumerate(variants): # First element must be the created `new_bigform` if i == 0: self.assertIs(new_bigform, form_variant) continue option = [] for name, values in clean_data.items(): form_value = form_variant[name][0] option.append(form_value) current_option = RANDOM_PICKS[i] self.assertEqual(tuple(option), current_option) variants_set.add(repr(form_variant)) # Ensure we actually got the expected number of variants f = FormParameters() expected = min(total_variants, f.TOP_VARIANTS) self.assertEquals(len(variants), expected + 1) # Variants shouldn't appear duplicated self.assertEquals(len(variants_set), expected)
def test_all_variants(self): # 'all' mode variants bigform_data = form_with_radio + form_select_misc clean_data = get_grouped_data(bigform_data) new_bigform = create_form_params_helper(bigform_data) total_variants = 2 * 5 * 10 variants_set = set() for i, form_variant in enumerate(new_bigform.get_variants(mode=MODE_ALL)): # First element must be the created `new_bigform` if i == 0: self.assertIs(new_bigform, form_variant) continue for name, all_values in clean_data.items(): self.assertIn(form_variant[name][0], all_values) variants_set.add(repr(form_variant)) # Ensure we actually got the expected number of variants f = FormParameters() expected = min(total_variants, f.TOP_VARIANTS) self.assertEquals(expected, i) # Variants shouldn't duplicated self.assertEquals(expected, len(variants_set))
def create_fuzzable_request(_id): path_count = _id * 5 paths = [rand_alnum(9) for _ in xrange(path_count)] url = 'http://example.com/%s' % '/'.join(paths) form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "abc")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form_params.set_action(URL(url)) form_params.set_method('post') form = dc_from_form_params(form_params) return FuzzableRequest.from_form(form)
def test_tmb_variants(self): # 'top-middle-bottom' mode variants def filter_tmb(values): if len(values) > 3: values = (values[0], values[len(values) / 2], values[-1]) return values bigform_data = form_with_radio + form_select_misc clean_data = get_grouped_data(bigform_data) new_bigform = create_form_params_helper(bigform_data) total_variants = 2 * 2 * 3 variants_set = set() variants = [v for v in new_bigform.get_variants(mode=MODE_TMB)] for i, form_variant in enumerate(variants): # First element must be the created `new_bigform` if i == 0: self.assertIs(new_bigform, form_variant) continue for name, values in clean_data.items(): tmb_values = filter_tmb(values) self.assertIn(form_variant[name][0], tmb_values) variants_set.add(repr(form_variant)) # Ensure we actually got the expected number of variants f = FormParameters() self.assertEquals(len(variants), total_variants + 1) # Variants shouldn't appear duplicated self.assertEquals(len(variants_set), total_variants)
def _handle_form_tag_start(self, tag, tag_name, attrs): """ Handle the form tags. This method also looks if there are "pending inputs" in the self._saved_inputs list and parses them. """ SGMLParser._handle_form_tag_start(self, tag, tag_name, attrs) method = attrs.get('method', 'GET').upper() action = attrs.get('action', None) form_encoding = attrs.get('enctype', DEFAULT_FORM_ENCODING) autocomplete = attrs.get('autocomplete', None) if action is None: action = self._source_url else: action = self._decode_url(action) try: action = self._base_url.url_join(action, encoding=self._encoding) except ValueError: # The URL in the action is invalid, the best thing we can do # is to guess, and our best guess is that the URL will be the # current one. action = self._source_url # Create the form object and store everything for later use form_params = FormParameters(encoding=self._encoding, method=method, action=action, form_encoding=form_encoding, attributes=attrs, hosted_at_url=self._source_url) form_params.set_autocomplete(autocomplete) self._forms.append(form_params) # Now I verify if there are any input tags that were found # outside the scope of a form tag for input_attrs in self._saved_inputs: # Parse them just like if they were found AFTER the # form tag opening self._handle_input_tag_inside_form(tag, 'input', input_attrs) # All parsed, remove them. self._saved_inputs = []
def test_tmb_variants_large(self): """ Note that this test has several changes from test_tmb_variants: * It uses form_select_misc_large, which exceeds the form's TOP_VARIANTS = 15 * Doesn't use filter_tmb since variants are based on a "random pick" """ bigform_data = form_with_radio + form_select_cars + \ form_select_misc_large clean_data = get_gruped_data(bigform_data) new_bigform = create_form_params_helper(bigform_data) total_variants = 2 * 3 * 3 * 3 variants_set = set() # Please note that this depends completely in form.SEED AND # form.TOP_VARIANTS RANDOM_PICKS = {1: ('volvo', 'black', 'd', 'female'), 2: ('volvo', 'blue', 'i', 'male'), 3: ('volvo', 'blue', 'f', 'female'), 4: ('volvo', 'black', 'g', 'female'), 5: ('volvo', 'black', 'm', 'male'), 6: ('volvo', 'black', 'l', 'male'), 7: ('volvo', 'blue', 'b', 'female'), 8: ('volvo', 'blue', 'e', 'female'), 9: ('volvo', 'black', 'c', 'male'), 10: ('volvo', 'black', 'a', 'female'), 11: ('volvo', 'blue', 'e', 'male'), 12: ('volvo', 'black', 'j', 'male'), 13: ('volvo', 'blue', 'c', 'male'), 14: ('volvo', 'black', 'a', 'male'), 15: ('volvo', 'black', 'i', 'female') } for i, form_variant in enumerate(new_bigform.get_variants(mode="tmb")): if i == 0: # First element must be the created `new_bigform` self.assertEquals(id(new_bigform), id(form_variant)) continue for name, values in clean_data.items(): current_random_values = RANDOM_PICKS[i] msg = 'Failed to find "%s" in "%s"' % ( form_variant[name][0], current_random_values) self.assertTrue( form_variant[name][0] in current_random_values, msg) variants_set.add(repr(form_variant)) # Ensure we actually got the expected number of variants f = FormParameters() expected = min(total_variants, f.TOP_VARIANTS) self.assertEquals(i, expected) # Variants shouldn't appear duplicated self.assertEquals(len(variants_set), expected)
def __init__(self, form_params=None): """ :note: I'm wrapping some of the form_params methods in order to provide extra features. I deliberately avoided a generic "forward-all" wrapper here, since I want to be in control and really know what is going to be forwarded to self.form_params. :param form_params: An instance of FormParameters """ form_params = FormParameters() if form_params is None else form_params self.form_params = form_params # We don't send any value in init_val because we're forwarding almost # all magic methods (__getitem__, __setitem__, etc.) to the # self.form_params attribute, which helps keep the two (FormParameters # and Form) instances in sync super(Form, self).__init__(init_val=(), encoding=form_params.get_encoding())
def test_store_fuzzable_request(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "abc")]) form_params.add_input([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/?id=1')) form_params.set_method('post') form = dc_from_form_params(form_params) fr = FuzzableRequest.from_form(form) ds = DiskSet() ds.add(fr) stored_fr = ds[0] self.assertEqual(stored_fr, fr) self.assertIsNot(stored_fr, fr)
def test_dc_from_form_params_without_files_with_multipart_enctype(self): form_params = FormParameters() form_params.set_method('POST') form_params.set_form_encoding('multipart/form-data') form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) mpdc = dc_from_form_params(form_params) self.assertIsInstance(mpdc, MultipartContainer) self.assertEqual(mpdc.get_file_vars(), []) self.assertEqual(mpdc['a'], ['bcd'])
def test_from_form_GET(self): form_params = FormParameters() form_params.add_input([("name", "username"), ("value", "abc")]) form_params.add_input([("name", "address"), ("value", "")]) form_params.set_action(URL('http://example.com/')) form_params.set_method('GET') form = dc_from_form_params(form_params) fr = FuzzableRequest.from_form(form) expected_url = 'http://example.com/?username=abc&address=' self.assertEqual(fr.get_uri().url_string, expected_url) self.assertEqual(fr.get_uri().querystring, 'username=abc&address=') self.assertEqual(fr.get_method(), 'GET') self.assertIsNot(fr.get_raw_data(), form) self.assertIsInstance(fr.get_uri().querystring, URLEncodedForm) uri_1 = fr.get_uri() uri_2 = fr.get_uri() self.assertIs(uri_1, uri_2)
def test_dc_from_form_params_with_files(self): form_params = FormParameters() form_params.add_field_by_attr_items([('name', 'b'), ('type', 'file')]) form_params.add_field_by_attr_items([('name', 'a'), ('type', 'text'), ('value', 'bcd')]) form_params.set_file_name('b', 'hello.txt') mpdc = dc_from_form_params(form_params) self.assertIsInstance(mpdc, MultipartContainer) self.assertEqual(mpdc.get_file_vars(), ['b']) self.assertEqual(mpdc['a'], ['bcd'])