Checks default wp-content dir regardless of detection mode if not found passively

This commit is contained in:
erwanlr
2019-10-10 19:59:09 +01:00
parent d85035d5ef
commit e39a192e8d
7 changed files with 109 additions and 116 deletions

View File

@@ -18,7 +18,7 @@ module WPScan
target.content_dir = ParsedCli.wp_content_dir if ParsedCli.wp_content_dir target.content_dir = ParsedCli.wp_content_dir if ParsedCli.wp_content_dir
target.plugins_dir = ParsedCli.wp_plugins_dir if ParsedCli.wp_plugins_dir target.plugins_dir = ParsedCli.wp_plugins_dir if ParsedCli.wp_plugins_dir
return if target.content_dir(ParsedCli.detection_mode) return if target.content_dir
raise Error::WpContentDirNotDetected raise Error::WpContentDirNotDetected
end end

View File

@@ -90,7 +90,7 @@ module WPScan
def wordpress_hosted? def wordpress_hosted?
return true if /\.wordpress\.com$/i.match?(uri.host) return true if /\.wordpress\.com$/i.match?(uri.host)
unless content_dir(:passive) unless content_dir
pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze pattern = %r{https?://s\d\.wp\.com#{WORDPRESS_PATTERN}}i.freeze
uris_from_page(homepage_res) do |uri| uris_from_page(homepage_res) do |uri|

View File

@@ -13,9 +13,8 @@ module WPScan
@plugins_dir = dir.chomp('/') @plugins_dir = dir.chomp('/')
end end
# @param [ Symbol ] detection_mode
# @return [ String ] The wp-content directory # @return [ String ] The wp-content directory
def content_dir(detection_mode = :mixed) def content_dir
unless @content_dir unless @content_dir
# scope_url_pattern is from CMSScanner::Target # scope_url_pattern is from CMSScanner::Target
pattern = %r{#{scope_url_pattern}([\w\s\-/]+)\\?/(?:themes|plugins|uploads|cache)\\?/}i pattern = %r{#{scope_url_pattern}([\w\s\-/]+)\\?/(?:themes|plugins|uploads|cache)\\?/}i
@@ -29,9 +28,7 @@ module WPScan
return @content_dir = match[1] return @content_dir = match[1]
end end
unless detection_mode == :passive return @content_dir = 'wp-content' if default_content_dir_exists?
return @content_dir = 'wp-content' if default_content_dir_exists?
end
end end
@content_dir @content_dir

View File

@@ -166,6 +166,8 @@ describe WPScan::Controller::Core do
before do before do
expect(core).to receive(:load_server_module) expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true) expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect(core.target).to receive(:wordpress_hosted?).and_return(false)
# expect(core.target).to receive(:content_dir).and_return('wp-content')
end end
it 'calls the formatter when started and finished to update the db' do it 'calls the formatter when started and finished to update the db' do
@@ -174,56 +176,6 @@ describe WPScan::Controller::Core do
end end
end end
context 'when a redirect occurs' do
before do
stub_request(:any, target_url)
expect(core.target).to receive(:homepage_res)
.at_least(1)
.and_return(Typhoeus::Response.new(effective_url: redirection, body: ''))
end
context 'to the wp-admin/install.php' do
let(:redirection) { "#{target_url}wp-admin/install.php" }
it 'calls the formatter with the correct parameters and exit' do
expect(core.formatter).to receive(:output)
.with('not_fully_configured', hash_including(url: redirection), 'core').ordered
# TODO: Would be cool to be able to test the exit code
expect { core.before_scan }.to raise_error(SystemExit)
end
end
context 'to something else' do
let(:redirection) { 'http://g.com/' }
it 'raises an error' do
expect { core.before_scan }.to raise_error(CMSScanner::Error::HTTPRedirect)
end
end
context 'to another path with the wp-admin/install.php in the query' do
let(:redirection) { "#{target_url}index.php?a=/wp-admin/install.php" }
context 'when wordpress' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
end
end
end
context 'when hosted on wordpress.com' do context 'when hosted on wordpress.com' do
let(:target_url) { 'http://ex.wordpress.com' } let(:target_url) { 'http://ex.wordpress.com' }
@@ -234,52 +186,106 @@ describe WPScan::Controller::Core do
end end
end end
context 'when wordpress' do context 'when not hosted on wordpress.com' do
before do before { allow(core.target).to receive(:wordpress_hosted?).and_return(false) }
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
it 'does not raise any error' do context 'when a redirect occurs' do
expect { core.before_scan }.to_not raise_error before do
end stub_request(:any, target_url)
end
context 'when not wordpress' do expect(core.target).to receive(:homepage_res)
before do .at_least(1)
expect(core).to receive(:load_server_module) .and_return(Typhoeus::Response.new(effective_url: redirection, body: ''))
end end
context 'when no --force' do context 'to the wp-admin/install.php' do
before { expect(core.target).to receive(:maybe_add_cookies) } let(:redirection) { "#{target_url}wp-admin/install.php" }
context 'when no cookies added or still not wordpress after being added' do it 'calls the formatter with the correct parameters and exit' do
it 'raises an error' do expect(core.formatter).to receive(:output)
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false) .with('not_fully_configured', hash_including(url: redirection), 'core').ordered
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress) # TODO: Would be cool to be able to test the exit code
expect { core.before_scan }.to raise_error(SystemExit)
end end
end end
context 'when the added cookies solved it' do context 'to something else' do
it 'does not raise an error' do let(:redirection) { 'http://g.com/' }
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false).ordered
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true).ordered it 'raises an error' do
expect { core.before_scan }.to raise_error(CMSScanner::Error::HTTPRedirect)
end
end
context 'to another path with the wp-admin/install.php in the query' do
let(:redirection) { "#{target_url}index.php?a=/wp-admin/install.php" }
context 'when wordpress' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
end
end
end
context 'when wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
it 'does not raise any error' do
expect { core.before_scan }.to_not raise_error
end
end
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
end
context 'when no --force' do
before { expect(core.target).to receive(:maybe_add_cookies) }
context 'when no cookies added or still not wordpress after being added' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).twice.with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::Error::NotWordPress)
end
end
context 'when the added cookies solved it' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false).ordered
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true).ordered
expect { core.before_scan }.to_not raise_error
end
end
end
context 'when --force' do
let(:cli_args) { "#{super()} --force" }
it 'does not raise any error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect { core.before_scan }.to_not raise_error expect { core.before_scan }.to_not raise_error
end end
end end
end end
context 'when --force' do
let(:cli_args) { "#{super()} --force" }
it 'does not raise any error' do
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect { core.before_scan }.to_not raise_error
end
end
end end
end end
end end

View File

@@ -20,7 +20,7 @@ describe WPScan::Controller::CustomDirectories do
describe '#before_scan' do describe '#before_scan' do
context 'when the content_dir is not found and not supplied' do context 'when the content_dir is not found and not supplied' do
before { expect(controller.target).to receive(:content_dir).with(:mixed) } before { expect(controller.target).to receive(:content_dir).and_return(nil) }
it 'raises an exception' do it 'raises an exception' do
expect { controller.before_scan }.to raise_error(WPScan::Error::WpContentDirNotDetected) expect { controller.before_scan }.to raise_error(WPScan::Error::WpContentDirNotDetected)

View File

@@ -152,7 +152,7 @@ shared_examples WPScan::Target::Platform::WordPress do
context 'when wp-content not detected' do context 'when wp-content not detected' do
before do before do
expect(target).to receive(:content_dir).with(:passive).and_return(nil) 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: File.read(fixtures.join(fixture).to_s))
end end
@@ -170,7 +170,7 @@ shared_examples WPScan::Target::Platform::WordPress do
end end
context 'when wp-content detected' do context 'when wp-content detected' do
before { expect(target).to receive(:content_dir).with(:passive).and_return('wp-content') } before { expect(target).to receive(:content_dir).and_return('wp-content') }
its(:wordpress_hosted?) { should be false } its(:wordpress_hosted?) { should be false }
end end

View File

@@ -42,35 +42,25 @@ shared_examples 'WordPress::CustomDirectories' do
end end
context 'when not found via the homepage' do context 'when not found via the homepage' do
before { stub_request(:get, target.url).to_return(body: '') } before do
stub_request(:get, target.url).to_return(body: '')
expect(target).to receive(:default_content_dir_exists?).and_return(dir_exist)
end
context 'when default dir does not exist' do
let(:dir_exist) { false }
context 'when detection mode is passive' do
it 'returns nil' do it 'returns nil' do
expect(target).not_to receive(:default_content_dir_exist?) expect(target.content_dir).to eql nil
expect(target.content_dir(:passive)).to eql nil
end end
end end
context 'when detection mode is mixed or aggressive' do context 'when default dir exists' do
before { expect(target).to receive(:default_content_dir_exists?).and_return(dir_exist) } let(:dir_exist) { true }
%i[mixed aggressive].each do |mode| it 'returns wp-content' do
context 'when default content dir exists' do expect(target.content_dir).to eql 'wp-content'
let(:dir_exist) { true }
it 'returns wp-content' do
expect(target.content_dir(mode)).to eql 'wp-content'
end
end
context 'when default content dir does not exist' do
let(:dir_exist) { false }
it 'returns nil' do
expect(target.content_dir(mode)).to eql nil
end
end
end end
end end
end end