HELLO v3!!!

This commit is contained in:
Ryan Dewhurst
2018-09-26 21:12:01 +02:00
parent 28b9c15256
commit d268a86795
1871 changed files with 988118 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
require 'spec_helper'
describe WPScan::Finders::ConfigBackups::KnownFilenames do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'config_backups') }
let(:opts) { { list: File.join(WPScan::DB_DIR, 'config_backups.txt') } }
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
expect(target).to receive(:homepage_or_404?).at_least(1).and_return(false)
finder.potential_urls(opts).each_key do |url|
stub_request(:get, url).to_return(status: 404)
end
end
context 'when all files are 404s' do
it 'returns an empty array' do
expect(finder.aggressive(opts)).to eql []
end
end
context 'when some files exist' do
let(:files) { ['%23wp-config.php%23', 'wp-config.bak'] }
let(:config_backup) { File.read(File.join(fixtures, 'wp-config.php')) }
before do
files.each do |file|
stub_request(:get, "#{url}#{file}").to_return(body: config_backup)
end
end
it 'returns the expected Array<ConfigBackup>' do
expected = []
files.each do |file|
url = "#{target.url}#{file}"
expected << WPScan::ConfigBackup.new(
url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
end
expect(finder.aggressive(opts)).to eql expected
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::ConfigBackups::Base do
subject(:config_backups) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(config_backups.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownFilenames]
end
end
end

View File

@@ -0,0 +1,69 @@
require 'spec_helper'
describe WPScan::Finders::DbExports::KnownLocations do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/aa/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'db_exports') }
let(:opts) { { list: File.join(WPScan::DB_DIR, 'db_exports.txt') } }
describe '#potential_urls' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
end
it 'replace {domain_name} by its value' do
expect(finder.potential_urls(opts).keys).to eql %w[
http://ex.lo/aa/ex.sql
http://ex.lo/aa/wordpress.sql
http://ex.lo/aa/backup/ex.zip
http://ex.lo/aa/backup/mysql.sql
http://ex.lo/aa/backups/ex.sql.gz
http://ex.lo/aa/backups/db_backup.sql
]
end
end
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
expect(target).to receive(:homepage_or_404?).at_least(1).and_return(false)
finder.potential_urls(opts).each_key do |url|
stub_request(:get, url).to_return(status: 404)
end
end
context 'when all files are 404s' do
it 'returns an empty array' do
expect(finder.aggressive(opts)).to eql []
end
end
context 'when some files exist' do
let(:files) { %w[ex.sql backups/db_backup.sql] }
let(:db_export) { File.read(File.join(fixtures, 'dump.sql')) }
before do
files.each do |file|
stub_request(:get, "#{url}#{file}").to_return(body: db_export)
end
end
it 'returns the expected Array<DbExport>' do
expected = []
files.each do |file|
url = "#{target.url}#{file}"
expected << WPScan::DbExport.new(
url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
end
expect(finder.aggressive(opts)).to eql expected
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::DbExports::Base do
subject(:db_exports) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(db_exports.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownLocations]
end
end
end

View File

@@ -0,0 +1,64 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::BackupDB do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'backup_db') }
let(:wp_content) { 'wp-content' }
let(:dir_url) { target.url("#{wp_content}/backup-db/") }
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
describe '#aggressive' do
before { stub_request(:get, dir_url).to_return(status: status, body: body) }
let(:body) { '' }
context 'when not a 200 or 403' do
let(:status) { 404 }
its(:aggressive) { should be_nil }
end
context 'when 200 and matching the homepage' do
before { expect(target).to receive(:homepage_or_404?).and_return(true) }
let(:status) { 200 }
its(:aggressive) { should be_nil }
end
context 'when 200 or 403' do
before { expect(target).to receive(:homepage_or_404?).and_return(false) }
let(:status) { 200 }
after do
found = finder.aggressive
expect(found).to eql WPScan::InterestingFinding.new(
dir_url,
confidence: 70,
found_by: described_class::DIRECT_ACCESS
)
expect(found.interesting_entries).to eq @expected_entries
end
context 'when no directory listing' do
it 'returns an empty interesting_findings attribute' do
@expected_entries = []
end
end
context 'when directory listing enabled' do
let(:body) { File.read(File.join(fixtures, 'dir_listing.html')) }
it 'returns the expected interesting_findings attribute' do
@expected_entries = %w[sqldump.sql test.txt]
end
end
end
end
end

View File

@@ -0,0 +1,34 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::DebugLog do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'debug_log') }
let(:wp_content) { 'wp-content' }
let(:log_url) { target.url("#{wp_content}/debug.log") }
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
describe '#aggressive' do
before { stub_request(:get, log_url).to_return(body: body) }
context 'when empty file' do
let(:body) { '' }
its(:aggressive) { should be_nil }
end
context 'when a log file' do
let(:body) { File.read(File.join(fixtures, 'debug.log')) }
it 'returns the InterestingFinding' do
expect(finder.aggressive).to eql WPScan::InterestingFinding.new(
log_url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'duplicator_installer_log') }
let(:filename) { 'installer-log.txt' }
let(:log_url) { target.url(filename) }
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
stub_request(:get, log_url).to_return(body: body)
end
context 'when the body does not match' do
let(:body) { '' }
its(:aggressive) { should be_nil }
end
context 'when the body matches' do
let(:body) { File.read(File.join(fixtures, filename)) }
it 'returns the InterestingFinding' do
expect(finder.aggressive).to eql WPScan::InterestingFinding.new(
log_url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
end
end
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::EmergencyPwdResetScript do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'emergency_pwd_reset_script') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,37 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'fpd') }
let(:file_url) { target.url('wp-includes/rss-functions.php') }
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
stub_request(:get, file_url).to_return(body: body)
end
context 'when empty file' do
let(:body) { '' }
its(:aggressive) { should be_nil }
end
context 'when a log file' do
let(:body) { File.read(File.join(fixtures, 'rss_functions.php')) }
it 'returns the InterestingFinding' do
found = finder.aggressive
expect(found).to eql WPScan::InterestingFinding.new(
file_url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
expect(found.interesting_entries).to eql %w[/blog/wp-includes/rss-functions.php]
end
end
end
end

View File

@@ -0,0 +1,16 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::MuPlugins do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'mu_plugins') }
describe '#passive' do
xit
end
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::Multisite do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'multisite') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,46 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::Readme do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'readme') }
describe '#aggressive' do
before do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
finder.potential_files.each do |file|
stub_request(:get, target.url(file)).to_return(status: 404)
end
end
context 'when no file present' do
its(:aggressive) { should be_nil }
end
# TODO: case when multiple files are present ? (should return only the first one found)
context 'when a file exists' do
let(:file) { finder.potential_files.sample }
let(:readme) { File.read(File.join(fixtures, 'readme-3.9.2.html')) }
before { stub_request(:get, target.url(file)).to_return(body: readme) }
it 'returns the expected InterestingFinding' do
expected = WPScan::InterestingFinding.new(
target.url(file),
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
expect(finder.aggressive).to eql expected
end
end
end
describe '#potential_files' do
it 'does not contain duplicates' do
expect(finder.potential_files.flatten.uniq.length).to eql finder.potential_files.length
end
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::Registration do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'registration') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::TmmDbMigrate do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'tmm_db_migrate') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::UploadDirectoryListing do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_directory_listing') }
let(:wp_content) { 'wp-content' }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,50 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::UploadSQLDump do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'interesting_findings', 'upload_sql_dump') }
let(:wp_content) { 'wp-content' }
describe '#aggressive' do
before { expect(target).to receive(:content_dir).at_least(1).and_return(wp_content) }
after { expect(finder.aggressive).to eql @expected }
context 'when not a 200' do
it 'returns nil' do
stub_request(:get, finder.dump_url).to_return(status: 404)
@expected = nil
end
end
context 'when a 200' do
before do
stub_request(:get, finder.dump_url)
.to_return(status: 200, body: File.read(File.join(fixtures, fixture)))
end
context 'when the body does not match a SQL dump' do
let(:fixture) { 'not_sql.txt' }
it 'returns nil' do
@expected = nil
end
end
context 'when the body matches a SQL dump' do
let(:fixture) { 'dump.sql' }
it 'returns the interesting findings' do
@expected = WPScan::InterestingFinding.new(
finder.dump_url,
confidence: 100,
found_by: described_class::DIRECT_ACCESS
)
end
end
end
end
end

View File

@@ -0,0 +1,21 @@
require 'spec_helper'
describe WPScan::Finders::InterestingFindings::Base do
subject(:files) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
let(:expected) do
%w[
Readme DebugLog FullPathDisclosure
Multisite MuPlugins Registration UploadDirectoryListing TmmDbMigrate
UploadSQLDump
]
end
it 'contains the expected finders' do
expect(files.finders.map { |f| f.class.to_s.demodulize }).to include(*expected)
end
end
end

View File

@@ -0,0 +1,58 @@
require 'spec_helper'
describe WPScan::Finders::MainTheme::CssStyle do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'css_style') }
describe '#passive' do
after do
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, fixture)))
expect(finder.passive).to eql @expected
end
context 'when no in scope style' do
let(:fixture) { 'no_in_scope_style.html' }
it 'returns nil' do
@expected = nil
end
end
context 'when in scope style' do
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
stub_request(:get, /.*.css/)
end
context 'when in a link href' do
let(:fixture) { 'link_href.html' }
it 'returns the expected theme' do
@expected = WPScan::Theme.new(
'twentyfifteen',
target,
found_by: 'Css Style (Passive Detection)',
confidence: 70,
style_url: 'http://wp.lab/wp-content/themes/twentyfifteen/style.css?ver=4.1.1'
)
end
end
context 'when in the style code' do
let(:fixture) { 'style_code.html' }
it 'returns the expected theme' do
@expected = WPScan::Theme.new(
'custom',
target,
found_by: 'Css Style (Passive Detection)',
confidence: 70,
style_url: 'http://wp.lab/wp-content/themes/custom/style.css'
)
end
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'spec_helper'
describe WPScan::Finders::MainTheme::UrlsInHomepage do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
let(:type) { 'themes' }
let(:uniq_links) { false }
let(:uniq_codes) { false }
let(:expected_from_links) { %w[twentyfifteen twentyfifteen twentyfifteen yolo] }
let(:expected_from_codes) { %w[test yolo] }
end
describe '#passive' do
before do
stub_request(:get, /.*.css/)
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'found.html')))
end
it 'returns the expected Themes' do
@expected = []
{ 'twentyfifteen' => 6, 'yolo' => 4, 'test' => 2 }.each do |slug, confidence|
@expected << WPScan::Theme.new(
slug, target, found_by: 'Urls In Homepage (Passive Detection)', confidence: confidence
)
end
expect(finder.passive).to eql @expected
end
end
end

View File

@@ -0,0 +1,39 @@
require 'spec_helper'
describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'main_theme', 'woo_framework_meta_generator') }
describe '#passive' do
after do
stub_request(:get, url).to_return(body: File.read(File.join(fixtures, @file)))
expect(finder.passive).to eql @expected
end
context 'when no Woo generator' do
it 'returns nil' do
@file = 'no_woo_generator.html'
@expected = nil
end
end
context 'when Woo generator' do
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
stub_request(:get, "#{url}wp-content/themes/Merchant/style.css")
end
it 'returns the expected theme' do
@file = 'woo_generator.html'
@expected = WPScan::Theme.new(
'Merchant', target,
found_by: 'Woo Framework Meta Generator (Passive Detection)',
confidence: 80
)
end
end
end
end

View File

@@ -0,0 +1,14 @@
require 'spec_helper'
describe WPScan::Finders::MainTheme::Base do
subject(:main_theme) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(main_theme.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[CssStyle WooFrameworkMetaGenerator UrlsInHomepage]
end
end
end

View File

@@ -0,0 +1,21 @@
require 'spec_helper'
describe WPScan::Finders::Medias::AttachmentBruteForcing do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'medias', 'attachment_brute_forcing') }
describe '#aggressive' do
xit
end
describe '#target_urls' do
it 'returns the expected urls' do
expect(finder.target_urls(range: (1..2))).to eql(
url + '?attachment_id=1' => 1,
url + '?attachment_id=2' => 2
)
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Medias::Base do
subject(:media) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(media.finders.map { |f| f.class.to_s.demodulize }).to eq %w[AttachmentBruteForcing]
end
end
end

View File

@@ -0,0 +1,116 @@
require 'spec_helper'
describe WPScan::Finders::PluginVersion::Readme do
subject(:finder) { described_class.new(plugin) }
let(:plugin) { WPScan::Plugin.new('spec', target) }
let(:target) { WPScan::Target.new('http://wp.lab/') }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugin_version', 'readme') }
def version(number, found_by, confidence)
WPScan::Version.new(
number,
found_by: format('Readme - %s (Aggressive Detection)', found_by),
confidence: confidence,
interesting_entries: [readme_url]
)
end
def stable_tag(number)
version(number, 'Stable Tag', 80)
end
def changelog_section(number)
version(number, 'ChangeLog Section', 50)
end
describe '#aggressive' do
before { expect(target).to receive(:content_dir).and_return('wp-content') }
after do
stub_request(:get, /.*/).to_return(status: 404)
stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, @file)))
expect(finder.aggressive).to eql @expected
end
let(:readme_url) { plugin.url(WPScan::WpItem::READMES.sample) }
context 'when no version' do
it 'returns nil' do
@file = 'no_version.txt'
@expected = nil
end
end
context 'when the stable tag does not contain numbers' do
it 'returns nil' do
@file = 'aa-health-calculator.txt'
@expected = nil
end
end
context 'when empty changelog section' do
it 'returns nil' do
@file = 'all-in-one-facebook.txt'
@expected = nil
end
end
context 'when no changelog section' do
it 'returns nil' do
@file = 'blog-reordering.txt'
@expected = nil
end
end
context 'when leaked from the stable tag' do
it 'returns the expected versions' do
@file = 'simple-login-lockdown-0.4.txt'
@expected = [stable_tag('0.4'), changelog_section('04')]
end
end
context 'when leaked from the version' do
it 'returns it' do
@file = 'wp-photo-plus-5.1.15.txt'
@expected = [stable_tag('5.1.15')]
end
end
context 'when version is in a release date format' do
it 'detects and returns it' do
@file = 's2member.txt'
@expected = [stable_tag('141007')]
end
end
context 'when version contains letters' do
it 'returns it' do
@file = 'beta1.txt'
@expected = [stable_tag('2.0.0-beta1')]
end
end
context 'when parsing the changelog for version numbers' do
{
'changelog_version' => '1.3',
'wp_polls' => '2.64',
'nextgen_gallery' => '2.0.66.33',
'wp_user_frontend' => '1.2.3',
'my_calendar' => '2.1.5',
'nextgen_gallery_2' => '1.9.13',
'advanced-most-recent-posts-mod' => '1.6.5.2',
'a-lead-capture-contact-form-and-tab-button-by-awebvoicecom' => '3.1',
'backup-scheduler' => '1.5.9',
'release_date_slash' => '1.0.4'
}. each do |file, version_number|
context "whith #{file}.txt" do
it 'returns the expected version' do
@file = "#{file}.txt"
@expected = [changelog_section(version_number)]
end
end
end
end
end
end

View File

@@ -0,0 +1,46 @@
require 'spec_helper'
# 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::Plugin.new(slug, target) }
let(:target) { WPScan::Target.new('http://wp.lab/') }
let(:default_finders) { %w[Readme] }
describe '#finders' do
after do
expect(target).to receive(:content_dir).and_return('wp-content')
expect(plugin_version.finders.map { |f| f.class.to_s.demodulize }).to match_array @expected
end
context 'when no related specific finders' do
let(:slug) { 'spec' }
it 'contains the default finders' do
@expected = default_finders
end
end
# 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
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
end
end
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::BodyPattern do
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
let(:expected_all) { df_expected_all['plugins'] }
let(:item_class) { WPScan::Plugin }
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::Comment do
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
let(:expected_all) { df_expected_all['plugins'] }
let(:item_class) { WPScan::Plugin }
end
end

View File

@@ -0,0 +1,15 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::ConfigParser do
xit
# it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
# subject(:finder) { described_class.new(target) }
# let(:target) { WPScan::Target.new(url) }
# let(:url) { 'http://wp.lab/' }
# let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
#
# let(:expected_all) { df_expected_all['plugins'] }
# let(:item_class) { WPScan::Plugin }
# end
end

View File

@@ -0,0 +1,45 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::HeaderPattern do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
def plugin(slug)
WPScan::Plugin.new(slug, target)
end
describe '#passive' do
after do
stub_request(:get, target.url).to_return(headers: headers)
found = finder.passive
expect(found).to match_array @expected
expect(found.first.found_by).to eql 'Header Pattern (Passive Detection)' unless found.empty?
end
context 'when empty headers' do
let(:headers) { {} }
it 'returns an empty array' do
@expected = []
end
end
context 'when headers' do
before { expect(target).to receive(:content_dir).and_return('wp-content') }
let(:headers) { JSON.parse(File.read(File.join(fixtures, 'header_pattern_passive_all.html'))) }
it 'returns the expected plugins' do
@expected = []
WPScan::DB::DynamicFinders::Plugin.passive_header_pattern_finder_configs.each_key do |slug|
@expected << plugin(slug)
end
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::JavascriptVar do
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
let(:expected_all) { df_expected_all['plugins'] }
let(:item_class) { WPScan::Plugin }
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::KnownLocations do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'known_locations') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,16 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::QueryParameter do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
describe '#passive' do
its(:passive) { should be nil }
end
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,27 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::UrlsInHomepage do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'plugins', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
let(:type) { 'plugins' }
let(:uniq_links) { true }
let(:uniq_codes) { true }
let(:expected_from_links) { (1..4).map { |i| "dl-#{i}" } }
let(:expected_from_codes) { (1..6).map { |i| "dc-#{i}" } }
end
describe '#passive' do
before do
stub_request(:get, finder.target.url)
.to_return(body: File.read(File.join(fixtures, 'found.html')))
expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content')
end
xit
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::Xpath do
it_behaves_like WPScan::Finders::DynamicFinder::WpItems::Finder do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(DYNAMIC_FINDERS_FIXTURES, 'plugin_version') }
let(:expected_all) { df_expected_all['plugins'] }
let(:item_class) { WPScan::Plugin }
end
end

View File

@@ -0,0 +1,14 @@
require 'spec_helper'
describe WPScan::Finders::Plugins::Base do
subject(:plugins) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(plugins.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[UrlsInHomepage HeaderPattern Comment Xpath BodyPattern JavascriptVar KnownLocations]
end
end
end

View File

@@ -0,0 +1,98 @@
require 'spec_helper'
describe WPScan::Finders::ThemeVersion::Style do
subject(:finder) { described_class.new(theme) }
let(:theme) { WPScan::Theme.new('spec', target) }
let(:target) { WPScan::Target.new('http://wp.lab/') }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'style') }
before :all do
Typhoeus::Config.cache = WPScan::Cache::Typhoeus.new(File.join(SPECS, 'cache'))
end
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
stub_request(:get, /.*.css/).and_return(body: defined?(style_body) ? style_body : '')
end
describe '#passive' do
before { expect(finder).to receive(:cached_style?).and_return(cached?) }
after { finder.passive }
context 'when the style_url request has been cached' do
let(:cached?) { true }
it 'calls the style_version' do
expect(finder).to receive(:style_version)
end
end
context 'when the style_url request has not been cached' do
let(:cached?) { false }
it 'returns nil' do
expect(finder).to_not receive(:style_version)
end
end
end
describe '#aggressive' do
before { expect(finder).to receive(:cached_style?).and_return(cached?) }
after { finder.aggressive }
context 'when the style_url request has been cached' do
let(:cached?) { true }
it 'returns nil' do
expect(finder).to_not receive(:style_version)
end
end
context 'when the style_url request has not been cached' do
let(:cached?) { false }
it 'calls the style_version' do
expect(finder).to receive(:style_version)
end
end
end
describe '#cached_style?' do
it 'calls the Cache with the correct arguments' do
expected = Typhoeus::Request.new(
theme.style_url,
finder.browser.default_request_params.merge(method: :get)
)
expect(Typhoeus::Config.cache).to receive(:get) { |arg| expect(arg).to eql expected }
finder.cached_style?
end
end
describe '#style_version' do
{
'inline' => '1.5.1',
'firefart' => '1.0.0',
'tralling_quote' => '1.3',
'no_version_tag' => nil,
'trunk_version' => nil,
'no_version' => nil
}.each do |file, expected_version|
context "when #{file}" do
let(:style_body) { File.new(File.join(fixtures, "#{file}.css")) }
it 'returns the expected version' do
expected = if expected_version
WPScan::Version.new(
expected_version,
confidence: 80,
interesting_entries: ["#{theme.style_url}, Version: #{expected_version}"]
)
end
expect(finder.style_version).to eql expected
end
end
end
end
end

View File

@@ -0,0 +1,41 @@
require 'spec_helper'
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
subject(:finder) { described_class.new(theme) }
let(:theme) { WPScan::Theme.new(slug, target) }
let(:target) { WPScan::Target.new('http://wp.lab/') }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'theme_version', 'woo_framework_meta_generator') }
before do
expect(target).to receive(:content_dir).and_return('wp-content')
stub_request(:get, /\.css\z/)
end
describe '#passive' do
after do
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, 'editorial-1.3.5.html')))
expect(finder.passive).to eql @expected
end
context 'when the theme slug does not match' do
let(:slug) { 'spec' }
it 'returns nil' do
@expected = nil
end
end
context 'when the theme slug matches' do
let(:slug) { 'Editorial' }
it 'return the expected version' do
@expected = WPScan::Version.new(
'1.3.5',
found_by: 'Woo Framework Meta Generator (Passive Detection)',
confidence: 80
)
end
end
end
end

View File

@@ -0,0 +1,35 @@
require 'spec_helper'
describe WPScan::Finders::ThemeVersion::Base do
subject(:theme_version) { described_class.new(theme) }
let(:theme) { WPScan::Plugin.new(slug, target) }
let(:target) { WPScan::Target.new('http://wp.lab/') }
let(:slug) { 'spec' }
let(:default_finders) { %w[Style WooFrameworkMetaGenerator] }
describe '#finders' do
after do
expect(target).to receive(:content_dir).and_return('wp-content')
expect(theme_version.finders.map { |f| f.class.to_s.demodulize }).to eql @expected
end
context 'when no related specific finders' do
it 'contains the default finders' do
@expected = default_finders
end
end
context 'when specific finders' do
{
}.each do |theme_slug, specific_finders|
context "when #{theme_slug} theme" do
let(:slug) { theme_slug }
it 'contains the expected finders' do
@expected = default_finders + specific_finders
end
end
end
end
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::Themes::KnownLocations do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'known_locations') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,20 @@
require 'spec_helper'
describe WPScan::Finders::Themes::UrlsInHomepage do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'themes', 'urls_in_homepage') }
it_behaves_like 'App::Finders::WpItems::URLsInHomepage' do
let(:type) { 'themes' }
let(:uniq_links) { true }
let(:uniq_codes) { true }
let(:expected_from_links) { %w[dl-1] }
let(:expected_from_codes) { %w[dc-1] }
end
describe '#passive' do
xit
end
end

View File

@@ -0,0 +1,14 @@
require 'spec_helper'
describe WPScan::Finders::Themes::Base do
subject(:themes) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(themes.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[UrlsInHomepage KnownLocations]
end
end
end

View File

@@ -0,0 +1,36 @@
require 'spec_helper'
describe WPScan::Finders::TimthumbVersion::BadRequest do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Timthumb.new(url) }
let(:url) { 'http://ex.lo/timthumb.php' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumb_version', 'bad_request') }
describe '#aggressive' do
before { stub_request(:get, url).to_return(body: File.read(File.join(fixtures, file))) }
after { expect(finder.aggressive).to eql @expected }
context 'when no version' do
let(:file) { 'no_version.php' }
it 'returns nil' do
@expected = nil
end
end
context 'when a version' do
let(:file) { '2.8.14.php' }
it 'returns the expected version' do
@expected = WPScan::Version.new(
'2.8.14',
confidence: 90,
found_by: 'Bad Request (Aggressive Detection)',
interesting_entries: [
"#{url}, TimThumb version : 2.8.14"
]
)
end
end
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::TimthumbVersion::Base do
subject(:timthumb_version) { described_class.new(target) }
let(:target) { WPScan::Timthumb.new(url) }
let(:url) { 'http://ex.lo/timthumb.php' }
describe '#finders' do
it 'contains the expected finders' do
expect(timthumb_version.finders.map { |f| f.class.to_s.demodulize }).to eq %w[BadRequest]
end
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::Timthumbs::KnownLocations do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'timthumbs', 'known_locations') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,13 @@
require 'spec_helper'
describe WPScan::Finders::Timthumbs::Base do
subject(:timthumb) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(timthumb.finders.map { |f| f.class.to_s.demodulize }).to eq %w[KnownLocations]
end
end
end

View File

@@ -0,0 +1,62 @@
require 'spec_helper'
describe WPScan::Finders::Users::AuthorIdBruteForcing do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_id_brute_forcing') }
describe '#aggressive' do
xit
end
describe '#target_urls' do
it 'returns the correct URLs' do
expect(finder.target_urls(range: (1..2))).to eql(
url + '?author=1' => 1,
url + '?author=2' => 2
)
end
end
describe '#potential_username' do
[
'4.1.1', '4.1.1-permalink',
'3.0', '3.0-permalink',
'2.9.2', '2.9.2-permalink'
].each do |file|
it "returns 'admin' from #{file}.html" do
body = File.read(File.join(fixtures, "#{file}.html"))
res = Typhoeus::Response.new(body: body)
expect(finder.username_from_response(res)).to eql 'admin'
end
end
end
describe '#display_name_from_body' do
context 'when display name' do
[
'4.1.1', '4.1.1-permalink',
'3.0', '3.0-permalink',
'2.9.2', '2.9.2-permalink'
].each do |file|
it "returns 'admin display_name' from #{file}.html" do
body = File.read(File.join(fixtures, "#{file}.html"))
expect(finder.display_name_from_body(body)).to eql 'admin display_name'
end
end
end
context 'when no display_name' do
['4.1.1', '3.0', '2.9.2'].each do |file|
it "returns nil for #{file}-empty.html" do
body = File.read(File.join(fixtures, "#{file}-empty.html"))
expect(finder.display_name_from_body(body)).to eql nil
end
end
end
end
end

View File

@@ -0,0 +1,27 @@
require 'spec_helper'
describe WPScan::Finders::Users::AuthorPosts do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'author_posts') }
describe '#passive' do
xit
end
describe '#potential_usernames' do
it 'returns the expected usernames' do
res = Typhoeus::Response.new(body: File.read(File.join(fixtures, 'potential_usernames.html')))
results = finder.potential_usernames(res)
expect(results).to eql([
['admin', 'Author Pattern', 100],
['admin display_name', 'Display Name', 30],
['editor', 'Author Pattern', 100],
['editor', 'Display Name', 30]
])
end
end
end

View File

@@ -0,0 +1,32 @@
require 'spec_helper'
describe WPScan::Finders::Users::LoginErrorMessages do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'login_error_messages') }
describe '#aggressive' do
xit
end
describe '#usernames' do
let(:opts) { { found: [] } }
after { expect(subject.usernames(opts)).to eql @expected }
context 'when no :list provided' do
it 'returns an empty list' do
@expected = []
end
end
context 'when :list provided' do
let(:opts) { super().merge(list: %w[u1 u2]) }
it 'returns the expected array' do
@expected = opts[:list]
end
end
end
end

View File

@@ -0,0 +1,12 @@
require 'spec_helper'
describe WPScan::Finders::Users::OembedApi do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'oembed_api') }
describe '#aggressive' do
xit
end
end

View File

@@ -0,0 +1,102 @@
require 'spec_helper'
describe WPScan::Finders::Users::RSSGenerator do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('users', 'rss_generator') }
let(:rss_fixture) { File.read(fixtures.join('feed.xml')) }
describe '#passive, #aggressive' do
before do
allow(target).to receive(:sub_dir).and_return(false)
stub_request(:get, target.url).to_return(body: File.read(homepage_fixture))
end
context 'when no RSS link in homepage' do
let(:homepage_fixture) { fixtures.join('homepage_no_links.html') }
its(:passive) { should eql [] }
it 'returns the expected from #aggressive' do
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
stub_request(:get, target.url('comments/feed/'))
stub_request(:get, target.url('feed/rss/'))
stub_request(:get, target.url('feed/rss2/'))
expect(finder.aggressive).to eql [
CMSScanner::User.new(
'admin',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
),
CMSScanner::User.new(
'Aa Días-Gildés',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
)
]
end
end
context 'when RSS link in homepage' do
let(:homepage_fixture) { File.join(fixtures, 'homepage_links.html') }
it 'returns the expected from #passive' do
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
expect(finder.passive).to eql [
CMSScanner::User.new(
'admin',
confidence: 50,
found_by: 'Rss Generator (Passive Detection)'
),
CMSScanner::User.new(
'Aa Días-Gildés',
confidence: 50,
found_by: 'Rss Generator (Passive Detection)'
)
]
end
context 'when :mixed mode' do
it 'avoids checking existing URL/s from #passive' do
stub_request(:get, target.url('comments/feed/')).to_return(body: rss_fixture)
expect(finder.aggressive(mode: :mixed)).to eql [
CMSScanner::User.new(
'admin',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
),
CMSScanner::User.new(
'Aa Días-Gildés',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
)
]
end
end
context 'when no mode' do
it 'checks the first URL detected from the URLs' do
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
expect(finder.aggressive).to eql [
CMSScanner::User.new(
'admin',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
),
CMSScanner::User.new(
'Aa Días-Gildés',
confidence: 50,
found_by: 'Rss Generator (Aggressive Detection)'
)
]
end
end
end
end
end

View File

@@ -0,0 +1,47 @@
require 'spec_helper'
describe WPScan::Finders::Users::WpJsonApi do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://wp.lab/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'users', 'wp_json_api') }
describe '#aggressive' do
before do
# allow(target).to receive(:content_dir).and_return('wp-content')
allow(target).to receive(:sub_dir).and_return(false)
stub_request(:get, finder.api_url).to_return(body: body)
end
context 'when not a JSON response' do
let(:body) { '' }
its(:aggressive) { should eql([]) }
end
context 'when a JSON response' do
context 'when unauthorised' do
let(:body) { File.read(File.join(fixtures, '401.json')) }
its(:aggressive) { should eql([]) }
end
context 'when limited exposure (WP >= 4.7.1)' do
let(:body) { File.read(File.join(fixtures, '4.7.2.json')) }
it 'returns the expected array of users' do
users = finder.aggressive
expect(users.size).to eql 1
user = users.first
expect(user.id).to eql 1
expect(user.username).to eql 'admin'
expect(user.confidence).to eql 100
expect(user.interesting_entries).to eql ['http://wp.lab/wp-json/wp/v2/users/']
end
end
end
end
end

View File

@@ -0,0 +1,14 @@
require 'spec_helper'
describe WPScan::Finders::Users::Base do
subject(:user) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
it 'contains the expected finders' do
expect(user.finders.map { |f| f.class.to_s.demodulize })
.to eq %w[AuthorPosts WpJsonApi OembedApi RSSGenerator AuthorIdBruteForcing LoginErrorMessages]
end
end
end

View File

@@ -0,0 +1,97 @@
require 'spec_helper'
describe WPScan::Finders::WpVersion::AtomGenerator do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { Pathname.new(FINDERS_FIXTURES).join('wp_version', 'atom_generator') }
let(:atom_fixture) { File.read(fixtures.join('feed', 'atom')) }
describe '#passive, #aggressive' do
before do
allow(target).to receive(:sub_dir).and_return(false)
stub_request(:get, target.url).to_return(body: File.read(homepage_fixture))
end
context 'when no atom links in homepage' do
let(:homepage_fixture) { fixtures.join('no_links.html') }
its(:passive) { should eql [] }
it 'returns the expected from #aggressive' do
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
stub_request(:get, target.url('?feed=atom'))
expect(finder.aggressive).to eql [
WPScan::WpVersion.new(
'4.0',
confidence: 80,
found_by: 'Atom Generator (Aggressive Detection)',
interesting_entries: [
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
"WordPress</generator>'"
]
)
]
end
end
context 'when atom links in homepage' do
let(:homepage_fixture) { File.join(fixtures, 'links.html') }
it 'returns the expected from #passive' do
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
expect(finder.passive).to eql [
WPScan::WpVersion.new(
'4.0',
confidence: 80,
found_by: 'Atom Generator (Passive Detection)',
interesting_entries: [
"#{target.url('?feed=atom')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
"WordPress</generator>'"
]
)
]
end
context 'when :mixed mode' do
it 'avoids checking existing URL/s from #passive' do
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
expect(finder.aggressive(mode: :mixed)).to eql [
WPScan::WpVersion.new(
'4.0',
confidence: 80,
found_by: 'Atom Generator (Aggressive Detection)',
interesting_entries: [
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
"WordPress</generator>'"
]
)
]
end
end
context 'when no mode' do
it 'checks all the URLs' do
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
stub_request(:get, target.url('?feed=atom'))
expect(finder.aggressive).to eql [
WPScan::WpVersion.new(
'4.0',
confidence: 80,
found_by: 'Atom Generator (Aggressive Detection)',
interesting_entries: [
"#{target.url('feed/atom/')}, Match: '<generator uri=\"https://wordpress.org/\" version=\"4.0\">" \
"WordPress</generator>'"
]
)
]
end
end
end
end
end

View File

@@ -0,0 +1,10 @@
require 'spec_helper'
describe WPScan::Finders::WpVersion::RDFGenerator do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rdf_generator') }
xit
end

View File

@@ -0,0 +1,49 @@
require 'spec_helper'
describe WPScan::Finders::WpVersion::Readme do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'readme') }
let(:readme_url) { url + 'readme.html' }
describe '#aggressive' do
before { stub_request(:get, readme_url).to_return(body: File.read(File.join(fixtures, file))) }
after do
expect(target).to receive(:sub_dir).and_return(false)
expect(finder.aggressive).to eql @expected
end
context 'when no version' do
let(:file) { 'no_version.html' }
it 'returns nil' do
@expected = nil
end
end
context 'when invalid version number' do
let(:file) { 'invalid.html' }
it 'returns nil' do
@expected = nil
end
end
context 'when present and valid' do
let(:file) { '4.0.html' }
it 'returns the expected version' do
@expected = WPScan::WpVersion.new(
'4.0',
confidence: 90,
found_by: 'Readme (Aggressive Detection)',
interesting_entries: [
"#{readme_url}, Match: 'Version 4.0'"
]
)
end
end
end
end

View File

@@ -0,0 +1,10 @@
require 'spec_helper'
describe WPScan::Finders::WpVersion::RSSGenerator do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'rss_generator') }
xit
end

View File

@@ -0,0 +1,10 @@
require 'spec_helper'
describe WPScan::Finders::WpVersion::UniqueFingerprinting do
subject(:finder) { described_class.new(target) }
let(:target) { WPScan::Target.new(url).extend(CMSScanner::Target::Server::Apache) }
let(:url) { 'http://ex.lo/' }
let(:fixtures) { File.join(FINDERS_FIXTURES, 'wp_version', 'unique_fingerprinting') }
xit
end

View File

@@ -0,0 +1,25 @@
require 'spec_helper'
# 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::WpVersion::Base do
subject(:wp_version) { described_class.new(target) }
let(:target) { WPScan::Target.new(url) }
let(:url) { 'http://ex.lo/' }
describe '#finders' do
let(:expected) { %w[RSSGenerator AtomGenerator RDFGenerator Readme UniqueFingerprinting] }
let(:expected_dynamic_finders) { WPScan::DB::DynamicFinders::Wordpress.versions_finders_configs.keys }
it 'contains the expected finders' do
finders = wp_version.finders.map { |f| f.class.to_s.demodulize }
expect(finders).to match_array expected + expected_dynamic_finders
expect(finders.first).to eql 'RSSGenerator'
expect(finders.last).to eql 'UniqueFingerprinting'
end
end
end