# frozen_string_literal: true # All Plugin Dynamic Finders returning a Version are tested here. # When adding one to the spec/fixtures/db/dynamic_finder.yml, a few files have # to be edited/created # # - spec/fixtures/dynamic_finder/expected.yml with the expected result/s # - Then, depending on the finder class used: spec/fixtures/dynamic_finder/plugin_version/ # # Furthermore, the fixtures files _passive_all.html are also used by plugins/themes # finders in spec/app/finders/plugins|themes to check the items existence from the homepage # # In case of a failure, it's recommended to use rspec -e "" while fixing. # e.g: rspec -e "WPScan::Finders::PluginVersion::Cardealerpress::HeaderPattern#passive" # The -e option can also be used to test all HeaderPattern, for example: rspec -e "::HeaderPattern" expected_all = df_expected_all['plugins'] 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 # The QueryParameter specs are slow given the huge fixture file # If someone find a fix for that, please share! describe df_tested_class_constant('PluginVersion', finder_class, slug), slow: true do subject(:finder) { described_class.new(plugin) } let(:plugin) { WPScan::Model::Plugin.new(slug, target) } let(:target) { WPScan::Target.new('http://wp.lab/') } let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') } let(:expected) do if expected_all[slug][finder_class].is_a?(Hash) [expected_all[slug][finder_class]] else expected_all[slug][finder_class] end end before { allow(target).to receive(:content_dir).and_return('wp-content') } describe '#passive', slow: true do before do if defined?(stubbed_homepage_res) stub_request(:get, target.url).to_return(stubbed_homepage_res) else stub_request(:get, target.url) end if defined?(stubbed_404_res) stub_request(:get, ERROR_404_URL_PATTERN).to_return(stubbed_404_res) else stub_request(:get, ERROR_404_URL_PATTERN) end end if config['path'] context 'when PATH' do it 'returns nil' do expect(finder.passive).to eql nil end end else context 'when no PATH' do context 'when the version is detected' do context 'from the homepage' do let(:ie_url) { target.url } let(:stubbed_homepage_res) do df_stubbed_response( fixtures.join("#{finder_super_class.underscore}_passive_all.html"), finder_super_class ) end it 'returns the expected version/s' do found = Array(finder.passive) expect(found).to_not be_empty found.each_with_index do |version, index| expected_version = expected.at(index) expected_ie = expected_version['interesting_entries'].map do |ie| ie.gsub(target.url + ',', ie_url + ',') end expect(version).to be_a WPScan::Model::Version expect(version.number).to eql expected_version['number'].to_s expect(version.found_by).to eql expected_version['found_by'] expect(version.interesting_entries).to match_array expected_ie expect(version.confidence).to eql expected_version['confidence'] if expected_version['confidence'] end end end context 'from the 404' do let(:ie_url) { target.error_404_url } let(:stubbed_404_res) do df_stubbed_response( fixtures.join("#{finder_super_class.underscore}_passive_all.html"), finder_super_class ) end it 'returns the expected version/s' do found = Array(finder.passive) expect(found).to_not be_empty found.each_with_index do |version, index| expected_version = expected.at(index) expected_ie = expected_version['interesting_entries'].map do |ie| ie.gsub(target.url + ',', ie_url + ',') end expect(version).to be_a WPScan::Model::Version expect(version.number).to eql expected_version['number'].to_s expect(version.found_by).to eql expected_version['found_by'] expect(version.interesting_entries).to match_array expected_ie expect(version.confidence).to eql expected_version['confidence'] if expected_version['confidence'] end end end end context 'when the version is not detected' do it 'returns nil or an empty array' do expect(finder.passive).to eql finder_super_class == 'QueryParameter' ? [] : nil end end end end end describe '#aggressive' do let(:fixtures) { super().join(slug, finder_class.underscore) } let(:stubbed_response) { { body: 'aa' } } before do stub_request(:get, plugin.url(config['path'])).to_return(stubbed_response) if config['path'] end if config['path'] context 'when the version is detected' do let(:stubbed_response) do df_stubbed_response(fixtures.join(config['path']), finder_super_class) end it 'returns the expected version' do found = Array(finder.aggressive) expect(found).to_not be_empty found.each_with_index do |version, index| expected_version = expected.at(index) expect(version).to be_a WPScan::Model::Version expect(version.number).to eql expected_version['number'].to_s expect(version.found_by).to eql expected_version['found_by'] expect(version.interesting_entries).to match_array expected_version['interesting_entries'] expect(version.confidence).to eql expected_version['confidence'] if expected_version['confidence'] end end end context 'when the version is not detected' do it 'returns nil or an empty array' do expect(finder.aggressive).to eql finder_super_class == 'QueryParameter' ? [] : nil end end else it 'returns nil' do expect(finder.aggressive).to eql nil end end end end end end