def __init__(self, url, action, params, ns, meth_name, headers=Headers()): HTTPPostDataRequest.__init__(self, url, headers=headers) self._action = action self._NS = ns self._name = meth_name self.set_parameters(params)
def test_add_HTTPPostDataRequest(self): ds = DiskSet() uri = URL("http://w3af.org/?id=2") hdr = Headers([("Referer", "http://w3af.org/")]) pdr1 = HTTPPostDataRequest(uri, method="GET", headers=hdr) uri = URL("http://w3af.org/?id=3") pdr2 = HTTPPostDataRequest(uri, method="GET", headers=hdr) uri = URL("http://w3af.org/?id=7") pdr3 = HTTPPostDataRequest(uri, method="FOO", headers=hdr) ds.add(pdr1) ds.add(pdr2) ds.add(pdr2) ds.add(pdr1) self.assertEqual(ds[0], pdr1) self.assertEqual(ds[1], pdr2) self.assertFalse(pdr3 in ds) self.assertTrue(pdr2 in ds) self.assertEqual(len(ds), 2) # This forces an internal change in the URL object pdr2.get_url().url_string self.assertTrue(pdr2 in ds)
def __init__(self, xml, uri, method='POST', headers=Headers()): """ :param xml: The original XML string that represents the call to the RPC. """ HTTPPostDataRequest.__init__(self, uri) self._xml = xml
def test_mutant_creation_qs_and_postdata(self): original_form = Form() original_form.add_input([("name", "username"), ("value", "")]) original_form.add_input([("name", "password"), ("value", "")]) url = URL('http://moth/foo.bar?action=login') freq = HTTPPostDataRequest(url, dc=original_form) created_mutants = Mutant.create_mutants(freq, self.payloads, [], False, self.fuzzer_config) expected_dc_lst = [ Form([('username', ['abc']), ('password', ['FrAmE30.'])]), Form([('username', ['def']), ('password', ['FrAmE30.'])]), Form([('username', ['John8212']), ('password', ['abc'])]), Form([('username', ['John8212']), ('password', ['def'])]), ] created_dc_lst = [i.get_dc() for i in created_mutants] created_urls = [i.get_uri() for i in created_mutants] self.assertEqual(created_urls, [ url, ] * 4) self.assertEqual(created_dc_lst, expected_dc_lst)
def test_mutant_creation_repeated_parameter_name(self): form = Form() form.add_input([("name", "id"), ("value", "")]) form.add_input([("name", "id"), ("value", "")]) freq = HTTPPostDataRequest(URL('http://w3af.com/?foo=3'), dc=form, method='GET') created_mutants = PostDataMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) expected_dc_lst = [ Form([('id', ['abc', '3419'])]), Form([('id', ['def', '3419'])]), Form([('id', ['3419', 'abc'])]), Form([('id', ['3419', 'def'])]) ] created_dc_lst = [i.get_dc() for i in created_mutants] self.assertEqual(created_dc_lst, expected_dc_lst) self.assertEqual(created_mutants[0].get_var(), 'id') self.assertEqual(created_mutants[0].get_var_index(), 0) self.assertEqual(created_mutants[0].get_original_value(), '') self.assertEqual(created_mutants[2].get_var(), 'id') self.assertEqual(created_mutants[2].get_var_index(), 1) self.assertEqual(created_mutants[2].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_mutant_creation(self): form = Form() form.add_input([("name", "username"), ("value", "")]) form.add_input([("name", "address"), ("value", "")]) freq = HTTPPostDataRequest(URL('http://www.w3af.com/?id=3'), dc=form, method='PUT') created_mutants = PostDataMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) expected_dc_lst = [ Form([('username', ['abc']), ('address', ['Bonsai Street 123'])]), Form([('username', ['def']), ('address', ['Bonsai Street 123'])]), Form([('username', ['John8212']), ('address', ['abc'])]), Form([('username', ['John8212']), ('address', ['def'])]) ] created_dc_lst = [i.get_dc() for i in created_mutants] self.assertEqual(created_dc_lst, expected_dc_lst) self.assertEqual(created_mutants[0].get_var(), 'username') self.assertEqual(created_mutants[0].get_var_index(), 0) self.assertEqual(created_mutants[0].get_original_value(), '') self.assertEqual(created_mutants[2].get_var(), 'address') self.assertEqual(created_mutants[2].get_var_index(), 0) self.assertEqual(created_mutants[2].get_original_value(), '') for m in created_mutants: self.assertIsInstance(m, PostDataMutant) for m in created_mutants: self.assertEqual(m.get_method(), 'PUT')
def test_mutant_creation_post_data(self): original_form = Form() original_form.add_input([("name", "username"), ("value", "")]) original_form.add_input([("name", "address"), ("value", "")]) original_form.add_file_input([("name", "file"), ("type", "file")]) freq = HTTPPostDataRequest(self.url, dc=original_form) created_mutants = Mutant.create_mutants(freq, self.payloads, [], False, self.fuzzer_config) self.assertEqual(len(created_mutants), 4, created_mutants) expected_username_values = self.payloads + ['John8212'] * 2 expected_address_values = ['Bonsai Street 123'] * 2 + self.payloads expected_file_values = ['GIF89a'] * 4 created_dc_lst = [i.get_dc() for i in created_mutants] generated_username_values = [ dc['username'][0] for dc in created_dc_lst ] generated_address_values = [dc['address'][0] for dc in created_dc_lst] generated_file_values = [dc['file'][0] for dc in created_dc_lst] self.assertEqual(expected_username_values, generated_username_values) self.assertEqual(expected_address_values, generated_address_values) for index, gen_file_value in enumerate(generated_file_values): startswith = gen_file_value.startswith(expected_file_values[index]) self.assertTrue(startswith, gen_file_value) self.assertTrue( all(str_file.name[-4:].startswith('.gif') for str_file in generated_file_values))
def test_not_qs_request(self): fuzzer_config = {'fuzz_cookies': True} freq = HTTPPostDataRequest(URL('http://www.w3af.com/foo/bar')) generated_mutants = CookieMutant.create_mutants( freq, self.payloads, [], False, fuzzer_config) self.assertEqual(len(generated_mutants), 0, generated_mutants)
def test_config_false(self): fuzzer_config = {'fuzz_form_files': False} freq = HTTPPostDataRequest(URL('http://www.w3af.com/foo/bar')) generated_mutants = FileContentMutant.create_mutants( freq, self.payloads, [], False, fuzzer_config) self.assertEqual(len(generated_mutants), 0, generated_mutants)
def test_add_HTTPPostDataRequest(self): ds = DiskSet() uri = URL('http://w3af.org/?id=2') hdr = Headers([('Referer', 'http://w3af.org/')]) pdr1 = HTTPPostDataRequest(uri, method='GET', headers=hdr) uri = URL('http://w3af.org/?id=3') pdr2 = HTTPPostDataRequest(uri, method='GET', headers=hdr) uri = URL('http://w3af.org/?id=7') pdr3 = HTTPPostDataRequest(uri, method='FOO', headers=hdr) ds.add(pdr1) ds.add(pdr2) ds.add(pdr2) ds.add(pdr1) self.assertEqual(ds[0], pdr1) self.assertEqual(ds[1], pdr2) self.assertFalse(pdr3 in ds) self.assertTrue(pdr2 in ds) self.assertEqual(len(ds), 2) # This forces an internal change in the URL object pdr2.get_url().url_string self.assertTrue(pdr2 in ds)
def test_found_at(self): form = Form() form.add_input([("name", "username"), ("value", "")]) form.add_input([("name", "address"), ("value", "")]) freq = HTTPPostDataRequest(URL('http://www.w3af.com/?id=3'), dc=form, method='PUT') m = PostDataMutant(freq) m.set_var('username') 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_mutant_smart_fill_simple(self): original_form = Form() original_form.add_input([("name", "username"), ("value", "")]) original_form.add_input([("name", "address"), ("value", "")]) freq = HTTPPostDataRequest(self.url, dc=original_form) filled_form = mutant_smart_fill(freq, original_form, 'username', 0, self.fuzzer_config) self.assertEqual(id(original_form), id(filled_form)) self.assertEqual(filled_form['username'], [ '', ]) self.assertEqual(filled_form['address'], [ 'Bonsai Street 123', ])
def test_config_true(self): fuzzer_config = { 'fuzz_form_files': True, 'fuzzed_files_extension': 'gif' } form = Form() form.add_input([("name", "username"), ("value", "")]) form.add_input([("name", "address"), ("value", "")]) form.add_file_input([("name", "file"), ("type", "file")]) freq = HTTPPostDataRequest(self.url, dc=form) generated_mutants = FileContentMutant.create_mutants( freq, self.payloads, [], False, fuzzer_config) self.assertNotEqual(len(generated_mutants), 0, generated_mutants)
def test_mutant_smart_fill_with_file(self): original_form = Form() original_form.add_input([("name", "username"), ("value", "")]) original_form.add_input([("name", "address"), ("value", "")]) original_form.add_file_input([("name", "file"), ("type", "file")]) freq = HTTPPostDataRequest(self.url, dc=original_form) filled_form = mutant_smart_fill(freq, original_form, 'username', 0, self.fuzzer_config) self.assertEqual(id(original_form), id(filled_form)) self.assertEqual(filled_form['username'], [ '', ]) self.assertEqual(filled_form['address'], [ 'Bonsai Street 123', ]) str_file = filled_form['file'][0] self.assertEqual(str_file.name[-4:], '.gif') self.assertIn('GIF', str_file)
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 = Form() form.add_input([("name", "username"), ("value", "")]) form.add_input([("name", "address"), ("value", "")]) freq = HTTPPostDataRequest(URL('http://www.w3af.com/?id=3'), dc=form, method='PUT') generated_mutants = create_mutants(freq, self.payloads) self.assertTrue( all('http://www.w3af.com/?id=3' == m.get_uri().url_string for m in generated_mutants)) self.assertTrue( all(isinstance(m, PostDataMutant) for m in generated_mutants), generated_mutants) self.assertTrue(all(m.get_method() == 'PUT' for m in generated_mutants)) expected_dc_lst = [ Form([('username', ['abc']), ('address', ['Bonsai Street 123'])]), Form([('username', ['def']), ('address', ['Bonsai Street 123'])]), Form([('username', ['John8212']), ('address', ['abc'])]), Form([('username', ['John8212']), ('address', ['def'])]) ] created_dc_lst = [i.get_dc() for i in generated_mutants] self.assertEqual(created_dc_lst, expected_dc_lst)
def test_mutant_creation_file(self): form = Form() form.add_input([("name", "username"), ("value", "default")]) form.add_file_input([("name", "file_upload")]) freq = HTTPPostDataRequest(URL('http://www.w3af.com/upload'), dc=form, method='POST') payloads = [ file(__file__), ] created_mutants = PostDataMutant.create_mutants( freq, payloads, [ 'file_upload', ], False, self.fuzzer_config) self.assertEqual(len(created_mutants), 1, created_mutants) mutant = created_mutants[0] self.assertIsInstance(mutant.get_dc()['file_upload'][0], file) self.assertEqual(mutant.get_dc()['username'][0], 'default')
def test_valid_results(self): form = Form() form.add_input([("name", "username"), ("value", "")]) form.add_file_input([("name", "file"), ("type", "file")]) freq = HTTPPostDataRequest(self.url, dc=form) generated_mutants = FileContentMutant.create_mutants( freq, self.payloads, [], False, self.fuzzer_config) self.assertEqual(len(generated_mutants), 2, generated_mutants) expected_data = [ Form([('username', ['John8212']), ('file', ['abc'])]), Form([('username', ['John8212']), ('file', ['def'])]), ] generated_data = [m.get_data() for m in generated_mutants] self.assertEqual(expected_data, generated_data) str_file = generated_data[0]['file'][0] self.assertEqual(str_file.name[-4:], '.gif') self.assertIn('abc', str_file)
def test_basics(self): form = Form() form.add_input([("name", "username"), ("value", "")]) form.add_input([("name", "address"), ("value", "")]) form.add_file_input([("name", "file"), ("type", "file")]) freq = HTTPPostDataRequest(self.url, dc=form) m = FileContentMutant(freq) m.set_var('file', 0) m.set_mod_value('abc') self.assertEqual(m.get_url().url_string, 'http://moth/') expected_mod_value = 'The data that was sent is: "username=&file=abc&address=".' generated_mod_value = m.print_mod_value() self.assertEqual(generated_mod_value, expected_mod_value) expected_found_at = u'"http://moth/", using HTTP method POST. The'\ ' sent post-data was: "username=&file=abc&address="'\ ' which modifies the uploaded file content.' generated_found_at = m.found_at() self.assertEqual(generated_found_at, expected_found_at)
def create_fuzzable_request_from_parts(url, method='GET', post_data='', add_headers=None): """ Creates a fuzzable request based on the input parameters. :param req_url: A URL object :param method: A string that represents the method ('GET', 'POST', etc) :param post_data: A string that represents the postdata. :param add_headers: A Headers object that holds the headers. If `req_url` is a request then this dict will be merged with the request's headers. """ if add_headers is not None and not isinstance(add_headers, Headers): raise ValueError('create_fuzzable_request requires Headers object.') if not isinstance(url, URL): raise TypeError('Requires URL to create FuzzableRequest.') headers = add_headers or Headers() # Just a query string request! No postdata if not post_data: return HTTPQSRequest(url, method, headers) else: # Seems to be something that has post data data = {} conttype, header_name = headers.iget('content-type', '') if conttype: del headers[header_name] contlen, header_name = headers.iget('content-length', '') if contlen: del headers[header_name] # # Case #1 - multipart form data - prepare data container # if conttype.startswith('multipart/form-data'): pdict = cgi.parse_header(conttype)[1] try: dc = cgi.parse_multipart(StringIO(post_data), pdict) except Exception, e: msg = 'Multipart form data is invalid, exception: "%s".' \ ' Returning our best match HTTPPostDataRequest.' om.out.debug(msg % e) empty_data = QueryString() return HTTPPostDataRequest(url, method, headers, dc=empty_data) else: data = QueryString() data.update(dc) # Please note that the QueryString is just a container for the # information. When the HTTPPostDataRequest is sent it should # be serialized into multipart again by the MultipartPostHandler # because the headers contain the multipart/form-data header headers['content-type'] = conttype return HTTPPostDataRequest(url, method, headers, dc=data) # # Case #2 - JSON request # try: data = json.loads(post_data) except: pass else: if data: return JSONPostDataRequest(url, method, headers, dc=data) # # Case #3 - XMLRPC request # if all(map(lambda stop: stop in post_data.lower(), XMLRPC_WORDS)): return XMLRPCRequest(post_data, url, method, headers) # # Case #4 - a typical post request # try: data = parse_qs(post_data) except: om.out.debug('Failed to create a data container that ' 'can store this data: "' + post_data + '".') else: # Finally create request return HTTPPostDataRequest(url, method, headers, dc=data) return None
def create_fuzzable_requests(resp, request=None, add_self=True): """ Generates the fuzzable requests based on an HTTP response instance. :param resp: An HTTPResponse instance. :param request: The HTTP request that generated the resp :param add_self: If I should add the current HTTP request (:param request) to the result on not. :return: A list of fuzzable requests. """ res = [] # Headers for all fuzzable requests created here: # And add the fuzzable headers to the dict req_headers = dict((h, '') for h in cf.cf.get('fuzzable_headers')) req_headers.update(request and request.get_headers() or {}) req_headers = Headers(req_headers.items()) # Get the cookie! cookie_obj = _create_cookie(resp) # Create the fuzzable request that represents the request object # passed as parameter if add_self: qsr = HTTPQSRequest( resp.get_uri(), headers=req_headers, cookie=cookie_obj ) res.append(qsr) # If response was a 30X (i.e. a redirect) then include the # corresponding fuzzable request. resp_headers = resp.get_headers() for url_header_name in URL_HEADERS: url_header_value, _ = resp_headers.iget(url_header_name, '') if url_header_value: url = smart_unicode(url_header_value, encoding=resp.charset) try: absolute_location = resp.get_url().url_join(url) except ValueError: msg = 'The application sent a "%s" redirect that w3af' \ ' failed to correctly parse as an URL, the header' \ ' value was: "%s"' om.out.debug(msg % (url_header_name, url)) else: qsr = HTTPQSRequest( absolute_location, headers=req_headers, cookie=cookie_obj ) res.append(qsr) # Try to find forms in the document try: dp = parser_cache.dpc.get_document_parser_for(resp) except BaseFrameworkException: # Failed to find a suitable parser for the document form_list = [] else: form_list = dp.get_forms() same_domain = lambda f: f.get_action().get_domain() == \ resp.get_url().get_domain() form_list = [f for f in form_list if same_domain(f)] if not form_list: # Check if its a wsdl file #TODO: Rewrite web service support """ wsdlp = WSDLParser() try: wsdlp.set_wsdl(resp.get_body()) except BaseFrameworkException: pass else: for rem_meth in wsdlp.get_methods(): wspdr = WebServiceRequest( rem_meth.get_location(), rem_meth.get_action(), rem_meth.get_parameters(), rem_meth.get_namespace(), rem_meth.get_methodName(), req_headers ) res.append(wspdr) """ else: # Create one HTTPPostDataRequest for each form variant mode = cf.cf.get('form_fuzzing_mode') for form in form_list: for variant in form.get_variants(mode): if form.get_method().upper() == 'POST': r = HTTPPostDataRequest( variant.get_action(), variant.get_method(), req_headers, cookie_obj, variant) else: # The default is a GET request r = HTTPQSRequest( variant.get_action(), headers=req_headers, cookie=cookie_obj ) r.set_dc(variant) res.append(r) return res
def create_fuzzable_requests(resp, request=None, add_self=True): """ Generates the fuzzable requests based on an HTTP response instance. :param resp: An HTTPResponse instance. :param request: The HTTP request that generated the resp :param add_self: If I should add the current HTTP request (:param request) to the result on not. :return: A list of fuzzable requests. """ res = [] # Headers for all fuzzable requests created here: # And add the fuzzable headers to the dict req_headers = dict((h, '') for h in cf.cf.get('fuzzable_headers')) req_headers.update(request and request.get_headers() or {}) req_headers = Headers(req_headers.items()) # Get the cookie! cookieObj = _create_cookie(resp) # Create the fuzzable request that represents the request object # passed as parameter if add_self: qsr = HTTPQSRequest(resp.get_uri(), headers=req_headers, cookie=cookieObj) res.append(qsr) # If response was a 30X (i.e. a redirect) then include the # corresponding fuzzable request. resp_headers = resp.get_headers() for url_header_name in URL_HEADERS: url_header_value, _ = resp_headers.iget(url_header_name, '') if url_header_value: url = smart_unicode(url_header_value, encoding=resp.charset) try: absolute_location = resp.get_url().url_join(url) except ValueError: msg = 'The application sent a "%s" redirect that w3af' \ ' failed to correctly parse as an URL, the header' \ ' value was: "%s"' om.out.debug(msg % (url_header_name, url)) else: qsr = HTTPQSRequest(absolute_location, headers=req_headers, cookie=cookieObj) res.append(qsr) # Try to find forms in the document try: dp = parser_cache.dpc.get_document_parser_for(resp) except BaseFrameworkException: # Failed to find a suitable parser for the document form_list = [] else: form_list = dp.get_forms() same_domain = lambda f: f.get_action().get_domain() == \ resp.get_url().get_domain() form_list = [f for f in form_list if same_domain(f)] if not form_list: # Check if its a wsdl file #TODO: Rewrite web service support """ wsdlp = WSDLParser() try: wsdlp.set_wsdl(resp.get_body()) except BaseFrameworkException: pass else: for rem_meth in wsdlp.get_methods(): wspdr = WebServiceRequest( rem_meth.get_location(), rem_meth.get_action(), rem_meth.get_parameters(), rem_meth.get_namespace(), rem_meth.get_methodName(), req_headers ) res.append(wspdr) """ else: # Create one HTTPPostDataRequest for each form variant mode = cf.cf.get('form_fuzzing_mode') for form in form_list: for variant in form.get_variants(mode): if form.get_method().upper() == 'POST': r = HTTPPostDataRequest(variant.get_action(), variant.get_method(), req_headers, cookieObj, variant) else: # The default is a GET request r = HTTPQSRequest(variant.get_action(), headers=req_headers, cookie=cookieObj) r.set_dc(variant) res.append(r) return res