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,94 @@
shared_examples WPScan::Finders::DynamicFinder::WpItems::Finder do
let(:passive_fixture) do
File.join(fixtures, "#{described_class.to_s.demodulize.underscore}_passive_all.html")
end
describe '#passive_configs' do
# Not sure if it's worth to do it as it's just a call to something tested
# and an exception will be raised if the method called is wrong
end
describe '#aggressive_configs' do
# Same as above
end
describe '#passive' do
before do
stub_request(:get, target.url).to_return(body: body)
allow(target).to receive(:content_dir).and_return('wp-content')
end
context 'when no matches' do
let(:body) { '' }
it 'returns an empty array' do
expect(finder.passive).to eql([])
end
end
context 'when matches' do
let(:body) { File.read(passive_fixture) }
it 'contains the expected plugins' do
expected = []
finder.passive_configs.each do |slug, configs|
configs.each_key do |finder_class|
expected_finding_opts = expected_all[slug][finder_class]
expected << item_class.new(
slug,
target,
confidence: expected_finding_opts['confidence'] || described_class::DEFAULT_CONFIDENCE,
found_by: expected_finding_opts['found_by']
)
end
end
expect(finder.passive).to match_array(expected.map { |item| eql(item) })
end
end
end
describe '#aggressive' do
its(:aggressive) { should be nil }
end
xdescribe '#aggressive' do
# TODO: Maybe also stub all paths to an empty body and expect an empty array ?
before do
@expected = []
allow(target).to receive(:content_dir).and_return('wp-content')
# Stubbing all requests to the different paths
finder.aggressive_configs.each do |slug, configs|
configs.each do |finder_class, config|
finder_super_class = config['class'] || finder_class
fixture = File.join(fixtures, slug, finder_class.underscore, config['path'])
stubbed_response = df_stubbed_response(fixture, finder_super_class)
path = finder.aggressive_path(slug, config)
expected_finding_opts = expected_all[slug][finder_class]
stub_request(:get, target.url(path)).to_return(stubbed_response)
@expected << item_class.new(
slug,
target,
confidence: expected_finding_opts['confidence'] || described_class::DEFAULT_CONFIDENCE,
found_by: expected_finding_opts['found_by']
)
end
end
end
it 'returns the expected plugins' do
expect(finder.aggressive).to match_array(@expected.map { |item| eql(item) })
end
end
end

View File

@@ -0,0 +1,45 @@
shared_examples 'App::Finders::WpItems::URLsInHomepage' do
before do
stub_request(:get, finder.target.url).to_return(body: File.read(File.join(fixtures, file)))
end
describe '#items_from_links' do
context 'when none found' do
let(:file) { 'none.html' }
it 'returns an empty array' do
expect(finder.items_from_links(type)).to eql([])
end
end
context 'when found' do
let(:file) { 'found.html' }
it 'returns the expected array' do
expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content')
expect(finder.items_from_links(type, uniq_links)).to eql expected_from_links
end
end
end
describe '#items_from_codes' do
before { expect(finder.target).to receive(:content_dir).at_least(1).and_return('wp-content') }
context 'when none found' do
let(:file) { 'none.html' }
it 'returns an empty array' do
expect(finder.items_from_codes(type)).to eql([])
end
end
context 'when found' do
let(:file) { 'found.html' }
it 'returns the expected array' do
expect(finder.items_from_codes(type, uniq_codes)).to eql expected_from_codes
end
end
end
end

View File

@@ -0,0 +1,48 @@
shared_examples WPScan::References do
describe '#references_keys' do
it 'contains the :wpvulndb symbol' do
expect(subject.class.references_keys)
.to include(:wpvulndb)
end
end
describe 'references' do
context 'when no references' do
its(:wpvulndb_ids) { should eql([]) }
its(:wpvulndb_urls) { should eql([]) }
its(:references_urls) { should eql([]) }
end
context 'when an unknown reference key is provided' do
let(:references) { { cve: 1, unknown: 12 } }
its(:references) { should eql(cve: %w[1]) }
end
context 'when references provided as string' do
let(:references) do
{
cve: 11,
wpvulndb: 12
}
end
its(:cves) { should eql %w[11] }
its(:cve_urls) { should eql %w[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-11] }
its(:wpvulndb_ids) { should eql %w[12] }
its(:wpvulndb_urls) { should eql %w[https://wpvulndb.com/vulnerabilities/12] }
its(:references_urls) do
should eql [
'https://wpvulndb.com/vulnerabilities/12',
'https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-11'
]
end
end
context 'when references provided as array' do
xit
end
end
end

View File

@@ -0,0 +1,41 @@
require_relative 'wordpress/custom_directories'
shared_examples WPScan::Target::Platform::WordPress do
it_behaves_like 'WordPress::CustomDirectories'
let(:fixtures) { File.join(FIXTURES, 'target', 'platform', 'wordpress') }
describe '#wordpress?' do
let(:fixtures) { File.join(super(), 'detection') }
before do
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, "#{body}.html")))
end
%w[default wp_includes only_scripts meta_generator comments mu_plugins].each do |file|
context "when a wordpress page (#{file}.html)" do
let(:body) { file }
its(:wordpress?) { should be true }
end
end
%w[not_wp].each do |file|
context "when not a wordpress page (#{file}.html)" do
let(:body) { file }
its(:wordpress?) { should be false }
end
end
end
describe '#wordpress_hosted?' do
its(:wordpress_hosted?) { should be false }
context 'when the target host matches' do
let(:url) { 'http://ex.wordpress.com' }
its(:wordpress_hosted?) { should be true }
end
end
end

View File

@@ -0,0 +1,177 @@
shared_examples 'WordPress::CustomDirectories' do
let(:fixtures) { File.join(super(), 'custom_directories') }
describe '#content_dir' do
{
default: 'wp-content', https: 'wp-content', custom_w_spaces: 'custom content spaces',
relative_one: 'wp-content', relative_two: 'wp-content', cache: 'wp-content'
}.each do |file, expected|
it "returns #{expected} for #{file}.html" do
fixture = File.join(fixtures, "#{file}.html")
stub_request(:get, target.url).to_return(body: File.read(fixture))
expect(target.content_dir).to eql expected
end
end
end
describe '#content_dir=, #plugins_dir=' do
['wp-content', 'wp-custom'].each do |dir|
context "when content_dir = #{dir} and no plugins_dir" do
before { target.content_dir = dir }
its(:content_dir) { should eq dir.chomp('/') }
its(:plugins_dir) { should eq dir.chomp('/') + '/plugins' }
end
context "when content_dir = #{dir} and plugins_dir = #{dir}" do
before do
target.content_dir = dir
target.plugins_dir = dir
end
its(:content_dir) { should eq dir.chomp('/') }
its(:plugins_dir) { should eq dir.chomp('/') }
end
end
end
describe '#content_uri, #content_url, #plugins_uri, #plugins_url' do
before { target.content_dir = 'wp-content' }
its(:content_uri) { should eq Addressable::URI.parse("#{url}/wp-content/") }
its(:content_url) { should eq "#{url}/wp-content/" }
its(:plugins_uri) { should eq Addressable::URI.parse("#{url}/wp-content/plugins/") }
its(:plugins_url) { should eq "#{url}/wp-content/plugins/" }
end
describe '#sub_dir' do
{ default: false, with_sub_dir: 'wp' }.each do |file, expected|
it "returns #{expected} for #{file}.html" do
fixture = File.join(fixtures, "#{file}.html")
stub_request(:get, target.url).to_return(body: File.read(fixture))
expect(target.sub_dir).to eql expected
end
end
end
describe '#url' do
after { expect(target.url(@path)).to eql @expected }
context 'when no path supplied' do
it 'returns the target url' do
@path = nil
@expected = "#{url}/"
end
end
context 'when no sub_dir' do
it 'does not add it' do
expect(target).to receive(:sub_dir).and_return(false)
@path = 'something'
@expected = "#{url}/#{@path}"
end
end
context 'when sub_dir' do
it 'adds it to the path' do
expect(target).to receive(:sub_dir).at_least(1).and_return('wp')
@path = 'path'
@expected = "#{url}/wp/path"
end
context 'when the path starts with /' do
it 'does not add it' do
@path = '/root'
@expected = "#{url}/root"
end
end
end
context 'when default directories' do
before { target.content_dir = 'wp-content' }
it 'does not replace the wp-content' do
@path = 'wp-content/themes/something'
@expected = "#{url}/#{@path}"
end
end
context 'when custom directories' do
# Ensures non custom wp dir path are not replaced
after do
expect(target).to receive(:sub_dir).at_least(1).and_return(false)
expect(target.url('not-wp-dir/spec.html')).to eql "#{url}/not-wp-dir/spec.html"
end
context 'when custom plugins dir' do
before do
target.content_dir = 'wp-content'
target.plugins_dir = 'custom-plugins'
end
it 'replaces wp-content/plugins' do
@path = 'wp-content/plugins/p1/file.txt'
@expected = "#{url}/custom-plugins/p1/file.txt"
end
it 'does not replace wp-content' do
@path = 'wp-content/themes/t1'
@expected = "#{url}/wp-content/themes/t1"
end
end
context 'when custom content dir' do
before { target.content_dir = 'custom-content' }
it 'replaces wp-content' do
@path = 'wp-content/plugins/p1'
@expected = "#{url}/custom-content/plugins/p1"
end
end
# Special case when for example, custom directories are
# supplied by the user: the plugin dir can the default one,
# but the content dir could be a custom (very rare case)
context 'when custom content and default plugins directories' do
before do
target.content_dir = 'custom-content'
target.plugins_dir = 'wp-content/plugins'
end
it 'does not replace wp-content/plugins ' do
@path = 'wp-content/plugins/p1/spec.html'
@expected = "#{url}/#{@path}"
end
it 'replaces wp-content' do
@path = 'wp-content/themes/t1'
@expected = "#{url}/custom-content/themes/t1"
end
end
context 'when custom content and plugins directories' do
before do
target.content_dir = 'custom-content'
target.plugins_dir = 'custom-plugins'
end
it 'replaces wp-content/plugins' do
@path = 'wp-content/plugins/p1/file.txt'
@expected = "#{url}/custom-plugins/p1/file.txt"
end
it 'replaces wp-content' do
@path = 'wp-content/themes/t1'
@expected = "#{url}/custom-content/themes/t1"
end
end
end
end
end

View File

@@ -0,0 +1,20 @@
require_relative 'enumeration/users'
require_relative 'enumeration/medias'
require_relative 'enumeration/themes'
require_relative 'enumeration/plugins'
require_relative 'enumeration/timthumbs'
require_relative 'enumeration/config_backups'
require_relative 'enumeration/db_exports'
shared_examples 'App::Views::Enumeration' do
let(:controller) { WPScan::Controller::Enumeration.new }
let(:tpl_vars) { { url: target_url } }
it_behaves_like 'App::Views::Enumeration::Users'
it_behaves_like 'App::Views::Enumeration::Medias'
it_behaves_like 'App::Views::Enumeration::Themes'
it_behaves_like 'App::Views::Enumeration::Plugins'
it_behaves_like 'App::Views::Enumeration::Timthumbs'
it_behaves_like 'App::Views::Enumeration::ConfigBackups'
it_behaves_like 'App::Views::Enumeration::DbExports'
end

View File

@@ -0,0 +1,18 @@
shared_examples 'App::Views::Enumeration::ConfigBackups' do
let(:view) { 'config_backups' }
let(:config_backup) { WPScan::ConfigBackup }
describe 'config_backups' do
context 'when no backups found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(config_backups: [])
end
end
context 'when backups found' do
xit
end
end
end

View File

@@ -0,0 +1,18 @@
shared_examples 'App::Views::Enumeration::DbExports' do
let(:view) { 'db_exports' }
let(:db_export) { WPScan::DbExport }
describe 'db_exports' do
context 'when no file found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(db_exports: [])
end
end
context 'when files found' do
xit
end
end
end

View File

@@ -0,0 +1,25 @@
shared_examples 'App::Views::Enumeration::Medias' do
let(:view) { 'medias' }
let(:media) { WPScan::Media }
describe 'medias' do
context 'when no medias found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(medias: [])
end
end
context 'when medias found' do
let(:m1) { media.new(target_url + '?attachment_id=1', found_by: 'Attachment Brute Forcing') }
let(:m2) { media.new(target_url + '?attachment_id=5', found_by: 'Attachment Brute Forcing') }
let(:medias) { [m1, m2] }
let(:expected_view) { File.join(view, 'medias') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(medias: medias)
end
end
end
end

View File

@@ -0,0 +1,18 @@
shared_examples 'App::Views::Enumeration::Plugins' do
let(:view) { 'plugins' }
let(:plugin) { WPScan::Plugin }
describe 'plugins' do
context 'when no plugins found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(plugins: [])
end
end
context 'when plugins found' do
xit
end
end
end

View File

@@ -0,0 +1,18 @@
shared_examples 'App::Views::Enumeration::Themes' do
let(:view) { 'themes' }
let(:plugin) { WPScan::Theme }
describe 'themes' do
context 'when no themes found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(themes: [])
end
end
context 'when themes found' do
xit
end
end
end

View File

@@ -0,0 +1,43 @@
shared_examples 'App::Views::Enumeration::Timthumbs' do
let(:view) { 'timthumbs' }
let(:timthumb) { WPScan::Timthumb }
let(:version) { WPScan::Version.new('2.8.14', found_by: 'Bad Request') }
describe 'timthumbs' do
context 'when no timthumbs found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(timthumbs: [])
end
end
context 'when timthumbs found' do
let(:tt) { timthumb.new(target_url + 'tt.php', found_by: 'Known Locations') }
let(:tt2) { timthumb.new(target_url + 'tt2.php', found_by: 'Known Locations') }
let(:timthumbs) { [tt, tt2] }
context 'when not vulnerable' do
let(:expected_view) { File.join(view, 'no_vulns') }
it 'outputs the expected string' do
expect(timthumbs[0]).to receive(:version).at_least(1).and_return(version)
expect(timthumbs[1]).to receive(:version).at_least(1).and_return(version)
@tpl_vars = tpl_vars.merge(timthumbs: timthumbs)
end
end
context 'when vulnerable' do
let(:expected_view) { File.join(view, 'with_vulns') }
it 'outputs the expected string' do
expect(timthumbs[0]).to receive(:version).at_least(1).and_return(false)
expect(timthumbs[1]).to receive(:version).at_least(1).and_return(version)
@tpl_vars = tpl_vars.merge(timthumbs: timthumbs)
end
end
end
end
end

View File

@@ -0,0 +1,21 @@
shared_examples 'App::Views::Enumeration::Users' do
let(:view) { 'users' }
let(:user) { CMSScanner::User }
describe 'users' do
context 'when no users found' do
let(:expected_view) { File.join(view, 'none_found') }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(users: [])
end
end
context 'when users found' do
let(:expected_view) { File.join(view, 'users') }
xit 'outputs the expected string' do
end
end
end
end

View File

@@ -0,0 +1,57 @@
shared_examples 'App::Views::MainTheme' do
let(:controller) { WPScan::Controller::MainTheme.new }
let(:tpl_vars) { { url: target_url } }
let(:theme) { WPScan::Theme.new(theme_name, target, found_by: 'rspec') }
describe 'main_theme' do
let(:view) { 'theme' }
context 'when no theme found' do
let(:expected_view) { 'not_found' }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(theme: nil)
end
end
context 'when a theme found' do
let(:theme_name) { 'test' }
before do
expect(target).to receive(:content_dir).at_least(1).and_return('wp-content')
stub_request(:get, /.*/)
stub_request(:get, /.*\.css\z/)
.to_return(body: File.read(File.join(FIXTURES, 'models', 'theme', 'style.css')))
end
context 'when no verbose' do
let(:expected_view) { 'no_verbose' }
it 'outputs the expected string' do
expect(theme).to receive(:version).at_least(1)
@tpl_vars = tpl_vars.merge(theme: theme)
end
end
context 'when verbose' do
let(:expected_view) { 'verbose' }
it 'outputs the expected string' do
expect(theme).to receive(:version).at_least(1).and_return(WPScan::Version.new('3.2', found_by: 'style'))
@tpl_vars = tpl_vars.merge(theme: theme, verbose: true)
end
end
context 'when vulnerable' do
let(:expected_view) { 'vulnerable' }
let(:theme_name) { 'dignitas-themes' }
it 'outputs the expected string' do
expect(theme).to receive(:version).at_least(1)
@tpl_vars = tpl_vars.merge(theme: theme, verbose: true)
end
end
end
end
end

View File

@@ -0,0 +1,84 @@
shared_examples 'App::Views::WpVersion' do
let(:controller) { WPScan::Controller::WpVersion.new }
let(:tpl_vars) { { url: target_url } }
describe 'version' do
let(:view) { 'version' }
context 'when the version is nil' do
let(:expected_view) { 'not_found' }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(version: nil)
end
end
context 'when the version is not nil' do
let(:version) { WPScan::WpVersion.new('4.0', found_by: 'rspec') }
context 'when confirmed_by is empty' do
context 'when no interesting_entries' do
let(:expected_view) { 'not_confirmed_no_entries' }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(version: version)
end
end
context 'when interesting_entries' do
let(:expected_view) { 'not_confirmed_entries' }
it 'outputs the expected string' do
version.interesting_entries << 'IE1' << 'IE2'
@tpl_vars = tpl_vars.merge(version: version)
end
end
end
context 'when confirmed_by is not empty' do
let(:confirmed_1) do
v = version.dup
v.found_by = 'Confirmed 1'
v.interesting_entries << 'IE1'
v
end
let(:confirmed_2) do
v = version.dup
v.found_by = 'Confirmed 2'
v.interesting_entries << 'IE1' << 'IE2'
v
end
context 'when one confirmed_by' do
let(:expected_view) { 'confirmed_one' }
it 'outputs the expected string' do
f = WPScan::Finders::Findings.new << version << confirmed_1
@tpl_vars = tpl_vars.merge(version: f.first)
end
end
context 'when multiple confirmed_by' do
let(:expected_view) { 'confirmed_multiples' }
it 'outputs the expected string' do
f = WPScan::Finders::Findings.new << version << confirmed_1 << confirmed_2
@tpl_vars = tpl_vars.merge(version: f.first)
end
end
end
end
context 'when the version is vulnerable' do
let(:expected_view) { 'with_vulns' }
it 'outputs the expected string' do
@tpl_vars = tpl_vars.merge(version: WPScan::WpVersion.new('3.8.1', found_by: 'rspec'))
end
end
end
end