def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # First we mangle the URL path = request.url_object.get_path() path = self._mutate(path) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.set_path(path) # Mangle the postdata data = request.get_data() if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: data = self._mutate(data) new_req = HTTPRequest(new_url, data, request.headers, request.get_origin_req_host()) return new_req
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # Mangle the postdata data = str(request.get_data()) if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: data = '\x00' + data headers_copy = copy.deepcopy(request.headers) headers_copy['content-length'] = str(len(data)) request = HTTPRequest(request.url_object, data, headers_copy, request.get_origin_req_host()) return request
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # First we mangle the URL path = request.url_object.get_path() path = self._mutate(path) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.set_path(path) # Mangle the postdata data = request.get_data() if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: data = self._mutate(data) new_req = HTTPRequest(new_url, data, request.headers, request.get_origin_req_host()) return new_req
def can_parse(post_data): try: parse_qs(post_data) except: return False else: return True
def can_parse(post_data): try: parse_qs(post_data) except: return False else: return True
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # Mangle the postdata data = str(request.get_data()) if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: data = "\x00" + data headers_copy = copy.deepcopy(request.headers) headers_copy["content-length"] = str(len(data)) request = HTTPRequest( request.url_object, data, headers_copy, request.get_origin_req_host(), retries=request.retries_left ) return request
def test_find_csrf_token_false(self): url = URL('http://moth/w3af/audit/csrf/') query_string = parse_qs('secret=not a token') freq = FuzzableRequest(url, method='GET', dc=query_string) token = self.csrf_plugin._find_csrf_token(freq) self.assertNotIn('secret', token)
def test_find_csrf_token_true_simple(self): url = URL('http://moth/w3af/audit/csrf/') query_string = parse_qs('secret=f842eb01b87a8ee18868d3bf80a558f3') freq = FuzzableRequest(url, method='GET', dc=query_string) token = self.csrf_plugin._find_csrf_token(freq) self.assertIn('secret', token)
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # First we mangle the URL qs = request.url_object.querystring.copy() qs = self._mutate(qs) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.querystring = qs # Mangle the postdata post_data = request.get_data() if post_data: try: # Only mangle the postdata if it is a url encoded string post_data = parse_qs(post_data) except: pass else: post_data = str(self._mutate(post_data)) new_req = HTTPRequest(new_url, post_data, request.headers, request.get_origin_req_host(), retries=request.retries_left) return new_req
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # First we mangle the URL qs = request.url_object.querystring.copy() qs = self._mutate(qs) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.querystring = qs # Mangle the postdata post_data = request.get_data() if post_data: try: # Only mangle the postdata if it is a url encoded string post_data = parse_qs(post_data) except: pass else: post_data = str(self._mutate(post_data)) new_req = HTTPRequest(new_url, post_data, request.headers, request.get_origin_req_host(), retries=request.retries_left) return new_req
def test_find_csrf_token_false(self): url = URL('http://moth/w3af/audit/csrf/') query_string = parse_qs('secret=not a token') freq = FuzzableRequest(url, method='GET', dc=query_string) token = self.csrf_plugin._find_csrf_token(freq) self.assertNotIn('secret', token)
def test_find_csrf_token_true_simple(self): url = URL('http://moth/w3af/audit/csrf/') query_string = parse_qs('secret=f842eb01b87a8ee18868d3bf80a558f3') freq = FuzzableRequest(url, method='GET', dc=query_string) token = self.csrf_plugin._find_csrf_token(freq) self.assertIn('secret', token)
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # This is a test URL # http://172.16.1.132/index.asp?q=%uFF1Cscript%3Ealert(%22Hello%22)%3C/script%3E # This is the content of index.asp : # <%=Request.QueryString("q")%> # First we mangle the URL path = request.url_object.get_path() path = self._mutate(path) # Now we mangle the postdata data = request.get_data() if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: # We get here only if the parsing was successful data = self._mutate(data) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.set_path(path) new_req = HTTPRequest(new_url, data, request.headers, request.get_origin_req_host(), retries=request.retries_left) return new_req
def from_postdata(cls, headers, post_data): if not URLEncodedForm.is_urlencoded(headers): raise ValueError('Request is not %s.' % URLEncodedForm.ENCODING) if not URLEncodedForm.can_parse(post_data): raise ValueError('Failed to parse post_data as Form.') data = parse_qs(post_data) urlencoded_form = cls() urlencoded_form.update(data.items()) return urlencoded_form
def from_postdata(cls, headers, post_data): if not URLEncodedForm.is_urlencoded(headers): raise ValueError("Request is not %s." % URLEncodedForm.ENCODING) if not URLEncodedForm.can_parse(post_data): raise ValueError("Failed to parse post_data as Form.") data = parse_qs(post_data) urlencoded_form = cls() urlencoded_form.update(data.items()) return urlencoded_form
def test_add_when_qs_and_postdata(self): rp = rnd_param() u = URL('http://www.w3af.com/?id=1') r = HTTPRequest(u, data='a=b') modified_request = rp.modify_request(r) data = parse_qs(modified_request.get_data()) self.assertEqual(len(data), 2) modified_qs = modified_request.url_object.querystring self.assertEqual(len(modified_qs), 2)
def test_add_when_qs_and_postdata(self): rp = rnd_param() u = URL('http://www.w3af.com/?id=1') r = HTTPRequest( u, data='a=b' ) modified_request = rp.modify_request( r ) data = parse_qs( modified_request.get_data() ) self.assertEqual(len(data), 2) modified_qs = modified_request.url_object.querystring self.assertEqual(len(modified_qs), 2)
def modify_request(self, request): """ Mangles the request :param request: HTTPRequest instance that is going to be modified by the evasion plugin :return: The modified request """ # This is a test URL # http://172.16.1.132/index.asp?q=%uFF1Cscript%3Ealert(%22Hello%22)%3C/script%3E # This is the content of index.asp : # <%=Request.QueryString("q")%> # First we mangle the URL path = request.url_object.get_path() path = self._mutate(path) # Now we mangle the postdata data = request.get_data() if data: try: # Only mangle the postdata if it is a url encoded string parse_qs(data) except: pass else: # We get here only if the parsing was successful data = self._mutate(data) # Finally, we set all the mutants to the request in order to return it new_url = request.url_object.copy() new_url.set_path(path) new_req = HTTPRequest(new_url, data, request.headers, request.get_origin_req_host(), retries=request.retries_left) return new_req
def test_get_query_string(self): self.assertEqual(URL(u"http://w3af.com/a/").querystring, QueryString({}.items())) self.assertEqual(URL(u"http://w3af.com/foo/bar.txt?id=3").querystring, QueryString({u"id": [u"3"]}.items())) self.assertEqual( URL(u"http://w3af.com/foo/bar.txt?id=3&id=4").querystring, QueryString({u"id": [u"3", u"4"]}.items()) ) url = URL(u"http://w3af.com/foo/bar.txt?id=3&ff=4&id=5") self.assertEqual(url.querystring, QueryString({u"id": [u"3", u"5"], u"ff": [u"4"]}.items())) self.assertEqual(url.querystring, parse_qs(str(url.querystring)))
def test_add_when_qs_and_postdata(self): url = URL('http://www.w3af.com/?id=1') original_req = HTTPRequest(url, data='a=b') modified_req = self.eplugin.modify_request(original_req) self.assertEqual(len(modified_req.url_object.querystring), 2) self.assertIn('id=1', str(modified_req.url_object.querystring)) data = parse_qs(modified_req.get_data()) self.assertEqual(len(data), 2) self.assertIn('a=b', str(data)) modified_qs = modified_req.url_object.querystring self.assertEqual(len(modified_qs), 2)
def test_add_when_qs_and_postdata(self): url = URL('http://www.w3af.com/?id=1') original_req = HTTPRequest(url, data='a=b') modified_req = self.eplugin.modify_request(original_req) self.assertEqual(len(modified_req.url_object.querystring), 2) self.assertIn('id=1', str(modified_req.url_object.querystring)) data = parse_qs(modified_req.get_data()) self.assertEqual(len(data), 2) self.assertIn('a=b', str(data)) modified_qs = modified_req.url_object.querystring self.assertEqual(len(modified_qs), 2)
def test_get_query_string(self): self.assertEqual(URL(u'http://w3af.com/a/').querystring, QueryString({}.items())) self.assertEqual(URL(u'http://w3af.com/foo/bar.txt?id=3').querystring, QueryString({u'id': [u'3']}.items())) self.assertEqual(URL(u'http://w3af.com/foo/bar.txt?id=3&id=4').querystring, QueryString({u'id': [u'3', u'4']}.items())) url = URL(u'http://w3af.com/foo/bar.txt?id=3&ff=4&id=5') self.assertEqual(url.querystring, QueryString({u'id': [u'3', u'5'], u'ff': [u'4']}.items())) self.assertEqual(url.querystring, parse_qs(str(url.querystring)))
def set_options(self, options_list): self.name = options_list['name'].get_value() self.url = options_list['url'].get_value() self.data = parse_qs(options_list['data'].get_value()) self.method = options_list['method'].get_value() self.vulnerable_parameter = options_list[ 'vulnerable_parameter'].get_value() if not self.data: raise ValueError('This vulnerability requires data to be configured.') if self.vulnerable_parameter not in self.data: msg = 'The vulnerable parameter was not found in the configured data'\ ' field. Please enter one of the following values: %s.' raise ValueError(msg % ', '.join(self.data))
def set_options(self, options_list): self.name = options_list['name'].get_value() self.url = options_list['url'].get_value() self.data = parse_qs(options_list['data'].get_value()) self.method = options_list['method'].get_value() self.vulnerable_parameter = options_list[ 'vulnerable_parameter'].get_value() if not self.data: raise ValueError( 'This vulnerability requires data to be configured.') if self.vulnerable_parameter not in self.data: msg = 'The vulnerable parameter was not found in the configured data'\ ' field. Please enter one of the following values: %s.' raise ValueError(msg % ', '.join(self.data))
def test_get_query_string(self): self.assertEqual( URL(u'http://w3af.com/a/').querystring, QueryString({}.items())) self.assertEqual( URL(u'http://w3af.com/foo/bar.txt?id=3').querystring, QueryString({u'id': [u'3']}.items())) self.assertEqual( URL(u'http://w3af.com/foo/bar.txt?id=3&id=4').querystring, QueryString({u'id': [u'3', u'4']}.items())) url = URL(u'http://w3af.com/foo/bar.txt?id=3&ff=4&id=5') self.assertEqual( url.querystring, QueryString({ u'id': [u'3', u'5'], u'ff': [u'4'] }.items())) self.assertEqual(url.querystring, parse_qs(str(url.querystring)))
def set_options(self, options_list): self.name = options_list['name'].get_value() self.url = options_list['url'].get_value() self.data = parse_qs(options_list['data'].get_value()) self.method = options_list['method'].get_value() self.vulnerable_parameter = options_list[ 'vulnerable_parameter'].get_value() if not self.data: msg = 'This vulnerability requires data to be configured.' raise ValueError(msg) if self.vulnerable_parameter not in self.data: msg = 'The vulnerable parameter was not found in the configured data'\ ' field. Please enter one of the following values: %s.' raise ValueError(msg % ', '.join(self.data)) try: self.create_vuln() except RuntimeError, rte: # https://github.com/andresriancho/w3af/issues/4310 raise ValueError('%s' % rte)
def set_options(self, options_list): self.name = options_list["name"].get_value() self.url = options_list["url"].get_value() self.data = parse_qs(options_list["data"].get_value()) self.method = options_list["method"].get_value() self.vulnerable_parameter = options_list["vulnerable_parameter"].get_value() if not self.data: msg = "This vulnerability requires data to be configured." raise ValueError(msg) if self.vulnerable_parameter not in self.data: msg = ( "The vulnerable parameter was not found in the configured data" " field. Please enter one of the following values: %s." ) raise ValueError(msg % ", ".join(self.data)) try: self.create_vuln() except RuntimeError, rte: # https://github.com/andresriancho/w3af/issues/4310 raise ValueError("%s" % rte)
def test_parse_qs_case04(self): self.assertEqual(parse_qs('id=3&ff=4&id=5'), QueryString([(u'id', [u'3', u'5']), (u'ff', [u'4'])]))
def test_parse_qs_repeated_parameter_names(self): self.assertEqual(parse_qs('id=3&id=4'), QueryString([ (u'id', [u'3', u'4']), ]))
def test_parse_qs_case02(self): self.assertEqual(parse_qs('id=3+1'), QueryString([ (u'id', [u'3+1']), ]))
def test_parse_qs_case06(self): expected_parsed_url = QueryString( [(u'\u9834\u82f1', [u'\u75ab\u76ca'])], encoding='euc-jp') self.assertEqual( parse_qs(u'%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp'), expected_parsed_url)
def test_parse_qs_case02(self): self.assertEqual(parse_qs('id=3+1'), QueryString([(u'id', [u'3+1']),] ))
def test_parse_qs_case05(self): self.assertEqual(parse_qs("pname"), QueryString([(u"pname", [u""])]))
def test_parse_qs_repeated_parameter_names(self): self.assertEqual(parse_qs("id=3&id=4"), QueryString([(u"id", [u"3", u"4"])]))
def test_parse_qs_case05(self): self.assertEqual(parse_qs('pname'), QueryString([ (u'pname', [u'']), ]))
def test_parse_qs_case06(self): self.assertEqual(parse_qs(u'%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp'), QueryString( [(u'\u9834\u82f1', [u'\u75ab\u76ca']),] ))
def test_parse_qs_case05(self): self.assertEqual(parse_qs('pname'), QueryString([(u'pname', [u'']),] ))
def test_parse_qs_case04(self): self.assertEqual(parse_qs('id=3&ff=4&id=5'), QueryString([(u'id', [u'3', u'5']), (u'ff', [u'4'])] ))
def __init__(self): self.name = "" self.url = URL("http://host.tld/") self.data = parse_qs("") self.method = "GET" self.vulnerable_parameter = ""
def test_parse_qs_case06(self): self.assertEqual( parse_qs(u'%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp'), QueryString([ (u'\u9834\u82f1', [u'\u75ab\u76ca']), ]))
def __init__(self): self.name = '' self.url = URL('http://host.tld/') self.data = parse_qs('') self.method = 'GET' self.vulnerable_parameter = ''
def test_parse_qs_case02(self): self.assertEqual(parse_qs("id=3+1"), QueryString([(u"id", [u"3+1"])]))
def __init__(self): self.name = '' self.url = URL('http://host.tld/') self.data = parse_qs('') self.method = 'GET' self.vulnerable_parameter = ''
def test_parse_qs_case04(self): self.assertEqual(parse_qs("id=3&ff=4&id=5"), QueryString([(u"id", [u"3", u"5"]), (u"ff", [u"4"])]))
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 test_parse_qs_case06(self): self.assertEqual( parse_qs(u"%B1%D0%B1%D1=%B1%D6%B1%D7", encoding="euc-jp"), QueryString([(u"\u9834\u82f1", [u"\u75ab\u76ca"])]), )
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 test_parse_qs_repeated_parameter_names(self): self.assertEqual(parse_qs('id=3&id=4'), QueryString([(u'id', [u'3', u'4']),] ))
def test_parse_qs_case06(self): expected_parsed_url = QueryString([(u'\u9834\u82f1', [u'\u75ab\u76ca'])], encoding='euc-jp') self.assertEqual(parse_qs(u'%B1%D0%B1%D1=%B1%D6%B1%D7', encoding='euc-jp'), expected_parsed_url)