This commit is contained in:
erwanlr
2019-07-04 15:45:01 +01:00
parent 1f627d5e49
commit aee9ffdb9c
2 changed files with 93 additions and 49 deletions

View File

@@ -77,9 +77,22 @@ module WPScan
end end
end end
# @return [ Boolean ]
def xmlrpc_get_users_blogs_enabled?
if xmlrpc&.enabled? &&
xmlrpc.available_methods.include?('wp.getUsersBlogs') &&
xmlrpc.method_call('wp.getUsersBlogs', [SecureRandom.hex[0, 6], SecureRandom.hex[0, 4]])
.run.body !~ /XML\-RPC services are disabled/
true
else
false
end
end
# @return [ CMSScanner::Finders::Finder ] # @return [ CMSScanner::Finders::Finder ]
def attacker_from_automatic_detection def attacker_from_automatic_detection
if xmlrpc&.enabled? && xmlrpc.available_methods.include?('wp.getUsersBlogs') if xmlrpc_get_users_blogs_enabled?
wp_version = target.wp_version wp_version = target.wp_version
if wp_version && wp_version < '4.4' if wp_version && wp_version < '4.4'

View File

@@ -52,6 +52,60 @@ describe WPScan::Controller::PasswordAttack do
end end
end end
describe '#xmlrpc_get_users_blogs_enabled?' do
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) }
context 'when xmlrpc not found' do
let(:xmlrpc) { nil }
its(:xmlrpc_get_users_blogs_enabled?) { should be false }
end
context 'when xmlrpc not enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php") }
it 'returns false' do
expect(xmlrpc).to receive(:enabled?).and_return(false)
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when xmlrpc enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php") }
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
context 'when wp.getUsersBlogs methods not listed' do
it 'returns false' do
expect(xmlrpc).to receive(:available_methods).and_return(%w[m1 m2])
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when wp.getUsersBlogs method listed' do
before { expect(xmlrpc).to receive(:available_methods).and_return(%w[wp.getUsersBlogs m2]) }
context 'when wp.getUsersBlogs method disabled' do
it 'returns false' do
stub_request(:post, xmlrpc.url).to_return(body: 'XML-RPC services are disabled on this site.')
expect(controller.xmlrpc_get_users_blogs_enabled?).to be false
end
end
context 'when wp.getUsersBlogs method enabled' do
it 'returns true' do
stub_request(:post, xmlrpc.url).to_return(body: 'Incorrect username or password.')
expect(controller.xmlrpc_get_users_blogs_enabled?).to be true
end
end
end
end
end
describe '#attacker' do describe '#attacker' do
context 'when --password-attack provided' do context 'when --password-attack provided' do
let(:cli_args) { "#{super()} --password-attack #{attack}" } let(:cli_args) { "#{super()} --password-attack #{attack}" }
@@ -92,7 +146,7 @@ describe WPScan::Controller::PasswordAttack do
before do before do
expect(controller.target) expect(controller.target)
.to receive(:xmlrpc) .to receive(:xmlrpc)
.and_return(WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php")) .and_return(WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php"))
end end
context 'when single xmlrpc' do context 'when single xmlrpc' do
@@ -117,73 +171,50 @@ describe WPScan::Controller::PasswordAttack do
end end
context 'when automatic detection' do context 'when automatic detection' do
before { expect(controller.target).to receive(:xmlrpc).and_return(xmlrpc) } context 'when xmlrpc_get_users_blogs_enabled? is false' do
context 'when xmlrpc not found' do
let(:xmlrpc) { nil }
it 'returns the WpLogin' do it 'returns the WpLogin' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin expect(controller).to receive(:xmlrpc_get_users_blogs_enabled?).and_return(false)
expect(controller.attacker.target).to be_a WPScan::Target
end
end
context 'when xmlrpc not enabled' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") }
it 'returns the WpLogin' do
expect(xmlrpc).to receive(:enabled?).and_return(false)
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin
expect(controller.attacker.target).to be_a WPScan::Target expect(controller.attacker.target).to be_a WPScan::Target
end end
end end
context 'when xmlrpc enabled' do context 'when xmlrpc_get_users_blogs_enabled? is true' do
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") } before do
expect(controller).to receive(:xmlrpc_get_users_blogs_enabled?).and_return(true)
before { expect(xmlrpc).to receive(:enabled?).and_return(true) } expect(controller.target)
.to receive(:xmlrpc).and_return(WPScan::Model::XMLRPC.new("#{target_url}xmlrpc.php"))
end
context 'when wp.getUsersBlogs methods not available' do context 'when WP version not found' do
it 'returns the WpLogin' do it 'returns the XMLRPC' do
expect(xmlrpc).to receive(:available_methods).and_return(%w[m1 m2]) expect(controller.target).to receive(:wp_version).and_return(false)
expect(controller.attacker).to be_a WPScan::Finders::Passwords::WpLogin expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Target expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end end
end end
context 'when wp.getUsersBlogs method evailable' do context 'when WP version found' do
before { expect(xmlrpc).to receive(:available_methods).and_return(%w[wp.getUsersBlogs m2]) } before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
context 'when WP version not found' do context 'when WP < 4.4' do
it 'returns the XMLRPC' do let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') }
expect(controller.target).to receive(:wp_version).and_return(false)
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC it 'returns the XMLRPCMulticall' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end end
end end
context 'when WP version found' do context 'when WP >= 4.4' do
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) } let(:wp_version) { WPScan::Model::WpVersion.new('4.4') }
context 'when WP < 4.4' do it 'returns the XMLRPC' do
let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') } expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
it 'returns the XMLRPCMulticall' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end
context 'when WP >= 4.4' do
let(:wp_version) { WPScan::Model::WpVersion.new('4.4') }
it 'returns the XMLRPC' do
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
end
end end
end end
end end