From 589c1ac9bb29f77b22e3616e3404add7a093c27d Mon Sep 17 00:00:00 2001 From: erwanlr Date: Mon, 8 Jul 2019 13:02:29 +0100 Subject: [PATCH] Only create Versions DF when needed --- app/controllers/enumeration.rb | 9 ----- app/finders/plugin_version.rb | 20 +++-------- app/finders/theme_version.rb | 20 +++-------- lib/wpscan/db/dynamic_finders/plugin.rb | 36 ++++++++++++------- spec/app/controllers/enumeration_spec.rb | 9 ----- spec/app/finders/plugin_version_spec.rb | 17 +++------ spec/app/finders/theme_version_spec.rb | 13 +++---- spec/lib/db/dynamic_finders/plugin_spec.rb | 11 ++++++ .../dynamic_finder/plugin_version_spec.rb | 10 ++---- .../dynamic_finder/theme_version_spec.rb | 10 ++---- 10 files changed, 59 insertions(+), 96 deletions(-) diff --git a/app/controllers/enumeration.rb b/app/controllers/enumeration.rb index 37d52bf4..b1258ceb 100644 --- a/app/controllers/enumeration.rb +++ b/app/controllers/enumeration.rb @@ -7,15 +7,6 @@ module WPScan module Controller # Enumeration Controller class Enumeration < CMSScanner::Controller::Base - def before_scan - DB::DynamicFinders::Plugin.create_versions_finders - DB::DynamicFinders::Theme.create_versions_finders - - # Force the Garbage Collector to run due to the above method being - # quite heavy in objects allocation - GC.start - end - def run enum = ParsedCli.enumerate || {} diff --git a/app/finders/plugin_version.rb b/app/finders/plugin_version.rb index 77c48d52..662361a4 100644 --- a/app/finders/plugin_version.rb +++ b/app/finders/plugin_version.rb @@ -13,25 +13,15 @@ module WPScan def initialize(plugin) finders << PluginVersion::Readme.new(plugin) - load_specific_finders(plugin) + create_and_load_dynamic_versions_finders(plugin) end - # Load the finders associated with the plugin + # Create the dynamic version finders related to the plugin and register them # # @param [ Model::Plugin ] plugin - def load_specific_finders(plugin) - module_name = plugin.classify - - return unless Finders::PluginVersion.constants.include?(module_name) - - mod = Finders::PluginVersion.const_get(module_name) - - mod.constants.each do |constant| - c = mod.const_get(constant) - - next unless c.is_a?(Class) - - finders << c.new(plugin) + def create_and_load_dynamic_versions_finders(plugin) + DB::DynamicFinders::Plugin.create_versions_finders(plugin.slug).each do |finder| + finders << finder.new(plugin) end end end diff --git a/app/finders/theme_version.rb b/app/finders/theme_version.rb index 3e870386..64bf3674 100644 --- a/app/finders/theme_version.rb +++ b/app/finders/theme_version.rb @@ -16,25 +16,15 @@ module WPScan ThemeVersion::Style.new(theme) << ThemeVersion::WooFrameworkMetaGenerator.new(theme) - load_specific_finders(theme) + create_and_load_dynamic_versions_finders(theme) end - # Load the finders associated with the theme + # Create the dynamic version finders related to the theme and register them # # @param [ Model::Theme ] theme - def load_specific_finders(theme) - module_name = theme.classify - - return unless Finders::ThemeVersion.constants.include?(module_name) - - mod = Finders::ThemeVersion.const_get(module_name) - - mod.constants.each do |constant| - c = mod.const_get(constant) - - next unless c.is_a?(Class) - - finders << c.new(theme) + def create_and_load_dynamic_versions_finders(theme) + DB::DynamicFinders::Theme.create_versions_finders(theme.slug).each do |finder| + finders << finder.new(theme) end end end diff --git a/lib/wpscan/db/dynamic_finders/plugin.rb b/lib/wpscan/db/dynamic_finders/plugin.rb index e22abf8d..ab0e605f 100644 --- a/lib/wpscan/db/dynamic_finders/plugin.rb +++ b/lib/wpscan/db/dynamic_finders/plugin.rb @@ -73,23 +73,33 @@ module WPScan version_finder_module.const_get(constant_name) end - def self.create_versions_finders - versions_finders_configs.each do |slug, finders| - mod = maybe_create_module(slug) + # Create the dynamic finders related to the given slug, and return the created classes + # + # @param [ String ] slug + # + # @return [ Array ] The created classes + def self.create_versions_finders(slug) + created = [] + mod = maybe_create_module(slug) - finders.each do |finder_class, config| - klass = config['class'] || finder_class + versions_finders_configs[slug]&.each do |finder_class, config| + klass = config['class'] || finder_class - # Instead of raising exceptions, skip unallowed/already defined finders - # So that, when new DF configs are put in the .yml - # users with old version of WPScan will still be able to scan blogs - # when updating the DB but not the tool - next if mod.constants.include?(finder_class.to_sym) || - !allowed_classes.include?(klass.to_sym) + # Instead of raising exceptions, skip unallowed/already defined finders + # So that, when new DF configs are put in the .yml + # users with old version of WPScan will still be able to scan blogs + # when updating the DB but not the tool - version_finder_super_class(klass).create_child_class(mod, finder_class.to_sym, config) - end + next unless allowed_classes.include?(klass.to_sym) + + created << if mod.constants.include?(finder_class.to_sym) + mod.const_get(finder_class.to_sym) + else + version_finder_super_class(klass).create_child_class(mod, finder_class.to_sym, config) + end end + + created end # The idea here would be to check if the class exist in diff --git a/spec/app/controllers/enumeration_spec.rb b/spec/app/controllers/enumeration_spec.rb index 10f15c40..0ad85094 100644 --- a/spec/app/controllers/enumeration_spec.rb +++ b/spec/app/controllers/enumeration_spec.rb @@ -102,15 +102,6 @@ describe WPScan::Controller::Enumeration do end end - describe '#before_scan' do - it 'creates the Dynamic Finders' do - expect(WPScan::DB::DynamicFinders::Plugin).to receive(:create_versions_finders) - expect(WPScan::DB::DynamicFinders::Theme).to receive(:create_versions_finders) - - controller.before_scan - end - end - describe '#run' do context 'when no :enumerate' do before do diff --git a/spec/app/finders/plugin_version_spec.rb b/spec/app/finders/plugin_version_spec.rb index 66688ae1..2c528de9 100644 --- a/spec/app/finders/plugin_version_spec.rb +++ b/spec/app/finders/plugin_version_spec.rb @@ -1,8 +1,5 @@ # frozen_string_literal: true -# If this file is tested alone (rspec path-to-this-file), then there will be an error about -# constants not being intilialized. This is due to the Dynamic Finders. - describe WPScan::Finders::PluginVersion::Base do subject(:plugin_version) { described_class.new(plugin) } let(:plugin) { WPScan::Model::Plugin.new(slug, target) } @@ -15,7 +12,7 @@ describe WPScan::Finders::PluginVersion::Base do expect(plugin_version.finders.map { |f| f.class.to_s.demodulize }).to match_array @expected end - context 'when no related specific finders' do + context 'when no related dynamic finders' do let(:slug) { 'spec' } it 'contains the default finders' do @@ -25,19 +22,13 @@ describe WPScan::Finders::PluginVersion::Base do # Dynamic Version Finders are not tested here, they are in # spec/lib/finders/dynamic_finder/plugin_versions_spec - context 'when specific finders' do - let(:specific) do - { - # None so far - } - end - + context 'when dynamic finders' do WPScan::DB::DynamicFinders::Plugin.versions_finders_configs.each do |plugin_slug, configs| context "when #{plugin_slug} plugin" do let(:slug) { plugin_slug } - it 'contains the expected finders (default + specific + the dynamic ones)' do - @expected = default_finders + [*specific[plugin_slug]] + configs.keys + it 'contains the expected finders (default + the dynamic ones)' do + @expected = default_finders + configs.keys end end end diff --git a/spec/app/finders/theme_version_spec.rb b/spec/app/finders/theme_version_spec.rb index 18a3f0fa..e516f4be 100644 --- a/spec/app/finders/theme_version_spec.rb +++ b/spec/app/finders/theme_version_spec.rb @@ -13,20 +13,21 @@ describe WPScan::Finders::ThemeVersion::Base do expect(theme_version.finders.map { |f| f.class.to_s.demodulize }).to eql @expected end - context 'when no related specific finders' do + context 'when no related dynamic finders' do it 'contains the default finders' do @expected = default_finders end end - context 'when specific finders' do - { - }.each do |theme_slug, specific_finders| + # Dynamic Version Finders are not tested here, they are in + # spec/lib/finders/dynamic_finder/theme_versions_spec + context 'when dynamic finders' do + WPScan::DB::DynamicFinders::Theme.versions_finders_configs.each do |theme_slug, configs| context "when #{theme_slug} theme" do let(:slug) { theme_slug } - it 'contains the expected finders' do - @expected = default_finders + specific_finders + it 'contains the expected finders (default + the dynamic ones)' do + @expected = default_finders + configs.keys end end end diff --git a/spec/lib/db/dynamic_finders/plugin_spec.rb b/spec/lib/db/dynamic_finders/plugin_spec.rb index 91baa5ee..aabba1f4 100644 --- a/spec/lib/db/dynamic_finders/plugin_spec.rb +++ b/spec/lib/db/dynamic_finders/plugin_spec.rb @@ -46,6 +46,17 @@ describe WPScan::DB::DynamicFinders::Plugin do describe '.create_versions_finders' do # handled and tested in spec/lib/finders/dynamic_finders/plugin_version_spec + + describe 'Try to create the finders twice' do + # let's just test one slug, no need to test them all + let(:slug) { '12-step-meeting-list' } + + it 'does not raise an error when the class already exists' do + WPScan::DB::DynamicFinders::Plugin.create_versions_finders(slug) + + expect { WPScan::DB::DynamicFinders::Plugin.create_versions_finders(slug) }.to_not raise_error + end + end end describe '.version_finder_super_class' do diff --git a/spec/lib/finders/dynamic_finder/plugin_version_spec.rb b/spec/lib/finders/dynamic_finder/plugin_version_spec.rb index 18d84811..8fa96ff8 100644 --- a/spec/lib/finders/dynamic_finder/plugin_version_spec.rb +++ b/spec/lib/finders/dynamic_finder/plugin_version_spec.rb @@ -16,15 +16,9 @@ expected_all = df_expected_all['plugins'] -WPScan::DB::DynamicFinders::Plugin.create_versions_finders - -describe 'Try to create the finders twice' do - it 'does not raise an error when the class already exists' do - expect { WPScan::DB::DynamicFinders::Plugin.create_versions_finders }.to_not raise_error - end -end - WPScan::DB::DynamicFinders::Plugin.versions_finders_configs.each do |slug, configs| + WPScan::DB::DynamicFinders::Plugin.create_versions_finders(slug) + configs.each do |finder_class, config| finder_super_class = config['class'] || finder_class diff --git a/spec/lib/finders/dynamic_finder/theme_version_spec.rb b/spec/lib/finders/dynamic_finder/theme_version_spec.rb index 8d25ef83..6ae926e5 100644 --- a/spec/lib/finders/dynamic_finder/theme_version_spec.rb +++ b/spec/lib/finders/dynamic_finder/theme_version_spec.rb @@ -16,15 +16,9 @@ expected_all = df_expected_all['themes'] -WPScan::DB::DynamicFinders::Theme.create_versions_finders - -describe 'Try to create the finders twice' do - it 'does not raise an error when the class already exists' do - expect { WPScan::DB::DynamicFinders::Theme.create_versions_finders }.to_not raise_error - end -end - WPScan::DB::DynamicFinders::Theme.versions_finders_configs.each do |slug, configs| + WPScan::DB::DynamicFinders::Theme.create_versions_finders(slug) + configs.each do |finder_class, config| finder_super_class = config['class'] || finder_class