diff --git a/app/finders/interesting_findings/mu_plugins.rb b/app/finders/interesting_findings/mu_plugins.rb index 4e32a946..88892b6e 100644 --- a/app/finders/interesting_findings/mu_plugins.rb +++ b/app/finders/interesting_findings/mu_plugins.rb @@ -9,7 +9,7 @@ module WPScan def passive(_opts = {}) pattern = %r{#{target.content_dir}/mu\-plugins/}i - target.in_scope_uris(target.homepage_res) do |uri| + target.in_scope_uris(target.homepage_res, '(//@href|//@src)[contains(., "mu-plugins")]') do |uri| next unless uri.path&.match?(pattern) url = target.url('wp-content/mu-plugins/') diff --git a/app/finders/main_theme/css_style_in_homepage.rb b/app/finders/main_theme/css_style_in_homepage.rb index 34bb8619..ed0eab7f 100644 --- a/app/finders/main_theme/css_style_in_homepage.rb +++ b/app/finders/main_theme/css_style_in_homepage.rb @@ -20,7 +20,7 @@ module WPScan end def passive_from_css_href(res, opts) - target.in_scope_uris(res, '//style/@src|//link/@href') do |uri| + target.in_scope_uris(res, '//link/@href[contains(., "style.css")]') do |uri| next unless uri.path =~ %r{/themes/([^\/]+)/style.css\z}i return create_theme(Regexp.last_match[1], uri.to_s, opts) diff --git a/app/finders/users/author_id_brute_forcing.rb b/app/finders/users/author_id_brute_forcing.rb index d7d1ca3b..ee70ac4b 100644 --- a/app/finders/users/author_id_brute_forcing.rb +++ b/app/finders/users/author_id_brute_forcing.rb @@ -71,11 +71,13 @@ module WPScan return username, 'Display Name', 50 if username end - # @param [ String ] url + # @param [ String, Addressable::URI ] uri # # @return [ String, nil ] - def username_from_author_url(url) - url[%r{/author/([^/\b]+)/?}i, 1] + def username_from_author_url(uri) + uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI) + + uri.path[%r{/author/([^/\b]+)/?}i, 1] end # @param [ Typhoeus::Response ] res @@ -83,12 +85,12 @@ module WPScan # @return [ String, nil ] The username found def username_from_response(res) # Permalink enabled - target.in_scope_uris(res, '//link/@href|//a/@href') do |uri| - username = username_from_author_url(uri.to_s) + target.in_scope_uris(res, '//@href[contains(., "author/")]') do |uri| + username = username_from_author_url(uri) return username if username end - # No permalink + # No permalink, TODO Maybe use xpath to extract the classes ? res.body[/
] The plugins/themes detected in the href, src attributes of the homepage + # @return [ Array
" }.join("\n")
+ end
+
+ it 'should not take a while to process the page' do
+ time_start = Time.now
+ result = finder.passive
+ time_end = Time.now
+
+ expect(result).to be nil
+ expect(time_end - time_start).to be < 1
+ end
+ end
+
+ context 'when uris' do
+ let(:body) { File.read(fixtures.join(fixture)) }
+
+ context 'when none matching' do
+ let(:fixture) { 'no_match.html' }
+
+ its(:passive) { should be nil }
+ end
+
+ context 'when matching via href' do
+ let(:fixture) { 'match_href.html' }
+
+ its(:passive) { should be_a WPScan::Model::MuPlugins }
+ end
+
+ context 'when matching from src' do
+ let(:fixture) { 'match_src.html' }
+
+ its(:passive) { should be_a WPScan::Model::MuPlugins }
+ end
+ end
end
describe '#aggressive' do
diff --git a/spec/app/finders/users/author_id_brute_forcing_spec.rb b/spec/app/finders/users/author_id_brute_forcing_spec.rb
index 517b7dcf..a9b4c311 100644
--- a/spec/app/finders/users/author_id_brute_forcing_spec.rb
+++ b/spec/app/finders/users/author_id_brute_forcing_spec.rb
@@ -19,7 +19,7 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
end
end
- describe '#potential_username' do
+ describe '#username_from_response' do
[
'4.1.1', '4.1.1-permalink',
'3.0', '3.0-permalink',
@@ -32,6 +32,19 @@ describe WPScan::Finders::Users::AuthorIdBruteForcing do
expect(finder.username_from_response(res)).to eql 'admin'
end
end
+
+ context 'when a lot of unrelated links' do
+ it 'should not take a while to process the page' do
+ body = Array.new(300) { |i| "Some Link" }.join("\n")
+ body << 'Link'
+
+ time_start = Time.now
+ expect(finder.username_from_response(Typhoeus::Response.new(body: body))).to eql 'test'
+ time_end = Time.now
+
+ expect(time_end - time_start).to be < 1
+ end
+ end
end
describe '#display_name_from_body' do
diff --git a/spec/app/finders/users/author_posts_spec.rb b/spec/app/finders/users/author_posts_spec.rb
index 4bca4e3f..ea5d5b3b 100644
--- a/spec/app/finders/users/author_posts_spec.rb
+++ b/spec/app/finders/users/author_posts_spec.rb
@@ -16,12 +16,31 @@ describe WPScan::Finders::Users::AuthorPosts do
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]
- ])
+ expect(results).to eql [
+ ['admin', 'Author Pattern', 100],
+ ['admin display_name', 'Display Name', 30],
+ ['editor', 'Author Pattern', 100],
+ ['editor', 'Display Name', 30]
+ ]
+ end
+
+ context 'when a lot of unrelated uris' do
+ it 'should not take a while to process the page' do
+ body = Array.new(300) { |i| "Some Link" }.join("\n")
+ body << "Other Link"
+ body << "user display name"
+
+ time_start = Time.now
+ results = finder.potential_usernames(Typhoeus::Response.new(body: body))
+ time_end = Time.now
+
+ expect(results).to eql [
+ ['admin', 'Author Pattern', 100],
+ ['user display name', 'Display Name', 30]
+ ]
+
+ expect(time_end - time_start).to be < 1
+ end
end
end
end
diff --git a/spec/cache/.gitignore b/spec/cache/.gitignore
index 86d0cb27..5e7d2734 100644
--- a/spec/cache/.gitignore
+++ b/spec/cache/.gitignore
@@ -1,4 +1,4 @@
# Ignore everything in this directory
*
# Except this file
-!.gitignore
\ No newline at end of file
+!.gitignore
diff --git a/spec/fixtures/finders/interesting_findings/mu_plugins/match_href.html b/spec/fixtures/finders/interesting_findings/mu_plugins/match_href.html
new file mode 100644
index 00000000..a5506aa8
--- /dev/null
+++ b/spec/fixtures/finders/interesting_findings/mu_plugins/match_href.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
" }.join("\n")
+ end
+
+ it 'should not take a while to process the page' do
+ time_start = Time.now
+ expect(finder.items_from_links(type)).to eql []
+ time_end = Time.now
+
+ expect(time_end - time_start).to be < 1
+ 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' }
+ let(:fixture) { 'none.html' }
it 'returns an empty array' do
expect(finder.items_from_codes(type)).to eql([])
@@ -37,7 +49,7 @@ shared_examples 'App::Finders::WpItems::UrlsInPage' do
end
context 'when found' do
- let(:file) { 'found.html' }
+ let(:fixture) { 'found.html' }
it 'returns the expected array' do
expect(finder.items_from_codes(type, uniq_codes)).to eql expected_from_codes
diff --git a/spec/shared_examples/target/platform/wordpress.rb b/spec/shared_examples/target/platform/wordpress.rb
index 32432996..bcad262c 100644
--- a/spec/shared_examples/target/platform/wordpress.rb
+++ b/spec/shared_examples/target/platform/wordpress.rb
@@ -172,11 +172,19 @@ shared_examples WPScan::Target::Platform::WordPress do
context 'when wp-content not detected' do
before do
expect(target).to receive(:content_dir).and_return(nil)
- stub_request(:get, target.url).to_return(body: File.read(fixtures.join(fixture).to_s))
+
+ stub_request(:get, target.url)
+ .to_return(body: defined?(body) ? body : File.read(fixtures.join(fixture).to_s))
end
- context 'when an URL matches a WP hosted' do
- let(:fixture) { 'matches.html' }
+ context 'when an src URL matches a WP hosted' do
+ let(:fixture) { 'match_src.html' }
+
+ its(:wordpress_hosted?) { should be true }
+ end
+
+ context 'when an href URL matches a WP hosted' do
+ let(:fixture) { 'match_href.html' }
its(:wordpress_hosted?) { should be true }
end
@@ -186,6 +194,20 @@ shared_examples WPScan::Target::Platform::WordPress do
its(:wordpress_hosted?) { should be false }
end
+
+ context 'when a lof of unrelated urls' do
+ let(:body) do
+ Array.new(250) { |i| "Some Link
" }.join("\n")
+ end
+
+ it 'should not take a while to process the page' do
+ time_start = Time.now
+ expect(target.wordpress_hosted?).to be false
+ time_end = Time.now
+
+ expect(time_end - time_start).to be < 1
+ end
+ end
end
context 'when wp-content detected' do