''' fuzzer.py Copyright 2006 Andres Riancho This file is part of w3af, w3af.sourceforge.net . w3af is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License. w3af is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with w3af; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ''' from string import letters, digits from random import choice, randint from core.data.fuzzer.mutant import mutant as mutant import core.data.kb.config as cf def createMutants( freq, mutantStrList, append=False, fuzzableParamList = [] ): ''' @parameter freq: A fuzzable request with a dataContainer inside. @parameter mutantStrList: a list with mutant strings to use @parameter append: This indicates if the content of mutantStrList should be appended to the variable value @parameter fuzzableParamList: If [] then all params are fuzzed. If ['a'] , then only 'a' is fuzzed. @return: Returns a MutantList. ''' result = [] fuzzable = freq.getFuzzable() for fuzzableType in fuzzable.keys() : dataContainer = fuzzable[ fuzzableType ] # First we fill all empty variables in the dataContainer # This will help when testing forms with server side validation that says "if not a complete form: error() else: executeSQLquery( formValues )" for variable in dataContainer.keys(): if dataContainer[variable] == '': dataContainer[variable] = smartFill( variable ) # Now I create more mutant strings, these mutant strings will do the "fuzz file content" feature if cf.cf.getData('fuzzFileContent' ) and freq.getFileVariables(): fileStrList = [] for mutantStr in mutantStrList: if type( mutantStr ) == str: # I have to create the fileStr with a "name" attr. This is needed for MultipartPostHandler fStr = fileStr( mutantStr ) extension = cf.cf.getData('fuzzFCExt' ) or 'txt' fStr.name = createRandAlpha( 7 ) + '.' + extension fileStrList.append( fStr ) result.extend( _createMutantsWorker( freq, fuzzableType, dataContainer, fileStrList, freq.getFileVariables() , append ) ) result.extend( _createMutantsWorker( freq, fuzzableType, dataContainer, mutantStrList, fuzzableParamList , append ) ) return result def _createMutantsWorker( freq, fuzzableType, dataContainer, mutantStrList, fuzzableParamList,append): ''' An auxiliary function to createMutants. ''' result = [] for var_to_mod in dataContainer.keys(): for mutantStr in mutantStrList: # Only fuzz the specified parameters if var_to_mod in fuzzableParamList or fuzzableParamList == []: dataContainerCopy = dataContainer.copy() if append : dataContainerCopy[var_to_mod] = dataContainerCopy[var_to_mod] + mutantStr else: dataContainerCopy[var_to_mod] = mutantStr freqCopy = freq.copy() m = mutant( freqCopy ) m.setFuzzable( fuzzableType, dataContainerCopy ) m.setVar( var_to_mod ) m.setModValue( mutantStr ) result.append ( m ) return result def createRandAlpha( length=0 ): ''' Create a random string ONLY with letters @return: A random string only composed by letters. ''' if length == 0: jibber = ''.join([letters]) ru = ''.join([choice(jibber) for x in range(randint(10, 30))]) else: jibber = ''.join([letters]) ru = ''.join([choice(jibber) for x in range(length)]) return ru def createRandAlNum( length=0): ''' Create a random string with random length @return: A random string of with length > 10 and length < 30. ''' if length == 0: jibber = ''.join([letters, digits]) ru = ''.join([choice(jibber) for x in range(randint(10, 30))]) else: jibber = ''.join([letters, digits]) ru = ''.join([choice(jibber) for x in range(length)]) return ru def createRandNum( length=0): ''' Create a random string ONLY with numbers @return: A random string only composed by numbers. ''' if length == 0: jibber = ''.join([digits]) ru = ''.join([choice(jibber) for x in range(randint(10, 30))]) else: jibber = ''.join([digits]) ru = ''.join([choice(jibber) for x in range(length)]) return ru def createFormatString( length ): ''' @return: A string with $length %s and a final %n ''' result = '%n' * length return result class fileStr( str ): isFile = True name = '' def read( self, size = 0 ): return self.__repr__()[1:-1] def seek( self, foo = 0 ): pass from core.data.fuzzer.formFiller import smartFill