def _fill_form(self, fuzzable_req): ''' Fill the HTTP request form that is passed as fuzzable_req. @return: A filled form ''' self._already_filled_form.add(fuzzable_req.getURL()) to_send = fuzzable_req.getDc().copy() for param_name in to_send: # I do not want to mess with the "static" fields if isinstance(to_send, form.Form): if to_send.getType(param_name) in ('checkbox', 'file', 'radio', 'select'): continue # Set all the other fields, except from the ones that have a # value set (example: hidden fields like __VIEWSTATE). for elem_index in xrange(len(to_send[param_name])): # TODO: Should I ignore it because it already has a value? if to_send[param_name][elem_index] != '': continue # SmartFill it! to_send[param_name][elem_index] = smartFill(param_name) fuzzable_req.setDc(to_send) return fuzzable_req
def discover(self, fuzzableRequest): """ Searches for links on the html. @parameter fuzzableRequest: A fuzzableRequest instance that contains (among other things) the URL to test. """ om.out.debug("webSpider plugin is testing: " + fuzzableRequest.getURL()) if self._first_run: # I have to set some variables, in order to be able to code the "onlyForward" feature self._first_run = False self._target_urls = [urlParser.getDomainPath(i) for i in cf.cf.getData("targets")] self._target_domain = urlParser.getDomain(cf.cf.getData("targets")[0]) # If its a form, then smartFill the Dc. original_dc = fuzzableRequest.getDc() if isinstance(fuzzableRequest, httpPostDataRequest.httpPostDataRequest): # TODO!!!!!! if fuzzableRequest.getURL() in self._already_filled_form: return [] else: self._already_filled_form.add(fuzzableRequest.getURL()) to_send = original_dc.copy() for parameter_name in to_send: # I do not want to mess with the "static" fields if isinstance(to_send, form.form): if to_send.getType(parameter_name) in ["checkbox", "file", "radio", "select"]: continue # # Set all the other fields, except from the ones that have a value set (example: # hidden fields like __VIEWSTATE). # for element_index in xrange(len(to_send[parameter_name])): # should I ignore it because it already has a value? if to_send[parameter_name][element_index] != "": continue # smartFill it! to_send[parameter_name][element_index] = smartFill(parameter_name) fuzzableRequest.setDc(to_send) self._fuzzableRequests = [] response = None try: response = self._sendMutant(fuzzableRequest, analyze=False) except KeyboardInterrupt, e: raise e
def _createMutantsWorker(freq, mutantClass, mutant_str_list, fuzzableParamList, append, dataContainer=None): """ An auxiliary function to createMutants. @return: A list of mutants. >>> from core.data.request.fuzzableRequest import fuzzableRequest >>> from core.data.parsers.urlParser import url_object >>> from core.data.dc.dataContainer import dataContainer as dc Mutant creation >>> freq = fuzzableRequest() >>> u = url_object('http://www.w3af.com/') >>> d = dc() >>> d['a'] = ['1',] >>> d['b'] = ['2',] >>> freq.setURL( u ) >>> freq.setDc( d ) >>> f = _createMutantsWorker( freq, mutantQs, ['abc', 'def'], [], True) >>> [ i.getDc() for i in f ] [{'a': ['abc'], 'b': ['2']}, {'a': ['def'], 'b': ['2']}, {'a': ['1'], 'b': ['abc']}, {'a': ['1'], 'b': ['def']}] Repeated parameters >>> freq = fuzzableRequest() >>> u = url_object('http://www.w3af.com/') >>> d = dc() >>> d['a'] = ['1','2','3'] >>> freq.setURL( u ) >>> freq.setDc( d ) >>> f = _createMutantsWorker( freq, mutantQs, ['abc', 'def'], [], True) >>> [ i.getDc() for i in f ] [{'a': ['abc', '2', '3']}, {'a': ['def', '2', '3']}, {'a': ['1', 'abc', '3']}, {'a': ['1', 'def', '3']}, {'a': ['1', '2', 'abc']}, {'a': ['1', '2', 'def']}] SmartFill of parameters >>> from core.data.dc.form import form >>> from core.data.request.httpPostDataRequest import httpPostDataRequest >>> pdr = httpPostDataRequest() >>> u = url_object('http://www.w3af.com/') >>> f = form() >>> _ = f.addInput( [("name", "address") , ("type", "text")] ) >>> _ = f.addInput( [("name", "foo") , ("type", "text")] ) >>> pdr.setURL( u ) >>> pdr.setDc( f ) >>> f = _createMutantsWorker( pdr, mutantPostData, ['abc', 'def'], [], True) >>> [ i.getDc() for i in f ] [{'foo': ['abc'], 'address': ['Bonsai Street 123']}, {'foo': ['def'], 'address': ['Bonsai Street 123']}, {'foo': ['56'], 'address': ['abc']}, {'foo': ['56'], 'address': ['def']}] """ result = [] if not dataContainer: dataContainer = freq.getDc() for parameter_name in dataContainer: # # Ignore the banned parameter names # if parameter_name in IGNORED_PARAMETERS: continue # This for is to support repeated parameter names for element_index, element_value in enumerate(dataContainer[parameter_name]): for mutant_str in mutant_str_list: # Exclude the file parameters, those are fuzzed in _createFileContentMutants() # (if the framework if configured to do so) # # But if we have a form with files, then we have a multipart form, and we have to keep it # that way. If we don't send the multipart form as multipart, the remote programming # language may ignore all the request, and the parameter that we are # fuzzing (that's not the file content one) will be ignored too # # The "keeping the multipart form alive" thing is done some lines below, search for # the "__HERE__" string! # # The exclusion is done here: if parameter_name in freq.getFileVariables() and not hasattr(mutant_str, "name"): continue # Only fuzz the specified parameters (if any) # or fuzz all of them (the fuzzableParamList == [] case) if parameter_name in fuzzableParamList or fuzzableParamList == []: dataContainerCopy = dataContainer.copy() original_value = element_value if append: dataContainerCopy[parameter_name][element_index] += mutant_str else: dataContainerCopy[parameter_name][element_index] = mutant_str # Ok, now we have a data container with the mutant string, but it's possible that # all the other fields of the data container are empty (think about a form) # We need to fill those in, with something *useful* to get around the easiest # developer checks like: "parameter A was filled". # But I only perform this task in HTML forms, everything else is left as it is: if isinstance(dataContainerCopy, form): for var_name_dc in dataContainerCopy: for element_index_dc, element_value_dc in enumerate(dataContainerCopy[var_name_dc]): if (var_name_dc, element_index_dc) != ( parameter_name, element_index, ) and dataContainerCopy.getType(var_name_dc) not in [ "checkbox", "radio", "select", "file", ]: # Fill only if the parameter does NOT have a value set. # # The reason of having this already set would be that the form # has something like this: # # <input type="text" name="p" value="foobar"> # if dataContainerCopy[var_name_dc][element_index_dc] == "": # # Fill it smartly # dataContainerCopy[var_name_dc][element_index_dc] = smartFill(var_name_dc) # __HERE__ # Please see the comment above for an explanation of what we are doing here: for var_name in freq.getFileVariables(): # I have to create the string_file with a "name" attr. # This is needed for MultipartPostHandler str_file_instance = string_file("") extension = cf.cf.getData("fuzzFCExt") or "txt" str_file_instance.name = createRandAlpha(7) + "." + extension dataContainerCopy[var_name][0] = str_file_instance # Create the mutant freq_copy = freq.copy() m = mutantClass(freq_copy) m.setVar(parameter_name, index=element_index) m.setDc(dataContainerCopy) m.setOriginalValue(original_value) m.setModValue(mutant_str) # Done, add it to the result result.append(m) return result
def _createMutantsWorker( freq, mutantClass, mutant_str_list, fuzzableParamList,append, dataContainer=None): ''' An auxiliary function to createMutants. @return: A list of mutants. ''' result = [] if not dataContainer: dataContainer = freq.getDc() for parameter_name in dataContainer: # # Ignore the banned parameter names # if parameter_name in IGNORED_PARAMETERS: continue # This for is to support repeated parameter names for element_index, element_value in enumerate(dataContainer[parameter_name]): for mutant_str in mutant_str_list: # Exclude the file parameters, those are fuzzed in _createFileContentMutants() # (if the framework if configured to do so) # # But if we have a form with files, then we have a multipart form, and we have to keep it # that way. If we don't send the multipart form as multipart, the remote programming # language may ignore all the request, and the parameter that we are # fuzzing (that's not the file content one) will be ignored too # # The "keeping the multipart form alive" thing is done some lines below, search for # the "__HERE__" string! # # The exclusion is done here: if parameter_name in freq.getFileVariables() and not hasattr(mutant_str, 'name'): continue # Only fuzz the specified parameters (if any) # or fuzz all of them (the fuzzableParamList == [] case) if parameter_name in fuzzableParamList or fuzzableParamList == []: dataContainerCopy = dataContainer.copy() original_value = element_value if append : dataContainerCopy[parameter_name][element_index] += mutant_str else: dataContainerCopy[parameter_name][element_index] = mutant_str # Ok, now we have a data container with the mutant string, but it's possible that # all the other fields of the data container are empty (think about a form) # We need to fill those in, with something *useful* to get around the easiest # developer checks like: "parameter A was filled". # But I only perform this task in HTML forms, everything else is left as it is: if isinstance( dataContainerCopy, form ): for var_name_dc in dataContainerCopy: for element_index_dc, element_value_dc in enumerate(dataContainerCopy[var_name_dc]): if (var_name_dc, element_index_dc) != (parameter_name, element_index) and\ dataContainerCopy.getType(var_name_dc) not in ['checkbox', 'radio', 'select', 'file' ]: # Fill only if the parameter does NOT have a value set. # # The reason of having this already set would be that the form # has something like this: # # <input type="text" name="p" value="foobar"> # if dataContainerCopy[var_name_dc][element_index_dc] == '': # # Fill it smartly # dataContainerCopy[var_name_dc][element_index_dc] = smartFill(var_name_dc) # __HERE__ # Please see the comment above for an explanation of what we are doing here: for var_name in freq.getFileVariables(): # I have to create the string_file with a "name" attr. # This is needed for MultipartPostHandler str_file_instance = string_file( '' ) extension = cf.cf.getData('fuzzFCExt' ) or 'txt' str_file_instance.name = createRandAlpha( 7 ) + '.' + extension dataContainerCopy[var_name][0] = str_file_instance # Create the mutant freq_copy = freq.copy() m = mutantClass( freq_copy ) m.setVar( parameter_name, index=element_index ) m.setDc( dataContainerCopy ) m.setOriginalValue( original_value ) m.setModValue( mutant_str ) # Done, add it to the result result.append( m ) return result
def _createMutantsWorker(freq, mutantClass, mutant_str_list, fuzzableParamList, append, dataContainer=None): ''' An auxiliary function to createMutants. @return: A list of mutants. >>> from core.data.request.fuzzableRequest import fuzzableRequest >>> from core.data.parsers.urlParser import url_object >>> from core.data.dc.dataContainer import DataContainer Mutant creation >>> d = DataContainer() >>> d['a'] = ['1',] >>> d['b'] = ['2',] >>> freq = fuzzableRequest(url_object('http://www.w3af.com/'), dc=d) >>> f = _createMutantsWorker( freq, mutantQs, ['abc', 'def'], [], False) >>> [ i.getDc() for i in f ] [DataContainer({'a': ['abc'], 'b': ['2']}), DataContainer({'a': ['def'], 'b': ['2']}), DataContainer({'a': ['1'], 'b': ['abc']}), DataContainer({'a': ['1'], 'b': ['def']})] Append >>> d = DataContainer() >>> d['a'] = ['1',] >>> d['b'] = ['2',] >>> freq = fuzzableRequest(url_object('http://www.w3af.com/'), dc=d) >>> f = _createMutantsWorker( freq, mutantQs, ['abc', 'def'], [], True) >>> [ i.getDc() for i in f ] [DataContainer({'a': ['1abc'], 'b': ['2']}), DataContainer({'a': ['1def'], 'b': ['2']}), DataContainer({'a': ['1'], 'b': ['2abc']}), DataContainer({'a': ['1'], 'b': ['2def']})] Repeated parameters >>> d = DataContainer() >>> d['a'] = ['1','2','3'] >>> freq.setDc(d) >>> f = _createMutantsWorker( freq, mutantQs, ['abc', 'def'], [], False) >>> [ i.getDc() for i in f ] [DataContainer({'a': ['abc', '2', '3']}), DataContainer({'a': ['def', '2', '3']}), DataContainer({'a': ['1', 'abc', '3']}), DataContainer({'a': ['1', 'def', '3']}), DataContainer({'a': ['1', '2', 'abc']}), DataContainer({'a': ['1', '2', 'def']})] SmartFill of parameters >>> from core.data.dc.form import Form >>> from core.data.request.httpPostDataRequest import httpPostDataRequest >>> f = Form() >>> _ = f.addInput( [("name", "address") , ("type", "text")] ) >>> _ = f.addInput( [("name", "foo") , ("type", "text")] ) >>> pdr = httpPostDataRequest(url_object('http://www.w3af.com/'), dc=f) >>> f = _createMutantsWorker( pdr, mutantPostData, ['abc', 'def'], [], False) >>> [ i.getDc() for i in f ] [Form({'address': ['abc'], 'foo': ['56']}), Form({'address': ['def'], 'foo': ['56']}), Form({'address': ['Bonsai Street 123'], 'foo': ['abc']}), Form({'address': ['Bonsai Street 123'], 'foo': ['def']})] Support for HTTP requests that have both QS and POST-Data >>> f = Form() >>> _ = f.addInput( [("name", "password") , ("type", "password")] ) >>> pdr = httpPostDataRequest(url_object('http://www.w3af.com/foo.bar?action=login'), dc=f) >>> mutants = _createMutantsWorker( pdr, mutantPostData, ['abc', 'def'], [], False) >>> [ i.getURI() for i in mutants ] [<url_object for "http://www.w3af.com/foo.bar?action=login">, <url_object for "http://www.w3af.com/foo.bar?action=login">] >>> [ i.getDc() for i in mutants ] [Form({'password': ['abc']}), Form({'password': ['def']})] ''' result = [] if not dataContainer: dataContainer = freq.getDc() for pname in dataContainer: # # Ignore the banned parameter names # if pname in IGNORED_PARAMETERS: continue # This for is to support repeated parameter names for element_index, element_value in _enumRepeatedParams(dataContainer[pname]): for mutant_str in mutant_str_list: # Exclude the file parameters, those are fuzzed in _createFileContentMutants() # (if the framework if configured to do so) # # But if we have a form with files, then we have a multipart form, and we have to keep it # that way. If we don't send the multipart form as multipart, the remote programming # language may ignore all the request, and the parameter that we are # fuzzing (that's not the file content one) will be ignored too # # The "keeping the multipart form alive" thing is done some lines below, search for # the "__HERE__" string! # # The exclusion is done here: if pname in freq.getFileVariables() and not hasattr(mutant_str, 'name'): continue # Only fuzz the specified parameters (if any) # or fuzz all of them (the fuzzableParamList == [] case) if pname in fuzzableParamList or fuzzableParamList == []: dc_copy = dataContainer.copy() original_value = element_value # Ok, now we have a data container with the mutant string, but it's possible that # all the other fields of the data container are empty (think about a form) # We need to fill those in, with something *useful* to get around the easiest # developer checks like: "parameter A was filled". # But I only perform this task in HTML forms, everything else is left as it is: if isinstance(dc_copy, Form): for var_name_dc in dc_copy: for element_index_dc, element_value_dc in enumerate(dc_copy[var_name_dc]): if (var_name_dc, element_index_dc) != (pname, element_index) and\ dc_copy.getType(var_name_dc) not in ['checkbox', 'radio', 'select', 'file' ]: # Fill only if the parameter does NOT have a value set. # # The reason of having this already set would be that the form # has something like this: # # <input type="text" name="p" value="foobar"> # if dc_copy[var_name_dc][element_index_dc] == '': # # Fill it smartly # dc_copy[var_name_dc][element_index_dc] = smartFill(var_name_dc) # __HERE__ # Please see the comment above for an explanation of what we are doing here: for var_name in freq.getFileVariables(): # I have to create the NamedStringIO with a "name". # This is needed for MultipartPostHandler fname = "%s.%s" % (createRandAlpha(7), cf.cf.getData('fuzzFCExt' ) or 'txt') str_file = NamedStringIO('', name=fname) dc_copy[var_name][0] = str_file if append: mutant_str = original_value + mutant_str dc_copy[pname][element_index] = mutant_str # Create the mutant freq_copy = freq.copy() m = mutantClass( freq_copy ) m.setVar( pname, index=element_index ) m.setDc( dc_copy ) m.setOriginalValue( original_value ) m.setModValue( mutant_str ) # Done, add it to the result result.append( m ) return result