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_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_with_plus_value(self): """ This test verifies that a fix for the bug identified while scanning demo.testfire.net is still working as expected. The issue was that the site had a form that looked like: <form action="/xyz"> <intput name="foo" value="bar+spam" type="hidden"> <intput name="eggs" type="text"> ... </form> And when trying to send a request to that form the "+" in the value was sent as %20. The input was an .NET's EVENTVALIDATION thus it was impossible to find any bugs in the "eggs" parameter. Please note that this is just a partial test, since there is much more going on in w3af than just creating a form and encoding it. A functional test for this issue can be found at test_special_chars.py """ form_with_plus = [{ 'tagname': 'input', 'name': 'foo', 'type': 'hidden', 'value': 'bar+spam' }, { 'tagname': 'input', 'name': 'eggs', 'type': 'text' }] form = URLEncodedForm(create_form_params_helper(form_with_plus)) self.assertEqual(str(form), 'eggs=&foo=bar%2Bspam')
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_from_postdata_no_post_data(self): headers = Headers([('content-type', URLEncodedForm.ENCODING)]) post_data = '' form = URLEncodedForm.from_postdata(headers, post_data) self.assertEqual(len(form), 0)
def test_mutant_creation_qs_and_postdata(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "")]) form_params.add_field_by_attr_items([("name", "password"), ("value", "")]) url = URL('http://moth/foo.bar?action=login') form = URLEncodedForm(form_params) freq = FuzzableRequest(url, post_data=form) created_mutants = PostDataMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) created_dcs = [str(i.get_dc()) for i in created_mutants] expected_dcs = [ 'username=abc&password=FrAmE30.', 'username=John8212&password=abc', 'username=def&password=FrAmE30.', 'username=John8212&password=def' ] self.assertEqual(created_dcs, expected_dcs) for m in created_mutants: self.assertEqual(m.get_uri(), url)
def test_from_url_keep_form(self): o = URL('http://w3af.com/foo/bar.txt') o.querystring = URLEncodedForm() u = URL.from_URL(o) self.assertIsInstance(u.querystring, URLEncodedForm) self.assertIsNot(u.querystring, o.querystring) self.assertEqual(u.querystring, o.querystring)
def test_POST(self): url = URL(get_moth_http('/audit/xss/simple_xss_form.py')) data = URLEncodedForm() data['text'] = ['123456abc'] http_response = self.uri_opener.POST(url, data, cache=False) self.assertIn('123456abc', http_response.body)
def test_form_str_special_chars_1(self): form_data = [{ 'tagname': 'input', 'type': 'text', 'name': 'abc', 'value': '1"2' }] form = URLEncodedForm(create_form_params_helper(form_data)) self.assertEqual(str(form), 'abc=1%222')
def test_form_str_simple(self): form_data = [{ 'tagname': 'input', 'type': 'text', 'name': 'abc', 'value': '123' }] form = URLEncodedForm(create_form_params_helper(form_data)) self.assertEqual(str(form), 'abc=123')
def test_POST_special_chars(self): url = URL(get_moth_http('/audit/xss/simple_xss_form.py')) test_data = u'abc<def>"-á-' data = URLEncodedForm() data['text'] = [test_data] http_response = self.uri_opener.POST(url, data, cache=False) self.assertIn(test_data, http_response.body)
def test_php_serialized_objects_post_data(self): post_data = 'obj=%s' % base64.b64encode(SERIALIZED_PHP_OBJECTS[1]) headers = Headers([('Content-Type', 'application/x-www-form-urlencoded')]) form = URLEncodedForm.from_postdata(headers, post_data) request = FuzzableRequest(self.url, headers=headers, post_data=form) self.plugin.grep(request, self.response) self.assertEquals(len(kb.kb.get('serialized_object', 'serialized_object')), 1)
def test_form_copy(self): headers = Headers([('content-type', URLEncodedForm.ENCODING)]) post_data = 'a=2&c=3' form = URLEncodedForm.from_postdata(headers, post_data) form.set_token(('a', 0)) form_copy = copy.deepcopy(form) self.assertEqual(form, form_copy) self.assertEqual(form.get_token(), form_copy.get_token()) self.assertIsNot(None, form_copy.get_token())
def test_form_pickle(self): headers = Headers([('content-type', URLEncodedForm.ENCODING)]) post_data = 'a=2&c=3' form = URLEncodedForm.from_postdata(headers, post_data) form.set_token(('a', 0)) pickled_form = cPickle.dumps(form) unpickled_form = cPickle.loads(pickled_form) self.assertEqual(form, unpickled_form) self.assertEqual(form.get_token(), unpickled_form.get_token()) self.assertIsNotNone(unpickled_form.get_token()) self.assertEqual(unpickled_form.keys(), ['a', 'c'])
def test_form_pickle(self): headers = Headers([("content-type", URLEncodedForm.ENCODING)]) post_data = "a=2&c=3" form = URLEncodedForm.from_postdata(headers, post_data) form.set_token(("a", 0)) pickled_form = cPickle.dumps(form) unpickled_form = cPickle.loads(pickled_form) self.assertEqual(form, unpickled_form) self.assertEqual(form.get_token(), unpickled_form.get_token()) self.assertIsNotNone(unpickled_form.get_token()) self.assertEqual(unpickled_form.keys(), ["a", "c"])
def test_mutant_creation(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 = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://www.w3af.com/?id=3'), post_data=form, method='PUT') created_mutants = PostDataMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) expected_dcs = [ 'username=def&address=Bonsai%20Street%20123', 'username=abc&address=Bonsai%20Street%20123', 'username=John8212&address=def', 'username=John8212&address=abc' ] 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(), 'username') self.assertEqual(token.get_original_value(), '') self.assertEqual(token.get_value(), 'abc') token = created_mutants[1].get_token() self.assertEqual(token.get_name(), 'address') self.assertEqual(token.get_original_value(), '') self.assertEqual(token.get_value(), 'abc') token = created_mutants[2].get_token() self.assertEqual(token.get_name(), 'username') self.assertEqual(token.get_original_value(), '') self.assertEqual(token.get_value(), 'def') token = created_mutants[3].get_token() self.assertEqual(token.get_name(), 'address') self.assertEqual(token.get_original_value(), '') self.assertEqual(token.get_value(), 'def') for m in created_mutants: self.assertIsInstance(m, PostDataMutant) for m in created_mutants: self.assertEqual(m.get_method(), 'PUT')
def test_found_at(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 = 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_postdata_ok(self): headers = Headers([("content-type", URLEncodedForm.ENCODING)]) post_data = "a=2&c=3" form = URLEncodedForm.from_postdata(headers, post_data) self.assertEqual(form["a"], ["2"]) self.assertEqual(form["c"], ["3"]) self.assertFalse(form.is_login_form()) self.assertFalse(form.is_password_change_form()) self.assertFalse(form.is_registration_form()) self.assertEqual(form.get_parameter_type("a"), INPUT_TYPE_TEXT) self.assertEqual(form.get_parameter_type("b"), INPUT_TYPE_TEXT)
def test_from_postdata_ok(self): headers = Headers([('content-type', URLEncodedForm.ENCODING)]) post_data = 'a=2&c=3' form = URLEncodedForm.from_postdata(headers, post_data) self.assertEqual(form['a'], ['2']) self.assertEqual(form['c'], ['3']) self.assertFalse(form.is_login_form()) self.assertFalse(form.is_password_change_form()) self.assertFalse(form.is_registration_form()) self.assertEqual(form.get_parameter_type('a'), INPUT_TYPE_TEXT) self.assertEqual(form.get_parameter_type('b'), INPUT_TYPE_TEXT)
def test_mutated_request(self): # Note that I'm sending the serialized object in reverse string order post_data = 'test=1&obj=%s' % base64.b64encode( SERIALIZED_PHP_OBJECTS[1]) headers = Headers([('Content-Type', 'application/x-www-form-urlencoded')]) form = URLEncodedForm.from_postdata(headers, post_data) request = FuzzableRequest(self.url, headers=headers, post_data=form) mutants = create_mutants(request, ['x']) for mutant in mutants: self.plugin.grep(mutant, self.response) self.assertEquals( len(kb.kb.get('serialized_object', 'serialized_object')), 1)
def test_from_postdata_ok(self): headers = Headers([('content-type', URLEncodedForm.ENCODING)]) post_data = 'a=2&c=3' form = URLEncodedForm.from_postdata(headers, post_data) self.assertEqual(form['a'], ['2']) self.assertEqual(form['c'], ['3']) self.assertFalse(form.is_login_form()) self.assertFalse(form.is_password_change_form()) self.assertFalse(form.is_registration_form()) self.assertEqual(form.get_parameter_type('a'), FormParameters.INPUT_TYPE_TEXT) self.assertEqual(form.get_parameter_type('b'), FormParameters.INPUT_TYPE_TEXT)
def test_should_inject_form_hidden(self): form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("type", "text")]) form_params.add_field_by_attr_items([("name", "csrf_token"), ("type", "hidden")]) form = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://www.w3af.com/'), post_data=form, method='PUT') m = PostDataMutant(freq) m.get_dc().set_token(('username', 0)) self.assertFalse(self.plugin._should_inject(m, 'python')) m.get_dc().set_token(('csrf_token', 0)) self.assertTrue(self.plugin._should_inject(m, 'python'))
def test_form_file_post_no_files(self): cf_singleton.save('fuzzable_headers', []) cf_singleton.save('fuzz_cookies', False) cf_singleton.save('fuzz_url_filenames', False) cf_singleton.save('fuzzed_files_extension', 'gif') cf_singleton.save('fuzz_form_files', True) # This one changed cf_singleton.save('fuzz_url_parts', False) form_params = FormParameters() form_params.add_field_by_attr_items([("name", "username"), ("value", "")]) form_params.add_field_by_attr_items([("name", "address"), ("value", "")]) form = URLEncodedForm(form_params) freq = FuzzableRequest(URL('http://www.w3af.com/?id=3'), post_data=form, method='PUT') mutants = create_mutants(freq, self.payloads) self.assertTrue(all(isinstance(m, QSMutant) for m in mutants[:2])) self.assertTrue(all( isinstance(m, PostDataMutant) for m in mutants[4:])) self.assertTrue(all(m.get_method() == 'PUT' for m in mutants)) expected_uris = { 'http://www.w3af.com/?id=abc', 'http://www.w3af.com/?id=def', 'http://www.w3af.com/?id=3', 'http://www.w3af.com/?id=3', 'http://www.w3af.com/?id=3', 'http://www.w3af.com/?id=3' } created_uris = set([i.get_uri().url_string for i in mutants]) self.assertEqual(expected_uris, created_uris) expected_dcs = { 'id=abc', 'id=def', 'username=abc&address=Bonsai%20Street%20123', 'username=def&address=Bonsai%20Street%20123', 'username=John8212&address=abc', 'username=John8212&address=def' } created_dcs = set([str(i.get_dc()) for i in mutants]) self.assertEqual(created_dcs, expected_dcs)
def dc_from_form_params(form_parameters): """ :param form_parameters: The form parameters is the result of parsing HTML, and contains information such as the parameter names and types. :return: An instance of URLEncodedForm or MultipartContainer """ if form_parameters.get_file_vars(): # If it has files, I don't care if the form encoding wasn't specified # we must send it as multipart. return MultipartContainer(form_parameters) if 'multipart' in form_parameters.get_form_encoding().lower(): # If there are no files but the web developer specified the multipart # form encoding, then we'll use multipart also return MultipartContainer(form_parameters) return URLEncodedForm(form_parameters)
def test_form_str_special_chars_2(self): form_data = [{ 'tagname': 'input', 'type': 'text', 'name': 'v', 'value': 'áéíóú' }, { 'tagname': 'input', 'type': 'hidden', 'name': 'c', 'value': 'ñçÑÇ' }] form_params = create_form_params_helper(form_data) form_params.add_field_by_attrs({'name': 'address', 'value': 'bsas'}) form = URLEncodedForm(form_params) self.assertEqual( urllib.unquote(str(form)).decode('utf-8'), u'c=ñçÑÇ&address=bsas&v=áéíóú')
def test_form_str_radio_select(self): form_dict = form_with_radio + form_with_checkbox + form_select_cars form = URLEncodedForm(create_form_params_helper(form_dict)) self.assertEqual(str(form), 'cars=volvo&vehicle=Bike&sex=male')