''' basePlugin.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 core.controllers.w3afException import w3afException import core.controllers.outputManager as om from core.controllers.threads.threadManager import threadManagerObj as tm from core.controllers.configurable import configurable class basePlugin(configurable): ''' This is the base class for ALL plugins, all plugins should inherit from it and implement the following method : 1. getPluginDeps() Please note that this class is a configurable object, so it must implement: 1. setOptions( OptionList ) 2. getOptionsXML() @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__(self): self._urlOpener = None self._tm = tm def setUrlOpener( self, urlOpener): ''' This method should not be overwritten by any plugin (but you are free to do it, for example a good idea is to rewrite this method to change the UrlOpener to do some IDS evasion technic). This method takes a CustomUrllib object as parameter and assigns it to itself. Then, on the testUrl method you use self.CustomUrlOpener._custom_urlopen(...) to open a Url and you are sure that the plugin is using the user supplied settings (proxy, user agent, etc). @return: No value is returned. ''' self._urlOpener = urlOpener def setOptions( self, OptionsMap ): ''' Sets the Options given on the OptionList to self. The options are the result of a user entering some data on a window that was constructed using the XML Options that was retrieved from the plugin using getOptionsXML() This method MUST be implemented on every plugin. @return: No value is returned. ''' raise w3afException('Plugin is not implementing required method setOptions' ) def getOptionsXML(self): ''' This method returns a XML containing the Options that the plugin has. Using this XML the framework will build a window, a menu, or some other input method to retrieve the info from the user. The XML has to validate against the xml schema file located at : w3af/core/display.xsd This method MUST be implemented on every plugin. @return: XML String @see: core/display.xsd ''' raise w3afException('Plugin is not implementing required method getOptionsXML' ) def getPluginDeps( self ): ''' @return: A list with the names of the plugins that should be runned before the current one. ''' raise w3afException('Plugin is not implementing required method getPluginDeps' ) def getDesc( self ): ''' @return: A description of the plugin. ''' if self.__doc__ != None: res2 = self.__doc__.replace( '\t' , '' ) res = ''.join ( [ i for i in res2.split('\n') if i != '' and i[0] != '@' ] ) else: res = '' return res def getLongDesc( self ): ''' @return: A DETAILED description of the plugin functions and features. ''' raise w3afException('Plugin is not implementing required method getLongDesc' ) def printUniq( self, vulnList, unique ): ''' Print to the user interface the list of vulns ( vulnList ) @parameter vulnList: A list of vuln objects @parameter unique: Defines whats unique: - 'URL': The URL must be unique - 'VAR': The url/variable combination must be unique - None: Print all vulns, nothing should be unique ''' inform = [] if unique == 'URL': reportedURLs = [] for v in vulnList: if v.getURL() not in reportedURLs: reportedURLs.append( v.getURL() ) inform.append( v.getDesc() ) elif unique == 'VAR': reportedVARs = [] for v in vulnList: if (v.getURL(), v.getVar()) not in reportedVARs: reportedVARs.append( (v.getURL(), v.getVar()) ) inform.append( v.getDesc() ) elif unique == None: inform = [ v.getDesc() for v in vulnList ] else: om.out.error('basePlugin.printUniq(): Unknown unique parameter value.') inform.sort() for v in inform: om.out.vulnerability( v ) def _sendMutant( self, mutant, analyze=True ): ''' Sends a mutant to the remote web server. ''' url = mutant.getURI() data = mutant.getData() headers = mutant.getHeaders() for h in mutant.getCookie().keys(): headers[h] = mutant.getCookie()[ h ] args = ( url, ) method = mutant.getMethod() functor = getattr( self._urlOpener , method ) # run functor , run ! ( forest gump flash ) res = apply( functor, args, {'data': data, 'headers': headers } ) if analyze: self._analyzeResult( mutant, res ) return res def getName( self ): return self.__class__.__name__ def __eq__( self, other ): ''' This function is called when extending a list of plugin instances. ''' if self.__class__.__name__ == other.__class__.__name__: return True else: return False