def test_remove_profile_using_name_in_file(self): p = profile('OWASP_TOP10', workdir='.') target_tmp = '/tmp/OWASP_TOP10.pw3af' shutil.copy(p.profile_file_name, '/tmp/') profile_content = file(target_tmp).read() profile_content = profile_content.replace('name = OWASP_TOP10', 'name = foobar') file(target_tmp, 'w').write(profile_content) p = profile('foobar', workdir='/tmp/') p.remove() self.assertFalse(os.path.exists(target_tmp))
def test_load_profile_using_name_in_file(self): p = profile('OWASP_TOP10', workdir='.') target_tmp = '/tmp/OWASP_TOP10.pw3af' shutil.copy(p.profile_file_name, '/tmp/') profile_content = file(target_tmp).read() profile_content = profile_content.replace('name = OWASP_TOP10', 'name = foobar') file(target_tmp, 'w').write(profile_content) p = profile('foobar', workdir='/tmp/') self.assertEqual(target_tmp, p.profile_file_name) os.unlink(target_tmp)
def remove_profile(self, profile_name): """ :return: True if the profile was successfully removed. Else, raise a BaseFrameworkException. """ profile_inst = profile(profile_name) profile_inst.remove() return True
def get_profile_list(self, directory=HOME_DIR): """ :param directory: The directory from which profiles are loaded :return: Two different lists: - One that contains the instances of the valid profiles that were loaded - One with the file names of the profiles that are invalid >>> HOME_DIR = '.' >>> p = w3af_core_profiles(None) >>> valid, invalid = p.get_profile_list(HOME_DIR) >>> valid_lower = [prof.get_name().lower() for prof in valid] >>> 'owasp_top10' in valid_lower True """ profile_home = os.path.join(directory, 'profiles') str_profile_list = get_file_list(profile_home, extension=profile.EXTENSION) instance_list = [] invalid_profiles = [] for profile_name in str_profile_list: profile_filename = os.path.join(profile_home, profile_name + profile.EXTENSION) try: profile_instance = profile(profile_filename) except BaseFrameworkException: invalid_profiles.append(profile_filename) else: instance_list.append(profile_instance) return instance_list, invalid_profiles
def get_profile_list(self, directory=HOME_DIR): """ :param directory: The directory from which profiles are loaded :return: Two different lists: - One that contains the instances of the valid profiles that were loaded - One with the file names of the profiles that are invalid >>> HOME_DIR = '.' >>> p = CoreProfiles(None) >>> valid, invalid = p.get_profile_list(HOME_DIR) >>> valid_lower = [prof.get_name().lower() for prof in valid] >>> 'owasp_top10' in valid_lower True """ profile_home = os.path.join(directory, 'profiles') str_profile_list = get_file_list(profile_home, extension=profile.EXTENSION) instance_list = [] invalid_profiles = [] for profile_name in str_profile_list: profile_filename = os.path.join(profile_home, profile_name + profile.EXTENSION) try: profile_instance = profile(profile_filename) except BaseFrameworkException: invalid_profiles.append(profile_filename) else: instance_list.append(profile_instance) return instance_list, invalid_profiles
def use_profile(self, profile_name, workdir=None): """ Gets all the information from the profile and stores it in the w3af core plugins / target attributes for later use. :raise BaseFrameworkException: if the profile to load has some type of problem, or the plugins are incorrectly configured. """ error_messages = [] # Clear all enabled plugins if profile_name is None if profile_name is None: self._w3af_core.plugins.zero_enabled_plugins() return # This might raise an exception (which we don't want to handle) when # the profile does not exist profile_inst = profile(profile_name, workdir) # It exists, work with it! # Set the target settings of the profile to the core self._w3af_core.target.set_options(profile_inst.get_target()) # Set the misc and http settings try: profile_misc_settings = profile_inst.get_misc_settings() except BaseFrameworkException, e: msg = ('Setting the framework misc-settings raised an exception' ' due to unknown or invalid configuration parameters. %s') error_messages.append(msg % e)
def save_current_to_profile(self, profile_name, prof_desc='', prof_path='', self_contained=False): """ Save the current configuration of the core to the profile called profile_name. :return: The new profile instance if the profile was successfully saved. Otherwise raise a BaseFrameworkException. """ # Open the already existing profile new_profile = profile(profile_name, workdir=os.path.dirname(prof_path)) # shortcut w3af_plugins = self._w3af_core.plugins # Save the enabled plugins for plugin_type in w3af_plugins.get_plugin_types(): enabled_plugins = [] for plugin_name in w3af_plugins.get_enabled_plugins(plugin_type): enabled_plugins.append(plugin_name) new_profile.set_enabled_plugins(plugin_type, enabled_plugins) # Save the plugin options for plugin_type in w3af_plugins.get_plugin_types(): for plugin_name in w3af_plugins.get_enabled_plugins(plugin_type): plugin_options = w3af_plugins.get_plugin_options( plugin_type, plugin_name) if plugin_options: new_profile.set_plugin_options( plugin_type, plugin_name, plugin_options, self_contained=self_contained) # Save the profile targets targets = cf.cf.get('targets') if targets: new_profile.set_target(' , '.join(t.url_string for t in targets)) # Save the misc and http settings misc_settings = MiscSettings() new_profile.set_misc_settings(misc_settings.get_options()) new_profile.set_http_settings( self._w3af_core.uri_opener.settings.get_options()) # Save the profile name and description new_profile.set_desc(prof_desc) new_profile.set_name(profile_name) # Save the profile to the file new_profile.save(profile_name) return new_profile
def test_load_save_as_no_changes(self): """ During some tests I noticed that the console UI was removing the plugin configuration from the profiles when I did a save_as, so this test is rather simple and will: * Load a profile * Save it again * Make a diff between the old and new, it should be empty """ self.core.profiles.use_profile('OWASP_TOP10', workdir='.') self.core.profiles.save_current_to_new_profile('unittest-OWASP_TOP10') # Diff the two profile files p1 = profile('OWASP_TOP10', workdir='.') p2 = profile('unittest-OWASP_TOP10', workdir='.') assertProfilesEqual(p1.profile_file_name, p2.profile_file_name) # cleanup self.core.profiles.remove_profile('unittest-OWASP_TOP10')
def save_current_to_profile(self, profile_name, prof_desc='', prof_path='', self_contained=False): """ Save the current configuration of the core to the profile called profile_name. :return: The new profile instance if the profile was successfully saved. Otherwise raise a BaseFrameworkException. """ # Open the already existing profile new_profile = profile(profile_name, workdir=os.path.dirname(prof_path)) # shortcut w3af_plugins = self._w3af_core.plugins # Save the enabled plugins for plugin_type in w3af_plugins.get_plugin_types(): enabled_plugins = [] for plugin_name in w3af_plugins.get_enabled_plugins(plugin_type): enabled_plugins.append(plugin_name) new_profile.set_enabled_plugins(plugin_type, enabled_plugins) # Save the plugin options for plugin_type in w3af_plugins.get_plugin_types(): for plugin_name in w3af_plugins.get_enabled_plugins(plugin_type): plugin_options = w3af_plugins.get_plugin_options(plugin_type, plugin_name) if plugin_options: new_profile.set_plugin_options(plugin_type, plugin_name, plugin_options, self_contained=self_contained) # Save the profile targets targets = cf.cf.get('targets') if targets: new_profile.set_target(' , '.join(t.url_string for t in targets)) # Save the misc and http settings misc_settings = MiscSettings() new_profile.set_misc_settings(misc_settings.get_options()) new_profile.set_http_settings( self._w3af_core.uri_opener.settings.get_options()) # Save the profile name and description new_profile.set_desc(prof_desc) new_profile.set_name(profile_name) # Save the profile to the file new_profile.save(profile_name) return new_profile
def test_save_as_self_contained_profile(self): commands_to_run = ['profiles', 'use OWASP_TOP10', 'save_as %s self-contained' % self.get_profile_name(), 'exit'] expected = ('Profile saved.',) self.console = ConsoleUI(commands=commands_to_run, do_upd=False) self.console.sh() assert_result, msg = self.startswith_expected_in_output(expected) self.assertTrue(assert_result, msg) # The profile is now self contained p = profile(self.get_profile_name()) self.assertIn('caFileName = base64://', file(p.profile_file_name).read()) # Before it wasn't p = profile('OWASP_TOP10') self.assertIn('caFileName = %ROOT_PATH%', file(p.profile_file_name).read())
def test_save_as_self_contained_profile(self): commands_to_run = [ 'profiles', 'use OWASP_TOP10', 'save_as %s self-contained' % self.get_profile_name(), 'exit' ] expected = ('Profile saved.', ) self.console = ConsoleUI(commands=commands_to_run, do_upd=False) self.console.sh() assert_result, msg = self.startswith_expected_in_output(expected) self.assertTrue(assert_result, msg) # The profile is now self contained p = profile(self.get_profile_name()) self.assertIn('caFileName = base64://', file(p.profile_file_name).read()) # Before it wasn't p = profile('OWASP_TOP10') self.assertIn('caFileName = %ROOT_PATH%', file(p.profile_file_name).read())
def save_current_to_new_profile(self, profile_name, profileDesc=""): """ Saves current config to a newly created profile. :param profile_name: The profile to clone :param profileDesc: The description of the new profile :return: The new profile instance if the profile was successfully saved. Else, raise a BaseFrameworkException. """ # Create the new profile. profile_inst = profile() profile_inst.set_desc(profileDesc) profile_inst.set_name(profile_name) profile_inst.save(profile_name) # Save current to profile return self.save_current_to_profile(profile_name, profileDesc)
def save_current_to_new_profile(self, profile_name, profileDesc=''): """ Saves current config to a newly created profile. :param profile_name: The profile to clone :param profileDesc: The description of the new profile :return: The new profile instance if the profile was successfully saved. Else, raise a BaseFrameworkException. """ # Create the new profile. profile_inst = profile() profile_inst.set_desc(profileDesc) profile_inst.set_name(profile_name) profile_inst.save(profile_name) # Save current to profile return self.save_current_to_profile(profile_name, profileDesc)
def _assert_equal(self, profile_name_a, profile_name_b): p1 = profile(profile_name_a, workdir='.') p2 = profile(profile_name_b, workdir='.') assertProfilesEqual(p1.profile_file_name, p2.profile_file_name)
def _remove_if_exists(self, profile_name): try: profile_inst = profile(profile_name) profile_inst.remove() except: pass
def load_profiles(self, selected=None, retry=True): """Load the profiles. :param selected: which profile is already selected. """ # create the ListStore, with the info listed below liststore = gtk.ListStore(str, str, str, int, str) # we will keep the profile instances here self.profile_instances = {None: None} # build the list with the profiles name, description, profile_instance instance_list, invalid_profiles = self.w3af.profiles.get_profile_list() tmpprofiles = [] for profile_obj in instance_list: nom = profile_obj.get_name() desc = profile_obj.get_desc() tmpprofiles.append((nom, desc, profile_obj)) # Also add to that list the "selected" profile, that was specified by the user with the # "-p" parameter when executing w3af if self._parameter_profile: try: profile_obj = profile(self._parameter_profile) except BaseFrameworkException: raise ValueError(_("The profile %r does not exists!") % self._parameter_profile) else: nom = profile_obj.get_name() desc = profile_obj.get_desc() # I don't want to add duplicates, so I perform this test: add_to_list = True for nom_tmp, desc_tmp, profile_tmp in tmpprofiles: if nom_tmp == nom and desc_tmp == desc: add_to_list = False break if add_to_list: tmpprofiles.append((nom, desc, profile_obj)) # Create the liststore using a specially sorted list, what I basically want is the # empty profile at the beginning of the list, and the rest sorted in alpha order tmpprofiles = sorted(tmpprofiles) tmpprofiles_special_order = [] for nom, desc, profile_obj in tmpprofiles: if nom == 'empty_profile': tmpprofiles_special_order.insert(0, (nom, desc, profile_obj)) else: tmpprofiles_special_order.append((nom, desc, profile_obj)) # And now create the liststore and the internal dict for nom, desc, profile_obj in tmpprofiles_special_order: prfid = str(id(profile_obj)) self.profile_instances[prfid] = profile_obj liststore.append([nom, desc, prfid, 0, nom]) # set this liststore self.liststore = liststore self.set_model(liststore) # select the indicated one self.selectedProfile = None if selected is None: self.set_cursor(0) self._use_profile() else: for i, (nom, desc, prfid, changed, perm) in enumerate(liststore): the_prof = self.profile_instances[prfid] if selected == the_prof.get_profile_file() or \ selected == the_prof.get_name(): self.set_cursor(i) self._use_profile() break else: # In some cases, this function is called in a thread while # the profile file is being stored to disk. Because of that # it might happen that the profile "is there" but didn't get # loaded properly in the first call to load_profiles. if retry: self.load_profiles(selected, retry=False) else: self.set_cursor(0) # Now that we've finished loading everything, show the invalid profiles in a nice pop-up window if invalid_profiles: message = 'The following profiles are invalid and failed to load:\n' for i in invalid_profiles: message += '\n\t- ' + i message += '\n\nPlease click OK to continue without these profiles.' dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, message) dlg.run() dlg.destroy()
def load_profiles(self, selected=None, retry=True): """Load the profiles. :param selected: which profile is already selected. """ # create the ListStore, with the info listed below liststore = gtk.ListStore(str, str, str, int, str) # we will keep the profile instances here self.profile_instances = {None: None} # build the list with the profiles name, description, profile_instance instance_list, invalid_profiles = self.w3af.profiles.get_profile_list() tmpprofiles = [] for profile_obj in instance_list: nom = profile_obj.get_name() desc = profile_obj.get_desc() tmpprofiles.append((nom, desc, profile_obj)) # Also add to that list the "selected" profile, that was specified by # the user with the "-p" parameter when executing w3af if self._parameter_profile: try: profile_obj = profile(self._parameter_profile) except BaseFrameworkException: raise ValueError( _("The profile %r does not exists!") % self._parameter_profile) else: nom = profile_obj.get_name() desc = profile_obj.get_desc() # I don't want to add duplicates, so I perform this test: add_to_list = True for nom_tmp, desc_tmp, profile_tmp in tmpprofiles: if nom_tmp == nom and desc_tmp == desc: add_to_list = False break if add_to_list: tmpprofiles.append((nom, desc, profile_obj)) # Create the liststore using a specially sorted list, what I basically # want is the empty profile at the beginning of the list, and the rest # sorted in alpha order tmpprofiles = sorted(tmpprofiles) tmpprofiles_special_order = [] for nom, desc, profile_obj in tmpprofiles: if nom == 'empty_profile': tmpprofiles_special_order.insert(0, (nom, desc, profile_obj)) else: tmpprofiles_special_order.append((nom, desc, profile_obj)) # And now create the liststore and the internal dict for nom, desc, profile_obj in tmpprofiles_special_order: prfid = str(id(profile_obj)) self.profile_instances[prfid] = profile_obj liststore.append([nom, desc, prfid, 0, nom]) # set this liststore self.liststore = liststore self.set_model(liststore) # select the indicated one self.selectedProfile = None if selected is None: self.set_cursor(0) self._use_profile() else: for i, (nom, desc, prfid, changed, perm) in enumerate(liststore): the_prof = self.profile_instances[prfid] if selected == the_prof.get_profile_file() or \ selected == the_prof.get_name(): self.set_cursor(i) self._use_profile() break else: # In some cases, this function is called in a thread while # the profile file is being stored to disk. Because of that # it might happen that the profile "is there" but didn't get # loaded properly in the first call to load_profiles. if retry: self.load_profiles(selected, retry=False) else: self.set_cursor(0) # Now that we've finished loading everything, show the invalid profiles # in a nice pop-up window if invalid_profiles: message = 'The following profiles are invalid and failed to load:\n' for i in invalid_profiles: message += '\n\t- ' + i message += '\n\nPlease click OK to continue without these profiles.' dlg = gtk.MessageDialog(None, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, message) dlg.run() dlg.destroy()
def _assert_exists(self, profile_name): try: profile(profile_name) except: assert False, 'The %s profile does NOT exist!' % profile_name
def use_profile(self, profile_name, workdir=None): """ Gets all the information from the profile and stores it in the w3af core plugins / target attributes for later use. :raise BaseFrameworkException: if the profile to load has some type of problem, or the plugins are incorrectly configured. """ # Clear all enabled plugins if profile_name is None if profile_name is None: self._w3af_core.plugins.zero_enabled_plugins() return # This might raise an exception (which we don't want to handle) when # the profile does not exist profile_inst = profile(profile_name, workdir) # It exists, work with it! # Set the target settings of the profile to the core self._w3af_core.target.set_options(profile_inst.get_target()) # Set the misc and http settings # # IGNORE the following parameters from the profile: # - misc_settings.local_ip_address # profile_misc_settings = profile_inst.get_misc_settings() if "local_ip_address" in profile_inst.get_misc_settings(): profile_misc_settings["local_ip_address"].set_value(get_local_ip()) misc_settings = MiscSettings() misc_settings.set_options(profile_misc_settings) self._w3af_core.uri_opener.settings.set_options(profile_inst.get_http_settings()) # # Handle plugin options # error_fmt = ( "The profile you are trying to load (%s) seems to be" " outdated, this is a common issue which happens when the" " framework is updated and one of its plugins adds/removes" " one of the configuration parameters referenced by a" " profile, or the plugin is removed all together.\n\n" "The profile was loaded but some of your settings might" " have been lost. This is the list of issues that were" " found:\n\n" " - %s\n" "\nWe recommend you review the specific plugin" " configurations, apply the required changes and save" " the profile in order to update it and avoid this" " message. If this warning does not disappear you can" " manually edit the profile file to fix it." ) error_messages = [] core_set_plugins = self._w3af_core.plugins.set_plugins for plugin_type in self._w3af_core.plugins.get_plugin_types(): plugin_names = profile_inst.get_enabled_plugins(plugin_type) # Handle errors that might have been triggered from a possibly # invalid profile try: unknown_plugins = core_set_plugins(plugin_names, plugin_type, raise_on_error=False) except KeyError: msg = 'The profile references the "%s" plugin type which is' " unknown to the w3af framework." error_messages.append(msg % plugin_type) continue for unknown_plugin in unknown_plugins: msg = 'The profile references the "%s.%s" plugin which is' " unknown in the current framework version." error_messages.append(msg % (plugin_type, unknown_plugin)) # Now we set the plugin options, which can also trigger errors with # "outdated" profiles that users could have in their ~/.w3af/ # directory. for plugin_name in set(plugin_names) - set(unknown_plugins): try: plugin_options = profile_inst.get_plugin_options(plugin_type, plugin_name) self._w3af_core.plugins.set_plugin_options(plugin_type, plugin_name, plugin_options) except BaseFrameworkException, w3e: msg = ( 'Setting the options for plugin "%s.%s" raised an' " exception due to unknown or invalid configuration" " parameters. %s" ) error_messages.append(msg % (plugin_type, plugin_name, w3e))
def use_profile(self, profile_name, workdir=None): """ Gets all the information from the profile and stores it in the w3af core plugins / target attributes for later use. @raise BaseFrameworkException: if the profile to load has some type of problem. """ # Clear all enabled plugins if profile_name is None if profile_name is None: self._w3af_core.plugins.zero_enabled_plugins() return # This might raise an exception (which we don't want to handle) when # the profile does not exist profile_inst = profile(profile_name, workdir) # It exists, work with it! # Set the target settings of the profile to the core self._w3af_core.target.set_options(profile_inst.get_target()) # Set the misc and http settings # # IGNORE the following parameters from the profile: # - misc_settings.local_ip_address # profile_misc_settings = profile_inst.get_misc_settings() if 'local_ip_address' in profile_inst.get_misc_settings(): profile_misc_settings['local_ip_address'].set_value(get_local_ip()) misc_settings = MiscSettings() misc_settings.set_options(profile_misc_settings) self._w3af_core.uri_opener.settings.set_options( profile_inst.get_http_settings()) # # Handle plugin options # error_fmt = ('The profile you are trying to load (%s) seems to be' ' outdated, this is a common issue which happens when the' ' framework is updated and one of its plugins adds/removes' ' one of the configuration parameters referenced by a profile' ', or the plugin is removed all together.\n\n' 'The profile was loaded but some of your settings might' ' have been lost. This is the list of issues that were found:\n\n' ' - %s\n' '\nWe recommend you review the specific plugin configurations,' ' apply the required changes and save the profile in order' ' to update it and avoid this message. If this warning does not' ' disappear you can manually edit the profile file to fix it.') error_messages = [] for plugin_type in self._w3af_core.plugins.get_plugin_types(): plugin_names = profile_inst.get_enabled_plugins(plugin_type) # Handle errors that might have been triggered from a possibly # invalid profile try: unknown_plugins = self._w3af_core.plugins.set_plugins(plugin_names, plugin_type, raise_on_error=False) except KeyError: msg = 'The profile references the "%s" plugin type which is'\ ' unknown to the w3af framework.' error_messages.append(msg % plugin_type) continue for unknown_plugin in unknown_plugins: msg = 'The profile references the "%s.%s" plugin which is unknown.' error_messages.append(msg % (plugin_type, unknown_plugin)) # Now we set the plugin options, which can also trigger errors with "outdated" # profiles that users could have in their ~/.w3af/ directory. for plugin_name in set(plugin_names) - set(unknown_plugins): try: plugin_options = profile_inst.get_plugin_options( plugin_type, plugin_name) self._w3af_core.plugins.set_plugin_options(plugin_type, plugin_name, plugin_options) except BaseFrameworkException, w3e: msg = 'Setting the options for plugin "%s.%s" raised an' \ ' exception due to unknown or invalid configuration' \ ' parameters.' msg += ' ' + str(w3e) error_messages.append(msg % (plugin_type, plugin_name))