''' baseManglePlugin.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.basePlugin.basePlugin import basePlugin from core.data.request.httpPostDataRequest import httpPostDataRequest from core.data.request.httpQsRequest import httpQsRequest import core.data.parsers.urlParser as urlParser class baseManglePlugin(basePlugin): ''' This is the base class for mangle plugins, all mangle plugins should inherit from it and implement the following methods : 1. mangleRequest( request ) 2. mangleResponse( request ) 3. setOptions( OptionList ) 4. getOptionsXML() @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__(self): pass def mangleRequest(self, request ): ''' This method mangles the request. This method MUST be implemented on every plugin. @param request: This is the request to mangle. @return: A mangled version of the request. ''' raise w3afException('Plugin is not implementing required method mangleRequest' ) def mangleResponse(self, response ): ''' This method mangles the response. This method MUST be implemented on every plugin. @param response: This is the response to mangle. @return: A mangled version of the response. ''' raise w3afException('Plugin is not implementing required method mangleResponse' ) def setUrlOpener(self, foo): pass def __gt__( self, other ): ''' This function is called when sorting mangle plugins. ''' if self.getPriority() > other.getPriority(): return True else: return False def __lt__( self, other ): ''' This function is called when sorting evasion plugins. ''' return not self.__gt__( other ) def __eq__( self, other ): ''' This function is called when sorting mangle plugins. ''' if self.getPriority() == other.getPriority(): return True else: return False def getPriority( self ): ''' This function is called when sorting mangle plugins. Each mangle plugin should implement this. @return: An integer specifying the priority. 100 is runned first, 0 last. ''' raise w3afException('Plugin is not implementing required method getPriority' ) def _fixContentLen( self, response ): ''' If the content-length header is present, calculate the new len and update the header. ''' cl = 'Content-Length' for i in response.getHeaders(): if i.lower() == 'Content-length'.lower(): cl = i break headers = response.getHeaders() headers[ cl ] = str( len( response.getBody() ) ) response.setHeaders( headers ) return response def _createFuzzFromRequest( self, command, url, postData, headers ): ''' Creates a fuzzable request based on a query sent FROM the browser. This was stolen from spiderMan plugin. TODO: put this transformation functions somewhere else... ''' res = None if len( postData ): pdr = httpPostDataRequest() pdr.setURL( url ) pdr.setMethod( command ) if 'content-length' in headers.keys(): headers.pop('content-length') pdr.setHeaders( headers ) if 'content-Type' in headers.keys() and headers['content-Type'] == 'multipart/form-data': dc = cgi.parse_multipart( postData, headers ) for i in dc.keys(): dc = dc[ i ][0] pdr.setDc( dc ) else: dc = urlParser.getQueryString( 'http://a/?' + postData ) pdr.setDc( dc ) res = pdr else: # Just a query string request ! no postdata qsr = httpQsRequest() qsr.setURL( url ) qsr.setHeaders( headers ) qsr.setMethod( command ) dc = urlParser.getQueryString( url ) qsr.setDc( dc ) res = qsr return res def headersToString( headerDict ): ''' @parameter headerDict: The header dictionary of the request @return: A string representation of the dictionary ''' res = '' for key in headerDict: res += key + ': ' + headerDict[key] + '\r\n' return res def stringToHeaders( headerString ): ''' The reverse of headersToString ''' res = {} splittedString = headerString.split('\r\n') for s in splittedString: if s != '': try: name = s.split(':')[0] value = ':'.join( s.split(':')[1:] ) except: om.out.error('You "over-mangled" the header! Now the headers are invalid, ignoring:' + s ) else: res[ name ] = value[1:] # Escape the space after the ":" return res