Checks for wp-content directly (depends on detection-mode) when not identified passively
This commit is contained in:
@@ -16,7 +16,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
|
return if target.content_dir(ParsedCli.detection_mode)
|
||||||
|
|
||||||
raise Error::WpContentDirNotDetected
|
raise Error::WpContentDirNotDetected
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ 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
|
def content_dir(detection_mode = :mixed)
|
||||||
unless @content_dir
|
unless @content_dir
|
||||||
escaped_url = Regexp.escape(url).gsub(/https?/i, 'https?')
|
escaped_url = Regexp.escape(url).gsub(/https?/i, 'https?')
|
||||||
pattern = %r{#{escaped_url}([\w\s\-\/]+)\/(?:themes|plugins|uploads|cache)\/}i
|
pattern = %r{#{escaped_url}([\w\s\-\/]+)\/(?:themes|plugins|uploads|cache)\/}i
|
||||||
@@ -26,11 +27,21 @@ module WPScan
|
|||||||
xpath_pattern_from_page('//script[not(@src)]', pattern, homepage_res) do |match|
|
xpath_pattern_from_page('//script[not(@src)]', pattern, homepage_res) do |match|
|
||||||
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?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@content_dir
|
@content_dir
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def default_content_dir_exists?
|
||||||
|
# url('wp-content') can't be used here as the folder has not yet been identified
|
||||||
|
# and the method would try to replace it by nil which would raise an error
|
||||||
|
[200, 401, 403].include?(Browser.forge_request(uri.join('wp-content/').to_s, head_or_get_params).run.code)
|
||||||
|
end
|
||||||
|
|
||||||
# @return [ Addressable::URI ]
|
# @return [ Addressable::URI ]
|
||||||
def content_uri
|
def content_uri
|
||||||
uri.join("#{content_dir}/")
|
uri.join("#{content_dir}/")
|
||||||
|
|||||||
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
# Version
|
# Version
|
||||||
module WPScan
|
module WPScan
|
||||||
VERSION = '3.5.2'
|
VERSION = '3.5.3'
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ describe WPScan::Controller::CustomDirectories do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#before_scan' do
|
describe '#before_scan' do
|
||||||
context 'when the content_dir is not found and not supply' do
|
context 'when the content_dir is not found and not supplied' do
|
||||||
before { expect(controller.target).to receive(:content_dir) }
|
before { expect(controller.target).to receive(:content_dir).with(:mixed) }
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@@ -15,6 +15,61 @@ shared_examples 'WordPress::CustomDirectories' do
|
|||||||
expect(target.content_dir).to eql expected
|
expect(target.content_dir).to eql expected
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when not found via the homepage' do
|
||||||
|
before { stub_request(:get, target.url).to_return(body: '') }
|
||||||
|
|
||||||
|
context 'when detection mode is passive' do
|
||||||
|
it 'returns nil' do
|
||||||
|
expect(target).not_to receive(:default_content_dir_exist?)
|
||||||
|
|
||||||
|
expect(target.content_dir(:passive)).to eql nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when detection mode is mixed or aggressive' do
|
||||||
|
before { expect(target).to receive(:default_content_dir_exists?).and_return(dir_exist) }
|
||||||
|
|
||||||
|
%i[mixed aggressive].each do |mode|
|
||||||
|
context 'when default content dir exists' do
|
||||||
|
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
|
||||||
|
|
||||||
|
describe 'default_content_dir_exists?' do
|
||||||
|
before do
|
||||||
|
expect(target).to receive(:head_or_get_params).and_return(method: :head)
|
||||||
|
stub_request(:head, target.uri.join('wp-content/').to_s).to_return(status: status)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when 404' do
|
||||||
|
let(:status) { 404 }
|
||||||
|
|
||||||
|
its(:default_content_dir_exists?) { should be false }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when 200, 401 or 403' do
|
||||||
|
[200, 401, 403].each do |code|
|
||||||
|
let(:status) { code }
|
||||||
|
|
||||||
|
its(:default_content_dir_exists?) { should be true }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#content_dir=, #plugins_dir=' do
|
describe '#content_dir=, #plugins_dir=' do
|
||||||
|
|||||||
Reference in New Issue
Block a user