This commit is contained in:
erwanlr
2019-02-10 15:32:30 +00:00
parent eb75d38716
commit 1780399050
6 changed files with 148 additions and 20 deletions

View File

@@ -71,7 +71,7 @@ module WPScan
exit(WPScan::ExitCode::VULNERABLE)
end
raise NotWordPressError unless target.wordpress? || parsed_options[:force]
raise NotWordPressError unless target.wordpress?(parsed_options[:detection_mode]) || parsed_options[:force]
end
# Loads the related server module in the target

View File

@@ -18,10 +18,10 @@ module WPScan
alias registration_enabled? registration_enabled
alias mu_plugins? mu_plugins
# @param [ Symbol ] detection_mode
#
# @return [ Boolean ]
def wordpress?
# res = Browser.get(url)
def wordpress?(detection_mode)
in_scope_urls(homepage_res) do |url|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
end
@@ -32,6 +32,14 @@ module WPScan
return true unless comments_from_page(/wordpress/i, homepage_res).empty?
if %i[mixed aggressive].include?(detection_mode)
%w[wp-admin/install.php wp-login.php].each do |path|
in_scope_urls(Browser.get_and_follow_location(url(path))).each do |url|
return true if Addressable::URI.parse(url).path.match(WORDPRESS_PATTERN)
end
end
end
false
end

View File

@@ -165,7 +165,7 @@ describe WPScan::Controller::Core do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).and_return(true)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
it 'calls the formatter when started and finished to update the db' do
@@ -208,7 +208,7 @@ describe WPScan::Controller::Core do
context 'when wordpress' do
it 'does not raise an error' do
expect(core.target).to receive(:wordpress?).and_return(true)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
expect { core.before_scan }.to_not raise_error
end
@@ -216,7 +216,7 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
it 'raises an error' do
expect(core.target).to receive(:wordpress?).and_return(false)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
expect { core.before_scan }.to raise_error(WPScan::NotWordPressError)
end
@@ -237,7 +237,7 @@ describe WPScan::Controller::Core do
context 'when wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).and_return(true)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(true)
end
it 'does not raise any error' do
@@ -248,7 +248,7 @@ describe WPScan::Controller::Core do
context 'when not wordpress' do
before do
expect(core).to receive(:load_server_module)
expect(core.target).to receive(:wordpress?).and_return(false)
expect(core.target).to receive(:wordpress?).with(:mixed).and_return(false)
end
context 'when no --force' do

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="noindex,nofollow" />
<title>WordPress &rsaquo; Installation</title>
<link rel='stylesheet' id='buttons-css' href='https://ex.lo/wp-includes/css/buttons.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='install-css' href='https://ex.lo/wp-admin/css/install.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='dashicons-css' href='https://ex.lo/wp-includes/css/dashicons.min.css?ver=5.0.3' type='text/css' media='all' />
</head>
<body class="wp-core-ui">
<p id="logo"><a href="https://wordpress.org/" tabindex="-1">WordPress</a></p>
<h1>Already Installed</h1><p>You appear to have already installed WordPress. To reinstall please clear your old database tables first.</p><p class="step"><a href="https://ex.lo/wp-login.php" class="button button-large">Log In</a></p></body></html>

View File

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<!--[if IE 8]>
<html xmlns="http://www.w3.org/1999/xhtml" class="ie8" lang="en-US">
<![endif]-->
<!--[if !(IE 8) ]><!-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
<!--<![endif]-->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Log In WP Lab</title>
<link rel='dns-prefetch' href='//s.w.org' />
<link rel='stylesheet' id='dashicons-css' href='https://ex.lo/wp-includes/css/dashicons.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='buttons-css' href='https://ex.lo/wp-includes/css/buttons.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='forms-css' href='https://ex.lo/wp-admin/css/forms.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='l10n-css' href='https://ex.lo/wp-admin/css/l10n.min.css?ver=5.0.3' type='text/css' media='all' />
<link rel='stylesheet' id='login-css' href='https://ex.lo/wp-admin/css/login.min.css?ver=5.0.3' type='text/css' media='all' />
<meta name='robots' content='noindex,noarchive' />
<meta name='referrer' content='strict-origin-when-cross-origin' />
<meta name="viewport" content="width=device-width" />
</head>
<body class="login login-action-login wp-core-ui locale-en-us">
<div id="login">
<h1><a href="https://ex.lo/" title="WP Lab" tabindex="-1">WP Lab</a></h1>
<form name="loginform" id="loginform" action="https://ex.lo/wp-login.php" method="post">
<p>
<label for="user_login">Username or Email Address<br />
<input type="text" name="log" id="user_login" class="input" value="" size="20" /></label>
</p>
<p>
<label for="user_pass">Password<br />
<input type="password" name="pwd" id="user_pass" class="input" value="" size="20" /></label>
</p>
<p class="forgetmenot"><label for="rememberme"><input name="rememberme" type="checkbox" id="rememberme" value="forever" /> Remember Me</label></p>
<p class="submit">
<input type="submit" name="wp-submit" id="wp-submit" class="button button-primary button-large" value="Log In" />
<input type="hidden" name="redirect_to" value="https://ex.lo/wp-admin/" />
<input type="hidden" name="testcookie" value="1" />
</p>
</form>
<p id="nav">
<a href="https://ex.lo/wp-login.php?action=lostpassword">Lost your password?</a>
</p>
<script type="text/javascript">
function wp_attempt_focus(){
setTimeout( function(){ try{
d = document.getElementById('user_login');
d.focus();
d.select();
} catch(e){}
}, 200);
}
wp_attempt_focus();
if(typeof wpOnload=='function')wpOnload();
</script>
<p id="backtoblog"><a href="https://ex.lo/">&larr; Back to WP Lab</a></p>
</div>
<div class="clear"></div>
</body>
</html>

View File

@@ -3,28 +3,65 @@ 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') }
let(:fixtures) { FIXTURES.join('target', 'platform', 'wordpress') }
describe '#wordpress?' do
let(:fixtures) { File.join(super(), 'detection') }
let(:fixtures) { super().join('detection') }
before do
stub_request(:get, target.url).to_return(body: File.read(File.join(fixtures, "#{body}.html")))
stub_request(:get, target.url).to_return(body: File.read(fixtures.join("#{homepage}.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 }
context 'when pattern/s in the homepage' do
%w[default wp_includes only_scripts meta_generator comments mu_plugins].each do |file|
context "when a wordpress page (#{file}.html)" do
let(:homepage) { file }
its(:wordpress?) { should be true }
it 'returns true' do
expect(subject.wordpress?(:mixed)).to be true
end
end
end
end
%w[not_wp].each do |file|
context "when not a wordpress page (#{file}.html)" do
let(:body) { file }
context 'when no clues in the homepage' do
let(:homepage) { 'not_wp' }
its(:wordpress?) { should be false }
context 'when only passive detection mode' do
it 'returns false' do
expect(subject.wordpress?(:passive)).to be false
end
end
context 'when mixed or aggressive detection modes' do
context 'when wp-admin/install.php and wp-login.php not there' do
it 'returns false' do
%w[wp-admin/install.php wp-login.php].each do |path|
stub_request(:get, target.url(path)).to_return(status: 404)
end
expect(subject.wordpress?(:mixed)).to be false
end
end
context 'when wp-admin/install.php is matching a WP install' do
it 'returns true' do
stub_request(:get, target.url('wp-admin/install.php'))
.to_return(body: File.read(fixtures.join('wp-admin-install.php')))
expect(subject.wordpress?(:mixed)).to be true
end
end
context 'when wp-admin/install.php not there but wp-login.php is matching a WP install' do
it 'returns true' do
stub_request(:get, target.url('wp-admin/install.php')).to_return(status: 404)
stub_request(:get, target.url('wp-login.php'))
.to_return(body: File.read(fixtures.join('wp-login.php')))
expect(subject.wordpress?(:mixed)).to be true
end
end
end
end
end