WpTarget modules reworked
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'BruteForce' do
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@target_url = @module.uri.to_s
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/bruteforce'
|
||||
@wordlist = @fixtures_dir + '/wordlist.txt'
|
||||
@username = 'admin'
|
||||
|
||||
@module.extend(BruteForce)
|
||||
Browser.instance.max_threads = 1
|
||||
end
|
||||
|
||||
describe '#lines_in_file' do
|
||||
it 'should return 6' do
|
||||
lines = BruteForce.lines_in_file(@wordlist)
|
||||
lines.should == 6
|
||||
end
|
||||
end
|
||||
|
||||
describe '#brute_force' do
|
||||
before :each do
|
||||
|
||||
end
|
||||
|
||||
it 'should get the correct password' do
|
||||
passwords = []
|
||||
File.open(@wordlist, 'r').each do |password|
|
||||
# ignore comments
|
||||
passwords << password.strip unless password.strip[0, 1] == '#'
|
||||
end
|
||||
# Last status must be 302 to get full code coverage
|
||||
passwords.each do |password|
|
||||
stub_request(:post, @module.login_url).
|
||||
to_return(
|
||||
{ status: 200, body: 'login_error' },
|
||||
{ status: 0, body: 'no reponse' },
|
||||
{ status: 500, body: 'server error' },
|
||||
{ status: 999, body: 'invalid' },
|
||||
{ status: 302, body: 'FOUND!' }
|
||||
)
|
||||
end
|
||||
|
||||
user = WpUser.new(@module.uri, login: 'admin')
|
||||
result = @module.brute_force([user], @wordlist)
|
||||
|
||||
result.length.should == 1
|
||||
result.should === [{ name: 'admin', password: 'root' }]
|
||||
end
|
||||
|
||||
it 'should cover the timeout branch and return an empty array' do
|
||||
stub_request(:post, @module.login_url).to_timeout
|
||||
|
||||
user = WpUser.new(@module.uri, login: 'admin')
|
||||
result = @module.brute_force([user], @wordlist)
|
||||
result.should == []
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,58 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'Malwares' do
|
||||
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@target_url = @module.uri.to_s
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/malwares'
|
||||
@malwares_file_path = @fixtures_dir + '/malwares.txt'
|
||||
|
||||
@module.extend(Malwares)
|
||||
end
|
||||
|
||||
describe '#malwares_file' do
|
||||
it "should return #{SPEC_FIXTURES_WPSCAN_MODULES_DIR}/wp_malwares.txt" do
|
||||
Malwares.malwares_file(@malwares_file_path).should === @malwares_file_path
|
||||
end
|
||||
end
|
||||
|
||||
describe '#malwares & #has_malwares' do
|
||||
after :each do
|
||||
if @fixture
|
||||
stub_request_to_fixture(url: @target_url, fixture: File.new(@fixture))
|
||||
end
|
||||
|
||||
malwares = @module.malwares(@malwares_file_path)
|
||||
|
||||
malwares.sort.should === @expected_malwares.sort
|
||||
@module.has_malwares?.should === (@expected_malwares.empty? ? false : true)
|
||||
end
|
||||
it 'should return an empty array on a 404' do
|
||||
stub_request(:get, @target_url).to_return(status: 404)
|
||||
|
||||
@expected_malwares = []
|
||||
end
|
||||
|
||||
it 'should return an array empty array if no infection found' do
|
||||
@fixture = @fixtures_dir + '/clean.html'
|
||||
@expected_malwares = []
|
||||
end
|
||||
|
||||
it 'should return an array with 1 malware url (.rr.nu check)' do
|
||||
@fixture = @fixtures_dir + '/single-infection.html'
|
||||
@expected_malwares = ['http://irstde24clined.rr.nu/mm.php?d=1']
|
||||
end
|
||||
|
||||
it 'should return an array with 1 malware url (iframe check)' do
|
||||
@fixture = @fixtures_dir + '/single-iframe-infection.html'
|
||||
@expected_malwares = ['http://www.thesea.org/media.php']
|
||||
end
|
||||
|
||||
it 'should return an array with 3 malwares url' do
|
||||
@fixture = @fixtures_dir + '/multiple-infections.html'
|
||||
@expected_malwares = ['http://irstde24clined.rr.nu/mm.php?d=1', 'http://atio79srem.rr.nu/pmg.php?dr=1', 'http://www.thesea.org/media.php']
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,66 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'WpConfigBackup' do
|
||||
|
||||
before :all do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_config_backup'
|
||||
@config_backup_files = WpConfigBackup.config_backup_files
|
||||
|
||||
@module.extend(WpConfigBackup)
|
||||
end
|
||||
|
||||
describe '#config_backup' do
|
||||
|
||||
# set all @config_backup_files to point to a 404
|
||||
before :each do
|
||||
@config_backup_files.each do |backup_file|
|
||||
file_url = @module.uri.merge(URI.escape(backup_file)).to_s
|
||||
|
||||
stub_request(:get, file_url).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
it 'shoud return an empty array if no config backup is present' do
|
||||
@module.config_backup.should be_empty
|
||||
end
|
||||
|
||||
it 'should return an array with 1 backup file' do
|
||||
expected = []
|
||||
|
||||
@config_backup_files.sample(1).each do |backup_file|
|
||||
file_url = @module.uri.merge(URI.escape(backup_file)).to_s
|
||||
expected << file_url
|
||||
|
||||
stub_request_to_fixture(url: file_url, fixture: @fixtures_dir + '/wp-config.php')
|
||||
end
|
||||
|
||||
wp_config_backup = @module.config_backup
|
||||
wp_config_backup.should_not be_empty
|
||||
wp_config_backup.should === expected
|
||||
end
|
||||
|
||||
# Is there a way to factorise that one with the previous test ?
|
||||
it 'should return an array with 2 backup file' do
|
||||
expected = []
|
||||
|
||||
@config_backup_files.sample(2).each do |backup_file|
|
||||
file_url = @module.uri.merge(URI.escape(backup_file)).to_s
|
||||
expected << file_url
|
||||
|
||||
stub_request_to_fixture(url: file_url, fixture: @fixtures_dir + '/wp-config.php')
|
||||
end
|
||||
|
||||
wp_config_backup = @module.config_backup
|
||||
wp_config_backup.should_not be_empty
|
||||
wp_config_backup.sort.should === expected.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe '#config_backup_files' do
|
||||
it 'should not contain duplicates' do
|
||||
WpConfigBackup.config_backup_files.flatten.uniq.length.should == WpConfigBackup.config_backup_files.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'WpFullPathDisclosure' do
|
||||
|
||||
before :all do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@module.extend(WpFullPathDisclosure)
|
||||
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_full_path_disclosure'
|
||||
end
|
||||
|
||||
describe '#full_path_disclosure_url' do
|
||||
it 'should return http://example.localhost/wp-includes/rss-functions.php' do
|
||||
@module.full_path_disclosure_url.should === 'http://example.localhost/wp-includes/rss-functions.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_full_path_disclosure?' do
|
||||
|
||||
it 'should return false on a 404' do
|
||||
stub_request(:get, @module.full_path_disclosure_url).
|
||||
to_return(status: 404)
|
||||
|
||||
@module.has_full_path_disclosure?.should be_false
|
||||
end
|
||||
|
||||
it 'should return false if no fpd found (blank page for example)' do
|
||||
stub_request(:get, @module.full_path_disclosure_url).
|
||||
to_return(status: 200, body: '')
|
||||
|
||||
@module.has_full_path_disclosure?.should be_false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:get, @module.full_path_disclosure_url).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/rss-functions-disclosure.php'))
|
||||
|
||||
@module.has_full_path_disclosure?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,99 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'WpLoginProtection' do
|
||||
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@module.extend(WpLoginProtection)
|
||||
@module.stub(:wp_plugins_dir).and_return('wp-content/plugins')
|
||||
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_login_protection'
|
||||
end
|
||||
|
||||
describe '#login_url' do
|
||||
it 'should return the login page url : http://example.localhost/wp-login.php' do
|
||||
@module.login_url.should === 'http://example.localhost/wp-login.php'
|
||||
end
|
||||
end
|
||||
|
||||
# It will test all protected methods has_.*_protection with each fixtures to be sure that
|
||||
# there is not false positive : for example the login-lock must not be detected as login-lockdown
|
||||
describe '#has_.*_protection?' do
|
||||
|
||||
pattern = WpLoginProtection::LOGIN_PROTECTION_METHOD_PATTERN
|
||||
fixtures =
|
||||
%w{
|
||||
wp-login-clean.php wp-login-login_lockdown.php wp-login-login_lock.php
|
||||
wp-login-better_wp_security.php wp-login-simple_login_lockdown.php wp-login-login_security_solution.php
|
||||
wp-login-limit_login_attempts.php wp-login-bluetrait_event_viewer.php
|
||||
}
|
||||
# For plugins which are detected from the existence of their directory into wp-content/plugins/ (or one of their file)
|
||||
# and not from a regex into the login page
|
||||
special_plugins = %w{better_wp_security simple_login_lockdown login_security_solution limit_login_attempts bluetrait_event_viewer}
|
||||
|
||||
after :each do
|
||||
stub_request_to_fixture(url: @module.login_url, fixture: @fixture)
|
||||
|
||||
# Stub all special plugins urls to a 404 except if it's the one we want
|
||||
special_plugins.each do |special_plugin|
|
||||
special_plugin_call_detection_symbol = :"has_#{special_plugin}_protection?"
|
||||
special_plugin_call_url_symbol = :"#{special_plugin}_url"
|
||||
|
||||
status_code = (@symbol_to_call === special_plugin_call_detection_symbol and @expected === true) ? 200 : 404
|
||||
stub_request(:get, @module.send(special_plugin_call_url_symbol).to_s).to_return(status: status_code)
|
||||
end
|
||||
|
||||
@module.send(@symbol_to_call).should === @expected
|
||||
end
|
||||
|
||||
WpLoginProtection.protected_instance_methods.grep(pattern).each do |symbol_to_call|
|
||||
plugin_name_from_symbol = symbol_to_call[pattern, 1].gsub('_', '-')
|
||||
|
||||
fixtures.each do |fixture|
|
||||
plugin_name_from_fixture = fixture[/wp-login-(.*)\.php/i, 1].gsub('_', '-')
|
||||
expected = plugin_name_from_fixture === plugin_name_from_symbol ? true : false
|
||||
|
||||
it "#{symbol_to_call} with #{fixture} should return #{expected}" do
|
||||
@plugin_name = plugin_name_from_fixture
|
||||
@fixture = @fixtures_dir + '/' + fixture
|
||||
@symbol_to_call = symbol_to_call
|
||||
@expected = expected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Factorise this with the code above ? :D
|
||||
describe '#login_protection_plugin' do
|
||||
after :each do
|
||||
stub_request_to_fixture(url: @module.login_url, fixture: @fixture)
|
||||
stub_request(:get, @module.send(:better_wp_security_url).to_s).to_return(status: 404)
|
||||
stub_request(:get, @module.send(:simple_login_lockdown_url).to_s).to_return(status: 404)
|
||||
stub_request(:get, @module.send(:login_security_solution_url).to_s).to_return(status: 404)
|
||||
stub_request(:get, @module.send(:limit_login_attempts_url).to_s).to_return(status: 404)
|
||||
stub_request(:get, @module.send(:bluetrait_event_viewer_url).to_s).to_return(status: 404)
|
||||
|
||||
@module.login_protection_plugin().should == @plugin_expected
|
||||
@module.has_login_protection?.should === @has_protection_expected
|
||||
end
|
||||
|
||||
it 'should return nil if no protection is present' do
|
||||
@fixture = @fixtures_dir + '/wp-login-clean.php'
|
||||
@plugin_expected = nil
|
||||
@has_protection_expected = false
|
||||
end
|
||||
|
||||
it 'should return a login-lockdown WpPlugin object' do
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lockdown.php'
|
||||
@plugin_expected = WpPlugin.new(@module.uri, name: 'login-lockdown')
|
||||
@has_protection_expected = true
|
||||
end
|
||||
|
||||
it 'should return a login-lock WpPlugin object' do
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lock.php'
|
||||
@plugin_expected = WpPlugin.new(@module.uri, name: 'login-lock')
|
||||
@has_protection_expected = true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,43 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples_for 'WpReadme' do
|
||||
|
||||
before :all do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_readme'
|
||||
|
||||
@module.extend(WpReadme)
|
||||
end
|
||||
|
||||
describe '#readme_url' do
|
||||
it 'should return http://example.localhost/readme.html' do
|
||||
@module.readme_url.should === "#{@module.uri}readme.html"
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_readme?' do
|
||||
|
||||
it 'should return false on a 404' do
|
||||
stub_request(:get, @module.readme_url).
|
||||
to_return(status: 404)
|
||||
|
||||
@module.has_readme?.should be_false
|
||||
end
|
||||
|
||||
it 'should return true if it exists' do
|
||||
stub_request(:get, @module.readme_url).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/readme-3.2.1.html'))
|
||||
|
||||
@module.has_readme?.should be_true
|
||||
end
|
||||
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=108
|
||||
it 'should return true even if the readme.html is not in english' do
|
||||
stub_request(:get, @module.readme_url).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/readme-3.3.2-fr.html'))
|
||||
|
||||
@module.has_readme?.should be_true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3,27 +3,29 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpTarget do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR }
|
||||
let(:target_url) { 'http://example.localhost/' }
|
||||
|
||||
before :each do
|
||||
Browser::reset
|
||||
@options =
|
||||
subject(:wp_target) { WpTarget.new(target_url, options) }
|
||||
let(:target_url) { 'http://example.localhost/' }
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR }
|
||||
let(:login_url) { wp_target.uri.merge('wp-login.php').to_s }
|
||||
let(:options) {
|
||||
{
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
|
||||
cache_ttl: 0,
|
||||
wp_content_dir: 'wp-content',
|
||||
wp_plugins_dir: 'wp-content/plugins'
|
||||
}
|
||||
@wp_target = WpTarget.new(target_url, @options)
|
||||
end
|
||||
}
|
||||
|
||||
it_should_behave_like 'WpReadme'
|
||||
it_should_behave_like 'WpConfigBackup'
|
||||
it_should_behave_like 'WpFullPathDisclosure'
|
||||
it_should_behave_like 'WpLoginProtection'
|
||||
it_should_behave_like 'Malwares'
|
||||
it_should_behave_like 'BruteForce'
|
||||
before { Browser::reset }
|
||||
|
||||
it_behaves_like 'WpTarget::Malwares'
|
||||
it_behaves_like 'WpTarget::WpReadme'
|
||||
it_behaves_like 'WpTarget::BruteForce'
|
||||
it_behaves_like 'WpTarget::WpRegistrable'
|
||||
it_behaves_like 'WpTarget::WpConfigBackup'
|
||||
it_behaves_like 'WpTarget::WpLoginProtection'
|
||||
it_behaves_like 'WpTarget::WpCustomDirectories'
|
||||
it_behaves_like 'WpTarget::WpFullPathDisclosure'
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should raise an error if the target_url is nil or empty' do
|
||||
@@ -33,256 +35,109 @@ describe WpTarget do
|
||||
end
|
||||
|
||||
describe '#login_url' do
|
||||
let(:login_url) { @wp_target.uri.merge('wp-login.php').to_s }
|
||||
|
||||
it 'should return the login url of the target' do
|
||||
it 'returns the login url of the target' do
|
||||
stub_request(:get, login_url).to_return(status: 200, body: '')
|
||||
|
||||
@wp_target.login_url.should === login_url
|
||||
wp_target.login_url.should === login_url
|
||||
end
|
||||
|
||||
it 'should return the redirection url if there is one (ie: for https)' do
|
||||
it 'returns the redirection url if there is one (ie: for https)' do
|
||||
https_login_url = login_url.gsub(/^http:/, 'https:')
|
||||
|
||||
stub_request(:get, login_url).to_return(status: 302, headers: { location: https_login_url })
|
||||
stub_request(:get, https_login_url).to_return(status: 200)
|
||||
|
||||
@wp_target.login_url.should === https_login_url
|
||||
wp_target.login_url.should === https_login_url
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wordpress?' do
|
||||
# each url (wp-login and xmlrpc) pointed to a 404
|
||||
before :each do
|
||||
stub_request(:get, @wp_target.url).
|
||||
to_return(status: 200, body: '', headers: { 'X-Pingback' => @wp_target.uri.merge('xmlrpc.php')})
|
||||
stub_request(:get, wp_target.url).
|
||||
to_return(status: 200, body: '', headers: { 'X-Pingback' => wp_target.uri.merge('xmlrpc.php')})
|
||||
|
||||
# Preventing redirection check from login_url()
|
||||
@wp_target.stub(redirection: nil)
|
||||
wp_target.stub(redirection: nil)
|
||||
|
||||
[@wp_target.login_url, @wp_target.xml_rpc_url].each do |url|
|
||||
[wp_target.login_url, wp_target.xml_rpc_url].each do |url|
|
||||
stub_request(:get, url).to_return(status: 404, body: '')
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return true if there is a /wp-content/ detected in the index page source' do
|
||||
stub_request_to_fixture(url: @wp_target.url, fixture: fixtures_dir + '/wp_content_dir/wordpress-3.4.1.htm')
|
||||
it 'returns true if there is a /wp-content/ detected in the index page source' do
|
||||
stub_request_to_fixture(url: wp_target.url, fixture: fixtures_dir + '/wp_content_dir/wordpress-3.4.1.htm')
|
||||
|
||||
@wp_target.should be_wordpress
|
||||
wp_target.should be_wordpress
|
||||
end
|
||||
|
||||
it 'should return true if the xmlrpc is found' do
|
||||
stub_request(:get, @wp_target.xml_rpc_url).
|
||||
it 'returns true if the xmlrpc is found' do
|
||||
stub_request(:get, wp_target.xml_rpc_url).
|
||||
to_return(status: 200, body: File.new(fixtures_dir + '/xmlrpc.php'))
|
||||
|
||||
@wp_target.should be_wordpress
|
||||
wp_target.should be_wordpress
|
||||
end
|
||||
|
||||
it 'should return true if the wp-login is found and is a valid wordpress one' do
|
||||
stub_request(:get, @wp_target.login_url).
|
||||
it 'returns true if the wp-login is found and is a valid wordpress one' do
|
||||
stub_request(:get, wp_target.login_url).
|
||||
to_return(status: 200, body: File.new(fixtures_dir + '/wp-login.php'))
|
||||
|
||||
@wp_target.should be_wordpress
|
||||
wp_target.should be_wordpress
|
||||
end
|
||||
|
||||
it 'should return false if both files are not found (404)' do
|
||||
@wp_target.should_not be_wordpress
|
||||
it 'returns false if both files are not found (404)' do
|
||||
wp_target.should_not be_wordpress
|
||||
end
|
||||
|
||||
context 'when the url contains "wordpress" and is a 404' do
|
||||
let(:target_url) { 'http://lamp/wordpress-3.5./' }
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, @wp_target.login_url).to_return(status: 404, body: 'The requested URL /wordpress-3.5. was not found on this server.')
|
||||
stub_request(:get, wp_target.login_url).to_return(status: 404, body: 'The requested URL /wordpress-3.5. was not found on this server.')
|
||||
|
||||
@wp_target.should_not be_wordpress
|
||||
wp_target.should_not be_wordpress
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#redirection' do
|
||||
it 'should return nil if no redirection detected' do
|
||||
stub_request(:get, @wp_target.url).to_return(status: 200, body: '')
|
||||
it 'returns nil if no redirection detected' do
|
||||
stub_request(:get, wp_target.url).to_return(status: 200, body: '')
|
||||
|
||||
@wp_target.redirection.should be_nil
|
||||
wp_target.redirection.should be_nil
|
||||
end
|
||||
|
||||
[301, 302].each do |status_code|
|
||||
it "should return http://new-location.com if the status code is #{status_code}" do
|
||||
it "returns http://new-location.com if the status code is #{status_code}" do
|
||||
new_location = 'http://new-location.com'
|
||||
|
||||
stub_request(:get, @wp_target.url).
|
||||
stub_request(:get, wp_target.url).
|
||||
to_return(status: status_code, headers: { location: new_location })
|
||||
|
||||
stub_request(:get, new_location).to_return(status: 200)
|
||||
|
||||
@wp_target.redirection.should === 'http://new-location.com'
|
||||
wp_target.redirection.should === 'http://new-location.com'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple redirections' do
|
||||
it 'should return the last redirection' do
|
||||
first_redirection = 'www.redirection.com'
|
||||
it 'returns the last redirection' do
|
||||
first_redirection = 'www.redirection.com'
|
||||
last_redirection = 'redirection.com'
|
||||
|
||||
stub_request(:get, @wp_target.url).to_return(status: 301, headers: { location: first_redirection })
|
||||
stub_request(:get, wp_target.url).to_return(status: 301, headers: { location: first_redirection })
|
||||
stub_request(:get, first_redirection).to_return(status: 302, headers: { location: last_redirection })
|
||||
stub_request(:get, last_redirection).to_return(status: 200)
|
||||
|
||||
@wp_target.redirection.should === last_redirection
|
||||
wp_target.redirection.should === last_redirection
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_content_dir' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_content_dir' }
|
||||
|
||||
after :each do
|
||||
@wp_target = WpTarget.new(@target_url) if @target_url
|
||||
|
||||
stub_request_to_fixture(url: @wp_target.url, fixture: @fixture) if @fixture
|
||||
stub_request(:any, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request
|
||||
stub_request(:any, /.*\.html$/).to_return(:status => 200, :body => '') # 404 hash request
|
||||
|
||||
@wp_target.wp_content_dir.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the string set in the initialize method' do
|
||||
@wp_target = WpTarget.new('http://example.localhost/', @options.merge(wp_content_dir: 'hello-world'))
|
||||
@expected = 'hello-world'
|
||||
end
|
||||
|
||||
it "should return 'wp-content'" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it "should return 'wp-content' if url has trailing slash" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1/'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it "should find the default 'wp-content' dir even if the target_url is not the same (ie : the user supply an IP address and the url used in the code is a domain)" do
|
||||
@target_url = 'http://192.168.1.103/wordpress-3.4.1/'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it "should return 'custom-content'" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1-custom'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1-custom.htm'
|
||||
@expected = 'custom-content'
|
||||
end
|
||||
|
||||
it "should return 'custom content spaces'" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1-custom'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1-custom-with-spaces.htm'
|
||||
@expected = 'custom content spaces'
|
||||
end
|
||||
|
||||
it "should return 'custom-dir/subdir/content'" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1-custom'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1-custom-subdirectories.htm'
|
||||
@expected = 'custom-dir/subdir/content'
|
||||
end
|
||||
|
||||
it 'should also check in src attributes' do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1-in-src.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it 'should find the location even if the src or href goes in the plugins dir' do
|
||||
@target_url = 'http://wordpress-3.4.1-in-plugins.htm'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1-in-plugins.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it 'should not detect facebook.com as a custom wp-content directory' do
|
||||
@target_url = 'http://lamp.localhost/'
|
||||
@fixture = fixtures_dir + '/facebook-detection.htm'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#default_wp_content_dir_exists?' do
|
||||
after :each do
|
||||
@wp_target = WpTarget.new('http://lamp.localhost/')
|
||||
stub_request(:any, @wp_target.url).to_return(:status => 200, :body => 'homepage') # homepage request
|
||||
|
||||
@wp_target.default_wp_content_dir_exists?.should === @expected
|
||||
end
|
||||
|
||||
it 'returns false if wp-content returns an invalid response code' do
|
||||
stub_request(:any, /.*\/wp-content\/?$/).to_return(:status => 404, :body => '') # default dir request
|
||||
stub_request(:any, /.*\.html$/).to_return(:status => 404, :body => '') # 404 hash request
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns false if wp-content and homepage have same bodies' do
|
||||
stub_request(:any, /.*\/wp-content\/?$/).to_return(:status => 200, :body => 'homepage') # default dir request
|
||||
stub_request(:any, /.*\.html$/).to_return(:status => 404, :body => '404!') # 404 hash request
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns false if wp-content and 404 page have same bodies' do
|
||||
stub_request(:any, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '404!') # default dir request
|
||||
stub_request(:any, /.*\.html$/).to_return(:status => 404, :body => '404!') # 404 hash request
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true if wp-content, 404 page and hoempage return different bodies' do
|
||||
stub_request(:any, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request
|
||||
stub_request(:any, /.*\.html$/).to_return(:status => 200, :body => '404!') # 404 hash request
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_plugins_dir' do
|
||||
after :each do
|
||||
@wp_target.stub(wp_plugins_dir: @stub_value) if @stub_value
|
||||
|
||||
@wp_target.wp_plugins_dir.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the string set in the initialize method' do
|
||||
@wp_target = WpTarget.new('http://example.localhost/', @options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins'))
|
||||
@expected = 'custom-plugins'
|
||||
end
|
||||
|
||||
it "should return 'plugins'" do
|
||||
@stub_value = 'plugins'
|
||||
@expected = 'plugins'
|
||||
end
|
||||
|
||||
it "should return 'wp-content/plugins'" do
|
||||
@wp_target = WpTarget.new('http://example.localhost/', @options.merge(wp_content_dir: 'wp-content', wp_plugins_dir: nil))
|
||||
@expected = 'wp-content/plugins'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_plugins_dir_exists?' do
|
||||
it 'should return true' do
|
||||
target = WpTarget.new('http://example.localhost/', @options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins'))
|
||||
url = target.uri.merge(target.wp_plugins_dir).to_s
|
||||
stub_request(:any, url).to_return(status: 200)
|
||||
target.wp_plugins_dir_exists?.should == true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
target = WpTarget.new('http://example.localhost/', @options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins'))
|
||||
url = target.uri.merge(target.wp_plugins_dir).to_s
|
||||
stub_request(:any, url).to_return(status: 404)
|
||||
target.wp_plugins_dir_exists?.should == false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#debug_log_url' do
|
||||
it "should return 'http://example.localhost/wp-content/debug.log" do
|
||||
@wp_target.stub(wp_content_dir: 'wp-content')
|
||||
@wp_target.debug_log_url.should === 'http://example.localhost/wp-content/debug.log'
|
||||
it "returns 'http://example.localhost/wp-content/debug.log" do
|
||||
wp_target.stub(wp_content_dir: 'wp-content')
|
||||
wp_target.debug_log_url.should === 'http://example.localhost/wp-content/debug.log'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -290,17 +145,17 @@ describe WpTarget do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/debug_log' }
|
||||
|
||||
after :each do
|
||||
@wp_target.stub(wp_content_dir: 'wp-content')
|
||||
stub_request_to_fixture(url: @wp_target.debug_log_url(), fixture: @fixture)
|
||||
@wp_target.has_debug_log?.should === @expected
|
||||
wp_target.stub(wp_content_dir: 'wp-content')
|
||||
stub_request_to_fixture(url: wp_target.debug_log_url(), fixture: @fixture)
|
||||
wp_target.has_debug_log?.should === @expected
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
it 'returns false' do
|
||||
@fixture = SPEC_FIXTURES_DIR + '/empty-file'
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
it 'returns true' do
|
||||
@fixture = fixtures_dir + '/debug.log'
|
||||
@expected = true
|
||||
end
|
||||
@@ -312,102 +167,26 @@ describe WpTarget do
|
||||
end
|
||||
|
||||
describe '#search_replace_db_2_url' do
|
||||
it 'should return the correct url' do
|
||||
@wp_target.search_replace_db_2_url.should == 'http://example.localhost/searchreplacedb2.php'
|
||||
it 'returns the correct url' do
|
||||
wp_target.search_replace_db_2_url.should == 'http://example.localhost/searchreplacedb2.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#search_replace_db_2_exists?' do
|
||||
it 'should return true' do
|
||||
stub_request(:any, @wp_target.search_replace_db_2_url).to_return(status: 200, body: 'asdf by interconnect asdf')
|
||||
@wp_target.search_replace_db_2_exists?.should be_true
|
||||
it 'returns true' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 200, body: 'asdf by interconnect asdf')
|
||||
wp_target.search_replace_db_2_exists?.should be_true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:any, @wp_target.search_replace_db_2_url).to_return(status: 500)
|
||||
@wp_target.search_replace_db_2_exists?.should be_false
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500)
|
||||
wp_target.search_replace_db_2_exists?.should be_false
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:any, @wp_target.search_replace_db_2_url).to_return(status: 500, body: 'asdf by interconnect asdf')
|
||||
@wp_target.search_replace_db_2_exists?.should be_false
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500, body: 'asdf by interconnect asdf')
|
||||
wp_target.search_replace_db_2_exists?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#registration_url' do
|
||||
it 'should return the correct url (multisite)' do
|
||||
# set to multi site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 200)
|
||||
@wp_target.registration_url.to_s.should == 'http://example.localhost/wp-signup.php'
|
||||
end
|
||||
|
||||
it 'should return the correct url (not multisite)' do
|
||||
# set to single site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 302, headers: { 'Location' => 'wp-login.php?action=register' })
|
||||
@wp_target.registration_url.to_s.should == 'http://example.localhost/wp-login.php?action=register'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#registration_enabled?' do
|
||||
it 'should return false (multisite)' do
|
||||
# set to multi site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 200)
|
||||
stub_request(:any, @wp_target.registration_url.to_s).to_return(status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' })
|
||||
@wp_target.registration_enabled?.should be_false
|
||||
end
|
||||
|
||||
it 'should return true (multisite)' do
|
||||
# set to multi site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 200)
|
||||
stub_request(:any, @wp_target.registration_url.to_s).to_return(status: 200, body: %{<form id="setupform" method="post" action="wp-signup.php">})
|
||||
@wp_target.registration_enabled?.should be_true
|
||||
end
|
||||
|
||||
it 'should return false (not multisite)' do
|
||||
# set to single site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 302, headers: { 'Location' => 'wp-login.php?action=register' })
|
||||
stub_request(:any, @wp_target.registration_url.to_s).to_return(status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' })
|
||||
@wp_target.registration_enabled?.should be_false
|
||||
end
|
||||
|
||||
it 'should return true (not multisite)' do
|
||||
# set to single site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 302, headers: { 'Location' => 'wp-login.php?action=register' })
|
||||
stub_request(:any, @wp_target.registration_url.to_s).to_return(status: 200, body: %{<form name="registerform" id="registerform" action="wp-login.php"})
|
||||
@wp_target.registration_enabled?.should be_true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
# set to single site
|
||||
stub_request(:any, 'http://example.localhost/wp-signup.php').to_return(status: 302, headers: { 'Location' => 'wp-login.php?action=register' })
|
||||
stub_request(:any, @wp_target.registration_url.to_s).to_return(status: 500)
|
||||
@wp_target.registration_enabled?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#is_multisite?' do
|
||||
before :each do
|
||||
@url = @wp_target.uri.merge('wp-signup.php').to_s
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:any, @url).to_return(status: 302, headers: { 'Location' => 'wp-login.php?action=register' })
|
||||
@wp_target.is_multisite?.should be_false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:any, @url).to_return(status: 302, headers: { 'Location' => 'http://example.localhost/wp-signup.php' })
|
||||
@wp_target.is_multisite?.should be_true
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:any, @url).to_return(status: 200)
|
||||
@wp_target.is_multisite?.should be_true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:any, @url).to_return(status: 500)
|
||||
@wp_target.is_multisite?.should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,36 +5,9 @@ require 'spec_helper'
|
||||
require WPSCAN_LIB_DIR + '/wpscan_helper'
|
||||
|
||||
SPEC_FIXTURES_WPSCAN_DIR = SPEC_FIXTURES_DIR + '/wpscan'
|
||||
SPEC_FIXTURES_WPSCAN_MODULES_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/modules'
|
||||
SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/web_site'
|
||||
SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_target'
|
||||
SPEC_FIXTURES_WPSCAN_WPSCAN_OPTIONS_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wpscan_options'
|
||||
SPEC_FIXTURES_WPSCAN_WP_THEME_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_theme'
|
||||
SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_plugin'
|
||||
SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_version'
|
||||
|
||||
# This class is a HACK to simulate the WpTarget behavior in order
|
||||
# to be able to test the modules independently
|
||||
class WpScanModuleSpec
|
||||
attr_reader :uri
|
||||
attr_accessor :error_404_hash, :homepage_hash, :wp_content_dir, :verbose
|
||||
|
||||
def initialize(target_url)
|
||||
@uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
|
||||
|
||||
Browser::reset
|
||||
Browser.instance(
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
|
||||
cache_ttl: 0
|
||||
)
|
||||
end
|
||||
|
||||
def url
|
||||
@uri.to_s
|
||||
end
|
||||
|
||||
def login_url
|
||||
@uri.merge('wp-login.php').to_s
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user