So long hombre
This commit is contained in:
@@ -1,60 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'Browser::Actions' do
|
||||
|
||||
describe '#post' do
|
||||
it 'returns a Typhoeus::Response wth body = "Welcome Master" if login=master&password=itsme!' do
|
||||
url = 'http://example.com/'
|
||||
|
||||
stub_request(:post, url).with(body: { login: 'master', password: 'itsme!' }).
|
||||
to_return(status: 200, body: 'Welcome Master')
|
||||
|
||||
response = Browser.post(
|
||||
url,
|
||||
body: 'login=master&password=itsme!'
|
||||
#body: { login: 'master', password: 'hello' } # It's should be this line, but it fails
|
||||
)
|
||||
|
||||
expect(response).to be_a Typhoeus::Response
|
||||
expect(response.body).to eq 'Welcome Master'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get' do
|
||||
it "returns a Typhoeus::Response with body = 'Hello World !'" do
|
||||
url = 'http://example.com/'
|
||||
|
||||
stub_request(:get, url).
|
||||
to_return(status: 200, body: 'Hello World !')
|
||||
|
||||
response = Browser.get(url)
|
||||
|
||||
expect(response).to be_a Typhoeus::Response
|
||||
expect(response.body).to eq 'Hello World !'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_and_follow_location' do
|
||||
# Typhoeus does not follow the location with rspec
|
||||
# See https://github.com/typhoeus/typhoeus/issues/279
|
||||
|
||||
#context 'whitout max_redirects params' do
|
||||
# context 'when multiples redirection' do
|
||||
# it 'returns the last redirection response' do
|
||||
# url = 'http://target.com'
|
||||
# first_redirection = 'www.first-redirection.com'
|
||||
# last_redirection = 'last-redirection.com'
|
||||
|
||||
# stub_request(:get, url).to_return(status: 301, headers: { location: first_redirection })
|
||||
# stub_request(:get, first_redirection).to_return(status: 301, headers: { location: last_redirection })
|
||||
# stub_request(:get, last_redirection).to_return(status: 200, body: 'Hello World!')
|
||||
|
||||
# response = Browser.get_and_follow_location(url)
|
||||
|
||||
# response.body.should === 'Hellow World!'
|
||||
# end
|
||||
# end
|
||||
#end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,199 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'Browser::Options' do
|
||||
|
||||
describe '#basic_auth=' do
|
||||
let(:exception) { /^Invalid basic authentication format, "login:password" or "Basic base_64_encoded" expected. Your input: .+$/ }
|
||||
|
||||
after do
|
||||
if @expected
|
||||
browser.basic_auth = @auth
|
||||
expect(browser.basic_auth).to eq @expected
|
||||
else
|
||||
expect { browser.basic_auth = @auth }.to raise_error(RuntimeError, exception)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid format' do
|
||||
it 'raises an error' do
|
||||
@auth = 'invalid'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when login:password' do
|
||||
it 'sets the basic auth' do
|
||||
@auth = 'admin:weakpass'
|
||||
@expected = 'Basic YWRtaW46d2Vha3Bhc3M='
|
||||
end
|
||||
end
|
||||
|
||||
context 'when Basic base_64_encoded' do
|
||||
context 'when invalid base_64_encoded' do
|
||||
it 'raises an error' do
|
||||
@auth = 'Basic <script>alert(1)</script>'
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets the basic auth' do
|
||||
@auth = 'Basic dXNlcm5hbWU6dGhlYmlncGFzc3dvcmRzb3dlYWs='
|
||||
@expected = @auth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#max_threads= & #max_threads' do
|
||||
let(:exception) { 'max_threads must be an Integer > 0' }
|
||||
|
||||
after do
|
||||
if @expected
|
||||
browser.max_threads = @max_threads
|
||||
expect(browser.max_threads).to eq @expected
|
||||
else
|
||||
expect { browser.max_threads = @max_threads }.to raise_error(exception)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the argument is not an Integer > 0' do
|
||||
it 'raises an error' do
|
||||
@max_thrads = nil
|
||||
end
|
||||
|
||||
it 'raises an error' do
|
||||
@max_threads = -3
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the argument is an Integer' do
|
||||
it 'returns the @max_threads' do
|
||||
@max_threads = 10
|
||||
@expected = 10
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'proxy=' do
|
||||
let(:exception) { 'Invalid proxy format. Should be [protocol://]host:port.' }
|
||||
|
||||
after do
|
||||
if @expected
|
||||
browser.proxy = @proxy
|
||||
expect(browser.proxy).to eq @expected
|
||||
else
|
||||
expect { browser.proxy = @proxy }.to raise_error(exception)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid format' do
|
||||
it 'raises an error' do
|
||||
@proxy = 'yolo'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid format' do
|
||||
@proxy = '127.0.0.1:9050'
|
||||
@expected = @proxy
|
||||
end
|
||||
end
|
||||
|
||||
describe 'proxy_auth=' do
|
||||
let(:exception) { 'Invalid proxy auth format, expected username:password or {proxy_username: username, proxy_password: password}' }
|
||||
|
||||
after :each do
|
||||
if @expected
|
||||
browser.proxy_auth = @proxy_auth
|
||||
expect(browser.proxy_auth).to be === @expected
|
||||
else
|
||||
expect { browser.proxy_auth = @proxy_auth }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the auth supplied is' do
|
||||
context 'not a String or a Hash' do
|
||||
it 'raises an error' do
|
||||
@proxy_auth = 10
|
||||
end
|
||||
end
|
||||
|
||||
context 'a String with' do
|
||||
context 'invalid format' do
|
||||
it 'raises an error' do
|
||||
@proxy_auth = 'invaludauthformat'
|
||||
end
|
||||
end
|
||||
|
||||
context 'valid format' do
|
||||
it 'sets the auth' do
|
||||
@proxy_auth = 'username:passwd'
|
||||
@expected = @proxy_auth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'a Hash with' do
|
||||
context 'only :proxy_username' do
|
||||
it 'raises an error' do
|
||||
@proxy_auth = { proxy_username: 'username' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'only :proxy_password' do
|
||||
it 'raises an error' do
|
||||
@proxy_auth = { proxy_password: 'hello' }
|
||||
end
|
||||
end
|
||||
|
||||
context ':proxy_username and :proxy_password' do
|
||||
it 'sets the auth' do
|
||||
@proxy_auth = { proxy_username: 'user', proxy_password: 'pass' }
|
||||
@expected = 'user:pass'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#override_config' do
|
||||
after do
|
||||
browser.send(:override_config, override_options)
|
||||
end
|
||||
|
||||
let(:config) { JSON.parse(File.read(browser.config_file)) }
|
||||
|
||||
context 'when an option value is nil' do
|
||||
let(:override_options) { { max_threads: nil } }
|
||||
|
||||
it 'does not set it' do
|
||||
expect(browser).not_to receive(:max_threads=)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an option is no allowed' do
|
||||
let(:override_options) { { not_allowed: 'owned' } }
|
||||
|
||||
it 'does not set it' do
|
||||
expect(browser).not_to receive(:not_allowed=)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when valid option' do
|
||||
let(:override_options) { { max_threads: 30 } }
|
||||
|
||||
it 'sets it' do
|
||||
expect(browser).to receive(:max_threads=).with(30)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple options' do
|
||||
let(:override_options) {
|
||||
{ max_threads: 10, not_allowed: 'owned', proxy: 'host:port' }
|
||||
}
|
||||
|
||||
it 'sets @max_threads, @proxy' do
|
||||
expect(browser).not_to receive(:not_allowed=)
|
||||
expect(browser).to receive(:max_threads=).with(10)
|
||||
expect(browser).to receive(:proxy=).with('host:port')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,108 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WebSite::HumansTxt' do
|
||||
let(:known_dirs) { WebSite::HumansTxt.known_dirs }
|
||||
|
||||
describe '#humans_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(web_site.humans_url).to eql 'http://example.localhost/humans.txt'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_humans?' do
|
||||
it 'returns true' do
|
||||
stub_request(:get, web_site.humans_url).to_return(status: 200)
|
||||
expect(web_site.has_humans?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, web_site.humans_url).to_return(status: 404)
|
||||
expect(web_site.has_humans?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parse_humans_txt' do
|
||||
|
||||
context 'installed in root' do
|
||||
after :each do
|
||||
stub_request_to_fixture(url: web_site.humans_url, fixture: @fixture)
|
||||
humans = web_site.parse_humans_txt
|
||||
expect(humans).to match_array @expected
|
||||
end
|
||||
|
||||
it 'returns an empty Array (empty humans.txt)' do
|
||||
@fixture = fixtures_dir + '/humans_txt/empty_humans.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns an empty Array (invalid humans.txt)' do
|
||||
@fixture = fixtures_dir + '/humans_txt/invalid_humans.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns some urls and some strings' do
|
||||
@fixture = fixtures_dir + '/humans_txt/invalid_humans_2.txt'
|
||||
@expected = %w(
|
||||
/ÖÜ()=?
|
||||
http://10.0.0.0/wp-includes/
|
||||
http://example.localhost/asdf/
|
||||
wooooza
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an Array of urls (valid humans.txt)' do
|
||||
@fixture = fixtures_dir + '/humans_txt/humans.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from humans.txt test 1' do
|
||||
@fixture = fixtures_dir + '/humans_txt/humans_duplicate_1.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from humans.txt test 2' do
|
||||
@fixture = fixtures_dir + '/humans_txt/humans_duplicate_2.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'installed in sub directory' do
|
||||
it 'returns an Array of urls (valid humans.txt, WP installed in subdir)' do
|
||||
web_site_sub = WebSite.new('http://example.localhost/wordpress/')
|
||||
fixture = fixtures_dir + '/humans_txt/humans.txt'
|
||||
expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
stub_request_to_fixture(url: web_site_sub.humans_url, fixture: fixture)
|
||||
humans = web_site_sub.parse_humans_txt
|
||||
expect(humans).to match_array expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#known_dirs' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(known_dirs.flatten.uniq.length).to eq known_dirs.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,35 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WebSite::InterestingHeaders' do
|
||||
|
||||
let(:known_headers) { WebSite::InterestingHeaders.known_headers }
|
||||
|
||||
describe '#interesting_headers' do
|
||||
|
||||
it 'returns MyTestHeader' do
|
||||
stub_request(:head, web_site.url).
|
||||
to_return(status: 200, headers: { 'Mytestheader' => 'Mytestheadervalue' })
|
||||
expect(web_site.interesting_headers).to match_array [ [ 'MYTESTHEADER', 'Mytestheadervalue' ] ]
|
||||
end
|
||||
|
||||
it 'removes known headers' do
|
||||
stub_request(:head, web_site.url).
|
||||
to_return(status: 200, headers: { 'Location' => 'a', 'Connection' => 'Close' })
|
||||
expect(web_site.interesting_headers).to be_empty
|
||||
end
|
||||
|
||||
it 'returns nothing' do
|
||||
stub_request(:head, web_site.url).
|
||||
to_return(status: 200, headers: { })
|
||||
expect(web_site.interesting_headers).to be_empty
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '#known_headers' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(known_headers.flatten.uniq.length).to eq known_headers.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,108 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WebSite::RobotsTxt' do
|
||||
let(:known_dirs) { WebSite::RobotsTxt.known_dirs }
|
||||
|
||||
describe '#robots_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(web_site.robots_url).to eql 'http://example.localhost/robots.txt'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_robots?' do
|
||||
it 'returns true' do
|
||||
stub_request(:get, web_site.robots_url).to_return(status: 200)
|
||||
expect(web_site.has_robots?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, web_site.robots_url).to_return(status: 404)
|
||||
expect(web_site.has_robots?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parse_robots_txt' do
|
||||
|
||||
context 'installed in root' do
|
||||
after :each do
|
||||
stub_request_to_fixture(url: web_site.robots_url, fixture: @fixture)
|
||||
robots = web_site.parse_robots_txt
|
||||
expect(robots).to match_array @expected
|
||||
end
|
||||
|
||||
it 'returns an empty Array (empty robots.txt)' do
|
||||
@fixture = fixtures_dir + '/robots_txt/empty_robots.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns an empty Array (invalid robots.txt)' do
|
||||
@fixture = fixtures_dir + '/robots_txt/invalid_robots.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns some urls and some strings' do
|
||||
@fixture = fixtures_dir + '/robots_txt/invalid_robots_2.txt'
|
||||
@expected = %w(
|
||||
/ÖÜ()=?
|
||||
http://10.0.0.0/wp-includes/
|
||||
http://example.localhost/asdf/
|
||||
wooooza
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an Array of urls (valid robots.txt)' do
|
||||
@fixture = fixtures_dir + '/robots_txt/robots.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from robots.txt test 1' do
|
||||
@fixture = fixtures_dir + '/robots_txt/robots_duplicate_1.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from robots.txt test 2' do
|
||||
@fixture = fixtures_dir + '/robots_txt/robots_duplicate_2.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'installed in sub directory' do
|
||||
it 'returns an Array of urls (valid robots.txt, WP installed in subdir)' do
|
||||
web_site_sub = WebSite.new('http://example.localhost/wordpress/')
|
||||
fixture = fixtures_dir + '/robots_txt/robots.txt'
|
||||
expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
stub_request_to_fixture(url: web_site_sub.robots_url, fixture: fixture)
|
||||
robots = web_site_sub.parse_robots_txt
|
||||
expect(robots).to match_array expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#known_dirs' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(known_dirs.flatten.uniq.length).to eq known_dirs.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,108 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WebSite::SecurityTxt' do
|
||||
let(:known_dirs) { WebSite::SecurityTxt.known_dirs }
|
||||
|
||||
describe '#security_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(web_site.security_url).to eql 'http://example.localhost/security.txt'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_security?' do
|
||||
it 'returns true' do
|
||||
stub_request(:get, web_site.security_url).to_return(status: 200)
|
||||
expect(web_site.has_security?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, web_site.security_url).to_return(status: 404)
|
||||
expect(web_site.has_security?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#parse_security_txt' do
|
||||
|
||||
context 'installed in root' do
|
||||
after :each do
|
||||
stub_request_to_fixture(url: web_site.security_url, fixture: @fixture)
|
||||
security = web_site.parse_security_txt
|
||||
expect(security).to match_array @expected
|
||||
end
|
||||
|
||||
it 'returns an empty Array (empty security.txt)' do
|
||||
@fixture = fixtures_dir + '/security_txt/empty_security.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns an empty Array (invalid security.txt)' do
|
||||
@fixture = fixtures_dir + '/security_txt/invalid_security.txt'
|
||||
@expected = []
|
||||
end
|
||||
|
||||
it 'returns some urls and some strings' do
|
||||
@fixture = fixtures_dir + '/security_txt/invalid_security_2.txt'
|
||||
@expected = %w(
|
||||
/ÖÜ()=?
|
||||
http://10.0.0.0/wp-includes/
|
||||
http://example.localhost/asdf/
|
||||
wooooza
|
||||
)
|
||||
end
|
||||
|
||||
it 'returns an Array of urls (valid security.txt)' do
|
||||
@fixture = fixtures_dir + '/security_txt/security.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from security.txt test 1' do
|
||||
@fixture = fixtures_dir + '/security_txt/security_duplicate_1.txt'
|
||||
@expected = %w(
|
||||
http://example.localhost/wordpress/
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/wp-admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
end
|
||||
|
||||
it 'removes duplicate entries from security.txt test 2' do
|
||||
@fixture = fixtures_dir + '/security_txt/security_duplicate_2.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'installed in sub directory' do
|
||||
it 'returns an Array of urls (valid security.txt, WP installed in subdir)' do
|
||||
web_site_sub = WebSite.new('http://example.localhost/wordpress/')
|
||||
fixture = fixtures_dir + '/security_txt/security.txt'
|
||||
expected = %w(
|
||||
http://example.localhost/wordpress/admin/
|
||||
http://example.localhost/wordpress/secret/
|
||||
http://example.localhost/Wordpress/wp-admin/
|
||||
http://example.localhost/wp-admin/tralling-space/
|
||||
http://example.localhost/asdf/
|
||||
)
|
||||
stub_request_to_fixture(url: web_site_sub.security_url, fixture: fixture)
|
||||
security = web_site_sub.parse_security_txt
|
||||
expect(security).to match_array expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#known_dirs' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(known_dirs.flatten.uniq.length).to eq known_dirs.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,94 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpItem::Existable' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_item/existable' }
|
||||
|
||||
describe '#exists?' do
|
||||
context 'when the response is supplied' do
|
||||
let(:response) { Typhoeus::Response.new }
|
||||
|
||||
it 'does not create a request' do
|
||||
expect(Browser).not_to receive(:get)
|
||||
allow(subject).to receive(:exists_from_response?).and_return(true)
|
||||
|
||||
expect(subject.exists?({}, response)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the response is not supplied' do
|
||||
it 'creates a request' do
|
||||
expect(Browser).to receive(:get)
|
||||
allow(subject).to receive(:exists_from_response?).and_return(false)
|
||||
|
||||
expect(subject.exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#exists_from_response?' do
|
||||
let(:exists_options) { {} }
|
||||
let(:body) { 'hello world!' }
|
||||
|
||||
after do
|
||||
response = Typhoeus::Response.new(@resp_opt)
|
||||
expect(subject.send(:exists_from_response?, response, exists_options)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when invalid response.code' do
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 500 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body hash = homepage_hash or error_404_hash' do
|
||||
let(:exists_options) { { homepage_hash: Digest::MD5.hexdigest(body) } }
|
||||
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 200, body: body }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'w/o exclude_content' do
|
||||
[200, 401, 403].each do |code|
|
||||
it "returns true on #{code}" do
|
||||
@resp_opt = { code: code, body: '' }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with exclude_content' do
|
||||
let(:exists_options) { { exclude_content: %r{world!} } }
|
||||
|
||||
context 'when the body match' do
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 200, body: body }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body does not match' do
|
||||
it 'returns true' do
|
||||
@resp_opt = { code: 200, body: 'hello dude!' }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when it\'s a redirect to the homepage' do
|
||||
context 'and the cache generation time is in comment tag' do
|
||||
let(:body) { File.new(fixtures_dir + '/cache_generation.html').read }
|
||||
let(:uncommented_body) { body.gsub(/<!--.*?-->/m, '') }
|
||||
let(:exists_options) { { homepage_hash: Digest::MD5.hexdigest(uncommented_body) } }
|
||||
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 200, body: body }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,17 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpItem::Findable#Found_From=' do
|
||||
|
||||
describe '#found_from=' do
|
||||
after do
|
||||
subject.found_from = @method
|
||||
expect(subject.found_from).to eq @expected
|
||||
end
|
||||
|
||||
it 'replaces _ by space' do
|
||||
@method = 'find_from_some_detection_method'
|
||||
@expected = 'some detection method'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,142 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpItem::Infos' do
|
||||
|
||||
# 2 expected urls have to be set in the described class (or subject)
|
||||
# e.g :
|
||||
# let(:changelog_url) { }
|
||||
# let(:error_log_url) { }
|
||||
|
||||
describe '#readme_url' do
|
||||
after { expect(subject.readme_url).to eql @expected }
|
||||
|
||||
it 'returns nil' do
|
||||
stub_request(:get, /.*/).to_return(status: 404)
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
context 'when the file exists' do
|
||||
%w{readme.txt readme.md}.each do |readme|
|
||||
it 'returns the correct url' do
|
||||
url = uri.merge(readme).to_s
|
||||
@expected = url
|
||||
|
||||
stub_request(:get, %r{^(?!#{url})}).to_return(status: 404)
|
||||
stub_request(:get, url).to_return(status: 200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_readme?' do
|
||||
after do
|
||||
allow(subject).to receive_messages(readme_url: @stub)
|
||||
expect(subject.has_readme?).to eql @expected
|
||||
end
|
||||
|
||||
context 'when readme_url is nil'
|
||||
it 'returns false' do
|
||||
@stub = nil
|
||||
@expected = false
|
||||
end
|
||||
|
||||
context 'when readme_url is not nil'
|
||||
it 'returns true' do
|
||||
@stub = uri.merge('readme.txt').to_s
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#changelog_url' do
|
||||
after { expect(subject.changelog_url).to eql @expected }
|
||||
|
||||
it 'returns nil' do
|
||||
stub_request(:get, /.*/).to_return(status: 404)
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
context 'when the file exists' do
|
||||
%w{changelog.txt CHANGELOG.md}.each do |changelog|
|
||||
it 'returns the correct url' do
|
||||
url = uri.merge(changelog).to_s
|
||||
@expected = url
|
||||
|
||||
stub_request(:get, %r{^(?!#{url})}).to_return(status: 404)
|
||||
stub_request(:get, url).to_return(status: 200)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_changelog?' do
|
||||
after do
|
||||
allow(subject).to receive_messages(changelog_url: @stub)
|
||||
expect(subject.has_changelog?).to eql @expected
|
||||
end
|
||||
|
||||
context 'when changelog_url is nil'
|
||||
it 'returns false' do
|
||||
@stub = nil
|
||||
@expected = false
|
||||
end
|
||||
|
||||
context 'when changelog_url is not nil'
|
||||
it 'returns true' do
|
||||
@stub = uri.merge('changelog.txt').to_s
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_directory_listing?' do
|
||||
after do
|
||||
stub_request(:get, subject.uri.to_s).to_return(@stub_return)
|
||||
expect(subject.has_directory_listing?).to eql @expected
|
||||
end
|
||||
|
||||
context 'when the body contains <title>Index of' do
|
||||
it 'returns true' do
|
||||
@stub_return = { status: 200, body: '<title>Index of asdf</title>' }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns false otherwise' do
|
||||
@stub_return = { status: 200, body: '<title>My Wordpress Site</title>' }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns false on a 404' do
|
||||
@stub_return = { status: 404 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#error_log_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(subject.error_log_url).to eq error_log_url
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_error_log?' do
|
||||
after do
|
||||
stub_request(:get, subject.error_log_url).to_return(@stub_return)
|
||||
expect(subject.has_error_log?).to eql @expected
|
||||
end
|
||||
|
||||
it 'returns true if the pattern is detected' do
|
||||
@stub_return = { status: 200, body: File.new(MODELS_FIXTURES + '/wp_item/error_log') }
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'returns false otherwise' do
|
||||
@stub_return = { status: 200, body: 'yolo' }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns false on a 404' do
|
||||
@stub_return = { status: 404 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,175 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpItem::Versionable' do
|
||||
|
||||
describe '#version' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_item/versionable' }
|
||||
let(:readme_url) { subject.uri.merge('readme.txt').to_s }
|
||||
|
||||
context 'when the version is already set' do
|
||||
it 'returns it' do
|
||||
subject.version = '1.2'
|
||||
expect(subject.version).to eq '1.2'
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
after do
|
||||
stub_request_to_fixture(url: readme_url, fixture: fixtures_dir + @file)
|
||||
expect(subject.version).to eq @expected
|
||||
end
|
||||
|
||||
context 'when version is "trunk"' do
|
||||
it 'returns nil' do
|
||||
@file = '/trunk-version.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the version is valid' do
|
||||
context 'when leaked from the stable tag' do
|
||||
it 'returns it' do
|
||||
@file = '/simple-login-lockdown-0.4.txt'
|
||||
@expected = '0.4'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when leaked from the version' do
|
||||
it 'returns it' do
|
||||
@file = '/wp-photo-plus-5.1.15.txt'
|
||||
@expected = '5.1.15'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when version is in a release date format' do
|
||||
it 'detects and returns it' do
|
||||
@file = '/s2member.txt'
|
||||
@expected = '141007'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when version contains letters' do
|
||||
it 'returns it' do
|
||||
@file = '/beta1.txt'
|
||||
@expected = '2.0.0-beta1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/changelog_version.txt'
|
||||
@expected = '1.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/wp_polls.txt'
|
||||
@expected = '2.64'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/nextgen_gallery.txt'
|
||||
@expected = '2.0.66.33'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/wp_user_frontend.txt'
|
||||
@expected = '1.2.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/my_calendar.txt'
|
||||
@expected = '2.1.5'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/nextgen_gallery_2.txt'
|
||||
@expected = '1.9.13'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/advanced-most-recent-posts-mod.txt'
|
||||
@expected = '1.6.5.2'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/a-lead-capture-contact-form-and-tab-button-by-awebvoicecom.txt'
|
||||
@expected = '3.1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/aa-health-calculator.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/all-in-one-facebook.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/backup-scheduler.txt'
|
||||
@expected = '1.5.9'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when parsing the changelog for version numbers' do
|
||||
it 'returns it' do
|
||||
@file = '/blog-reordering.txt'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
# context 'when parsing the changelog for version numbers with dates' do
|
||||
# it 'returns it' do
|
||||
# @file = '/wp-maintenance-mode.txt'
|
||||
# @expected = '2.0.9'
|
||||
# end
|
||||
# end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
after do
|
||||
allow(subject).to receive(:version).and_return(@version)
|
||||
subject.name = 'some-name'
|
||||
|
||||
expect(subject.to_s).to eq @expected
|
||||
end
|
||||
|
||||
context 'when the version does not exist' do
|
||||
it 'returns only the name' do
|
||||
@version = nil
|
||||
@expected = 'some-name'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the version exists' do
|
||||
it 'returns the name and the version' do
|
||||
@version = '1.3'
|
||||
@expected = 'some-name - v1.3'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,109 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpItem::Vulnerable' do
|
||||
|
||||
# 2 variables have to be set in the described class or subject:
|
||||
# let(:db_file) { }
|
||||
# let(:expected_vulns) { } The expected Vulnerabilities when using db_file and vulns_xpath
|
||||
#
|
||||
# 1 variable is optional, used if supplied, otherwise subject.vulns_xpath is used
|
||||
# let(:vulns_xpath) { }
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
let(:empty_file) { MODELS_FIXTURES + '/wp_item/vulnerable/empty.json' }
|
||||
|
||||
before do
|
||||
stub_request(:get, /.*\/readme\.(?:txt|md)/i)
|
||||
stub_request(:get, /.*\/style\.css/i)
|
||||
end
|
||||
|
||||
after do
|
||||
subject.db_file = @db_file
|
||||
subject.identifier = identifier if defined?(identifier)
|
||||
|
||||
result = subject.vulnerabilities
|
||||
expect(result).to be_a Vulnerabilities
|
||||
expect(result).to eq @expected
|
||||
end
|
||||
|
||||
context 'when the db_file is empty' do
|
||||
it 'returns an empty Vulnerabilities' do
|
||||
@db_file = empty_file
|
||||
@expected = Vulnerabilities.new
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the expected vulnerabilities' do
|
||||
@db_file = db_file
|
||||
@expected = expected_vulns
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerable?' do
|
||||
after do
|
||||
allow(subject).to receive(:vulnerabilities).and_return(@stub)
|
||||
expect(subject.vulnerable?).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns false when no vulnerabilities' do
|
||||
@stub = []
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true when vulnerabilities' do
|
||||
@stub = ['not empty']
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#vulnerable_to?' do
|
||||
let(:version_orig) { '1.5.6' }
|
||||
let(:version_newer) { '1.6' }
|
||||
let(:version_older) { '1.0' }
|
||||
let(:newer) { Vulnerability.new('Newer', 'XSS', { :url => ['http://ref.com'] }, version_newer) }
|
||||
let(:older) { Vulnerability.new('Older', 'XSS', { :url => ['http://ref.com'] }, version_older) }
|
||||
let(:same) { Vulnerability.new('Same', 'XSS', { :url => ['http://ref.com'] }, version_orig) }
|
||||
let(:no_fixed_info) { Vulnerability.new('Same', 'XSS', { :url => ['http://ref.com'] }, nil) }
|
||||
|
||||
before do
|
||||
stub_request(:get, /.*\/readme\.txt/i).to_return(status: 200, body: "Stable Tag: #{version_orig}")
|
||||
stub_request(:get, /.*\/style\.css/i).to_return(status: 200, body: "Version: #{version_orig}")
|
||||
end
|
||||
|
||||
context 'check basic version comparing' do
|
||||
it 'returns true because checked version is newer' do
|
||||
expect(subject.version).to eq version_orig
|
||||
expect(subject.vulnerable_to?(newer)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false because checked version is older' do
|
||||
expect(subject.version).to eq version_orig
|
||||
expect(subject.vulnerable_to?(older)).to be_falsey
|
||||
end
|
||||
|
||||
it 'returns false because checked version is the fixed version' do
|
||||
expect(subject.version).to eq version_orig
|
||||
expect(subject.vulnerable_to?(same)).to be_falsey
|
||||
end
|
||||
|
||||
it 'returns true because no fixed_in version is provided' do
|
||||
expect(subject.version).to eq version_orig
|
||||
expect(subject.vulnerable_to?(no_fixed_info)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'no version found in wp_item' do
|
||||
before do
|
||||
stub_request(:get, /.*\/readme\.(?:txt|md)/i).to_return(status: 404)
|
||||
stub_request(:get, /.*\/style\.css/i).to_return(status: 404)
|
||||
end
|
||||
|
||||
it 'returns true because no version can be detected' do
|
||||
expect(subject.vulnerable_to?(newer)).to be_truthy
|
||||
expect(subject.vulnerable_to?(older)).to be_truthy
|
||||
expect(subject.vulnerable_to?(same)).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,160 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require WPSCAN_LIB_DIR + '/wp_target'
|
||||
|
||||
shared_examples 'WpItems::Detectable' do
|
||||
let(:vulns_file) { fixtures_dir + '/vulns.json' }
|
||||
let(:targets_items_file) { fixtures_dir + '/targets.txt' }
|
||||
let(:wp_content_dir) { 'wp-content' }
|
||||
let(:wp_plugins_dir) { wp_content_dir + '/plugins' }
|
||||
let(:wp_target) { WpTarget.new(url, wp_content_dir: wp_content_dir, wp_plugins_dir: wp_plugins_dir) }
|
||||
let(:url) { 'http://example.com/' }
|
||||
let(:uri) { URI.parse(url) }
|
||||
let(:empty_file) { SPEC_FIXTURES_DIR + '/empty-file' }
|
||||
|
||||
before do
|
||||
if class_vulns_file = subject.vulns_file
|
||||
expect(class_vulns_file).to eq expected[:vulns_file]
|
||||
end
|
||||
|
||||
allow(subject).to receive(:vulns_file).and_return(vulns_file)
|
||||
|
||||
unless subject.item_xpath
|
||||
allow(subject).to receive(:item_xpath).and_return('//item')
|
||||
end
|
||||
end
|
||||
|
||||
describe '::request_params' do
|
||||
it 'returns the default params' do
|
||||
expect(subject.send(:request_params)).to eq expected[:request_params]
|
||||
end
|
||||
end
|
||||
|
||||
describe '::item_class' do
|
||||
it 'returns the correct item class' do
|
||||
klass = subject.send(:item_class)
|
||||
|
||||
expect(klass).to be_a Class
|
||||
expect(klass).to eq item_class
|
||||
end
|
||||
end
|
||||
|
||||
describe '::targets_items' do
|
||||
let(:options) { { type: :all } }
|
||||
|
||||
after do
|
||||
if @expected
|
||||
results = subject.send(:targets_items, wp_target, options)
|
||||
|
||||
expect(results.sort.map { |i| i.name }).to eq @expected.sort.map { |i| i.name }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :type = :vulnerable' do
|
||||
let(:options) { { type: :vulnerable } }
|
||||
|
||||
it 'returns the expected Array of WpItem' do
|
||||
@expected = expected[:vulnerable_targets_items]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::passive_detection' do
|
||||
after do
|
||||
stub_request_to_fixture(url: wp_target.url, fixture: @fixture)
|
||||
|
||||
results = subject.passive_detection(wp_target)
|
||||
|
||||
expect(results).to be_a subject
|
||||
expect(results.map { |i| i.name }).to eq @expected.sort.map { |i| i.name }
|
||||
end
|
||||
|
||||
context 'when the page is empty' do
|
||||
it 'return an empty WpItems' do
|
||||
@fixture = empty_file
|
||||
@expected = subject.new
|
||||
end
|
||||
end
|
||||
|
||||
context 'when items are present' do
|
||||
it 'returns the expected items' do
|
||||
@fixture = fixtures_dir + '/passive_detection.html'
|
||||
@expected = expected[:passive_detection]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::aggressive_detection' do
|
||||
def stub_targets_dont_exist(targets)
|
||||
targets.each { |t| allow(t).to receive(:exists?).and_return(false) }
|
||||
end
|
||||
|
||||
let(:options) { {} }
|
||||
|
||||
after do
|
||||
stub_request(:get, /.*/).to_return(status: 404)
|
||||
|
||||
result = subject.aggressive_detection(wp_target, options)
|
||||
|
||||
expect(result).to be_a subject
|
||||
expect(result.sort.map { |i| i.name }).to eq @expected.sort.map { |i| i.name }
|
||||
end
|
||||
|
||||
context 'when :type = :vulnerable' do
|
||||
let(:options) { { type: :vulnerable } }
|
||||
let(:targets) { expected[:vulnerable_targets_items] }
|
||||
|
||||
it 'only checks and return vulnerable targets' do
|
||||
samples = targets.sample(2)
|
||||
fixed_target = samples[0]
|
||||
vulnerable_target = samples[1]
|
||||
|
||||
stub_targets_dont_exist(targets)
|
||||
|
||||
allow(vulnerable_target).to receive(:exists?).and_return(true)
|
||||
allow(vulnerable_target).to receive(:vulnerable?).and_return(true)
|
||||
|
||||
allow(fixed_target).to receive(:exists?).and_return(true)
|
||||
allow(fixed_target).to receive(:vulnerable?).and_return(false)
|
||||
|
||||
@expected = subject.new << vulnerable_target
|
||||
|
||||
expect(subject).to receive(:targets_items).and_return(targets)
|
||||
end
|
||||
|
||||
context 'when all targets dont exist' do
|
||||
it 'returns an empty WpItems' do
|
||||
stub_targets_dont_exist(targets)
|
||||
expect(subject).to receive(:targets_items).and_return(targets)
|
||||
@expected = subject.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no :type = :vulnerable' do
|
||||
let(:targets) { (expected[:vulnerable_targets_items] + expected[:targets_items_from_file]).uniq { |t| t.name } }
|
||||
|
||||
it 'checks all targets, and merge the results with passive_detection' do
|
||||
target = targets.sample
|
||||
@expected = expected[:passive_detection] << target
|
||||
|
||||
stub_targets_dont_exist(targets)
|
||||
allow(target).to receive(:exists?).and_return(true)
|
||||
|
||||
expect(subject).to receive(:targets_items).and_return(targets)
|
||||
expect(subject).to receive(:passive_detection).and_return(expected[:passive_detection])
|
||||
end
|
||||
|
||||
context 'when all targets dont exist' do
|
||||
it 'returns the result from passive_detection' do
|
||||
@expected = expected[:passive_detection]
|
||||
|
||||
stub_targets_dont_exist(targets)
|
||||
expect(subject).to receive(:targets_items).and_return(targets)
|
||||
expect(subject).to receive(:passive_detection).and_return(@expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpPlugin::Vulnerable' do
|
||||
|
||||
describe '#db_file' do
|
||||
after { expect(subject.db_file).to eq @expected }
|
||||
|
||||
context 'when :db_file is no set' do
|
||||
it 'returns the default one' do
|
||||
@expected = PLUGINS_FILE
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :db_file is already set' do
|
||||
it 'returns it' do
|
||||
@expected = 'test.json'
|
||||
subject.db_file = @expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#identifier' do
|
||||
its(:identifier) { should eq 'plugin-name' }
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,61 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpConfigBackup' do
|
||||
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_config_backup' }
|
||||
let(:config_backup_files) { WpTarget::WpConfigBackup.config_backup_files }
|
||||
|
||||
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 = wp_target.uri.merge(url_encode(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
|
||||
expect(wp_target.config_backup).to be_empty
|
||||
end
|
||||
|
||||
it 'returns an array with 1 backup file' do
|
||||
expected = []
|
||||
|
||||
config_backup_files.sample(1).each do |backup_file|
|
||||
file_url = wp_target.uri.merge(url_encode(backup_file)).to_s
|
||||
expected << file_url
|
||||
|
||||
stub_request_to_fixture(url: file_url, fixture: fixtures_dir + '/wp-config.php')
|
||||
end
|
||||
|
||||
wp_config_backup = wp_target.config_backup
|
||||
expect(wp_config_backup).not_to be_empty
|
||||
expect(wp_config_backup).to be === expected
|
||||
end
|
||||
|
||||
# Is there a way to factorise that one with the previous test ?
|
||||
it 'returns an array with 2 backup file' do
|
||||
expected = []
|
||||
|
||||
config_backup_files.sample(2).each do |backup_file|
|
||||
file_url = wp_target.uri.merge(url_encode(backup_file)).to_s
|
||||
expected << file_url
|
||||
|
||||
stub_request_to_fixture(url: file_url, fixture: fixtures_dir + '/wp-config.php')
|
||||
end
|
||||
|
||||
wp_config_backup = wp_target.config_backup
|
||||
expect(wp_config_backup).not_to be_empty
|
||||
expect(wp_config_backup.sort).to be === expected.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe '#config_backup_files' do
|
||||
it 'does not contain duplicates' do
|
||||
expect(config_backup_files.flatten.uniq.length).to eq config_backup_files.length
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,143 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpCustomDirectories' do
|
||||
|
||||
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(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request
|
||||
stub_request(:get, /.*\.html$/).to_return(:status => 200, :body => '') # 404 hash request
|
||||
|
||||
expect(@wp_target.wp_content_dir).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns 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 "returns 'wp-content'" do
|
||||
@target_url = 'http://lamp/wordpress-3.4.1'
|
||||
@fixture = fixtures_dir + '/wordpress-3.4.1.htm'
|
||||
@expected = 'wp-content'
|
||||
end
|
||||
|
||||
it "returns '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 "returns '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 "returns '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 "returns '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(:get, @wp_target.url).to_return(:status => 200, :body => 'homepage') # homepage request
|
||||
|
||||
expect(@wp_target.default_wp_content_dir_exists?).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns false if wp-content returns an invalid response code' do
|
||||
stub_request(:get, /.*\/wp-content\/?$/).to_return(:status => 404, :body => '') # default dir request
|
||||
stub_request(:get, /.*\.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(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => 'homepage') # default dir request
|
||||
stub_request(:get, /.*\.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(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '404!') # default dir request
|
||||
stub_request(:get, /.*\.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(:get, /.*\/wp-content\/?$/).to_return(:status => 200, :body => '') # default dir request
|
||||
stub_request(:get, /.*\.html$/).to_return(:status => 200, :body => '404!') # 404 hash request
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_plugins_dir' do
|
||||
after :each do
|
||||
expect(@wp_target.wp_plugins_dir).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns 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 "returns 'custom/plugins'" do
|
||||
@wp_target = WpTarget.new('http://example.localhost/', options.merge(wp_content_dir: 'custom', wp_plugins_dir: nil))
|
||||
@expected = 'custom/plugins'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_plugins_dir_exists?' do
|
||||
let(:wp_target) { WpTarget.new('http://example.localhost/', custom_options) }
|
||||
let(:custom_options) { options.merge(wp_content_dir: 'asdf', wp_plugins_dir: 'custom-plugins') }
|
||||
let(:url) { wp_target.uri.merge(wp_target.wp_plugins_dir).to_s }
|
||||
|
||||
it 'returns true' do
|
||||
stub_request(:get, url).to_return(status: 200)
|
||||
expect(wp_target.wp_plugins_dir_exists?).to eq true
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, url).to_return(status: 404)
|
||||
expect(wp_target.wp_plugins_dir_exists?).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,37 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpFullPathDisclosure' do
|
||||
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_full_path_disclosure' }
|
||||
|
||||
describe '#full_path_disclosure_url' do
|
||||
it 'returns http://example.localhost/wp-includes/rss-functions.php' do
|
||||
expect(wp_target.full_path_disclosure_url).to be === 'http://example.localhost/wp-includes/rss-functions.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_full_path_disclosure?' do
|
||||
after do
|
||||
stub_request(:get, wp_target.full_path_disclosure_url).
|
||||
to_return(@stub)
|
||||
|
||||
expect(wp_target.has_full_path_disclosure?).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns false on a 404' do
|
||||
@stub = { status: 404 }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns false if no fpd found (blank page for example)' do
|
||||
@stub = { status: 200, body: '' }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200, body: File.new(fixtures_dir + '/rss-functions-disclosure.php') }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,91 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpLoginProtection' do
|
||||
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_login_protection' }
|
||||
|
||||
before { allow(wp_target).to receive(:wp_plugins_dir).and_return('wp-content/plugins') }
|
||||
|
||||
# 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 = WpTarget::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 wp-login-security_protection.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: 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, wp_target.send(special_plugin_call_url_symbol).to_s).to_return(status: status_code)
|
||||
end
|
||||
|
||||
expect(wp_target.send(@symbol_to_call)).to eql @expected
|
||||
end
|
||||
|
||||
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} returns #{expected}" do
|
||||
@plugin_name = plugin_name_from_fixture
|
||||
@fixture = File.join(fixtures_dir, fixture)
|
||||
@symbol_to_call = symbol_to_call
|
||||
@expected = expected
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#login_protection_plugin' do
|
||||
after :each do
|
||||
stub_request(:get, /.*/).to_return(status: 404)
|
||||
stub_request_to_fixture(url: login_url, fixture: @fixture)
|
||||
|
||||
expect(wp_target.login_protection_plugin).to eq @plugin_expected
|
||||
expect(wp_target.has_login_protection?).to eql @protection_expected
|
||||
end
|
||||
|
||||
it 'returns nil if no protection is present' do
|
||||
@fixture = File.join(fixtures_dir, 'wp-login-clean.php')
|
||||
@plugin_expected = nil
|
||||
@protection_expected = false
|
||||
end
|
||||
|
||||
it 'returns a login-lockdown WpPlugin object' do
|
||||
@fixture = File.join(fixtures_dir, 'wp-login-login_lockdown.php')
|
||||
@plugin_expected = WpPlugin.new(wp_target.uri, name: 'login-lockdown')
|
||||
@protection_expected = true
|
||||
end
|
||||
|
||||
it 'returns a login-lock WpPlugin object' do
|
||||
@fixture = File.join(fixtures_dir, 'wp-login-login_lock.php')
|
||||
@plugin_expected = WpPlugin.new(wp_target.uri, name: 'login-lock')
|
||||
@protection_expected = true
|
||||
end
|
||||
|
||||
it 'returns a security-protection WpPlugin object' do
|
||||
@fixture = File.join(fixtures_dir, 'wp-login-security_protection.php')
|
||||
@plugin_expected = WpPlugin.new(wp_target.uri, name: 'security-protection')
|
||||
@protection_expected = true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpReadme' do
|
||||
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/wp_readme' }
|
||||
|
||||
describe '#readme_url' do
|
||||
it 'returns http://example.localhost/readme.html' do
|
||||
expect(wp_target.readme_url).to be === "#{wp_target.uri}readme.html"
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_readme?' do
|
||||
after do
|
||||
stub_request(:get, wp_target.readme_url).to_return(@stub)
|
||||
|
||||
expect(wp_target.has_readme?).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns false on a 404' do
|
||||
@stub = { status: 404 }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true if it exists' do
|
||||
@stub = { status: 200, body: File.new(fixtures_dir + '/readme-3.2.1.html') }
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'returns true even if the readme.html is not in english' do
|
||||
@stub = { status: 200, body: File.new(fixtures_dir + '/readme-3.3.2-fr.html') }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,96 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTarget::WpRegistrable' do
|
||||
|
||||
let(:signup_url) { wp_target.uri.merge('wp-signup.php').to_s }
|
||||
|
||||
describe '#registration_url' do
|
||||
after { expect(wp_target.registration_url).to be === @expected }
|
||||
|
||||
context 'when multisite' do
|
||||
it 'returns the signup url' do
|
||||
allow(wp_target).to receive(:multisite?).and_return(true)
|
||||
|
||||
@expected = signup_url
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not multisite' do
|
||||
it 'returns the login url with ?action=register' do
|
||||
allow(wp_target).to receive(:multisite?).and_return(false)
|
||||
|
||||
@expected = login_url + '?action=register'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#registration_enabled?' do
|
||||
after do
|
||||
allow(wp_target).to receive(:multisite?).and_return(multisite)
|
||||
stub_request(:get, wp_target.registration_url).to_return(@stub)
|
||||
|
||||
expect(wp_target.registration_enabled?).to be === @expected
|
||||
end
|
||||
|
||||
context 'when multisite' do
|
||||
let(:multisite) { true }
|
||||
it 'returns false' do
|
||||
@stub = { status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' } }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200, body: '<form id="setupform" method="post" action="wp-signup.php">'}
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not multisite' do
|
||||
let(:multisite) { false }
|
||||
|
||||
it 'returns false' do
|
||||
@stub = { status: 302, headers: { 'Location' => 'wp-login.php?registration=disabled' } }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200, body: '<form name="registerform" id="registerform" action="wp-login.php"'}
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@stub = { status: 500 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#multisite?' do
|
||||
after do
|
||||
stub_request(:get, signup_url).to_return(@stub)
|
||||
|
||||
expect(wp_target.multisite?).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@stub = { status: 302, headers: { 'Location' => 'wp-login.php?action=register' } }
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 302, headers: { 'Location' => 'http://example.localhost/wp-signup.php' } }
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200 }
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@stub = { status: 500 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,48 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTheme::Versionable' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_theme/versionable/' }
|
||||
|
||||
describe '#version' do
|
||||
after do
|
||||
if @file
|
||||
body = File.new(fixtures_dir + @file)
|
||||
stub_request(:get, subject.style_url).to_return(status: 200, body: body)
|
||||
end
|
||||
|
||||
expect(subject.version).to eq @expected
|
||||
end
|
||||
|
||||
context 'the version is already set' do
|
||||
it 'returns it' do
|
||||
subject.version = '2.1'
|
||||
@expected = '2.1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the version is not found' do
|
||||
it 'returns nil' do
|
||||
@file = 'twentyeleven-unknow.css'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the stylesheet is inline' do
|
||||
it 'returns the correct version' do
|
||||
@file = 'bueno-1.5.1.css'
|
||||
@expected = '1.5.1'
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the correct version' do
|
||||
@file = 'twentyeleven-1.3.css'
|
||||
@expected = '1.3'
|
||||
end
|
||||
|
||||
it 'returns the correct version' do
|
||||
@file = 'firefart.net.css'
|
||||
@expected = '1.0.0'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTheme::Vulnerable' do
|
||||
|
||||
describe '#db_file' do
|
||||
after { expect(subject.db_file).to eq @expected }
|
||||
|
||||
context 'when :db_file is not set' do
|
||||
it 'returns the default one' do
|
||||
@expected = THEMES_FILE
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :db_file is already set' do
|
||||
it 'returns it' do
|
||||
@expected = 'test.json'
|
||||
subject.db_file = @expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#identifier' do
|
||||
its(:identifier) { should eq 'theme-name' }
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,37 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTimthumb::Existable' do
|
||||
|
||||
describe 'exists_from_response?' do
|
||||
after do
|
||||
response = Typhoeus::Response.new(@resp_opt)
|
||||
expect(subject.send(:exists_from_response?, response)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when the status is not a 400' do
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 200 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the status is a 400' do
|
||||
let(:opt) { { code: 400 } }
|
||||
|
||||
context 'when the body contains "no image specified"' do
|
||||
it 'returns true' do
|
||||
@resp_opt = opt.merge(body: 'The following error(s) occured:<br/>No image specified')
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
it 'returns false' do
|
||||
@resp_opt = opt.merge(body: 'im a fake one, hehe')
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,52 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpTimthumb::Versionable' do
|
||||
|
||||
describe '#version' do
|
||||
after do
|
||||
stub_request(:get, subject.url).to_return(status: 200, body: @body)
|
||||
|
||||
expect(subject.version).to be === @expected
|
||||
end
|
||||
|
||||
context 'when a version is already set' do
|
||||
it 'returns it' do
|
||||
subject.version = '2.3.1'
|
||||
@expected = '2.3.1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body match' do
|
||||
it 'returns the version' do
|
||||
@body = 'Query String :<br />TimThumb version : 2.8.10</pre>'
|
||||
@expected = '2.8.10'
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
it 'returns nil' do
|
||||
@body = 'not in here'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
after { expect(subject.to_s).to eq @expected }
|
||||
|
||||
context 'when there is a version' do
|
||||
it 'returns it with the url' do
|
||||
subject.version = '1.3'
|
||||
@expected = uri.merge(options[:path]).to_s + ' v1.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is not a version' do
|
||||
it 'returns only the url' do
|
||||
allow(subject).to receive(:version).and_return(nil)
|
||||
@expected = uri.merge(options[:path]).to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,139 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpUser::BruteForcable' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_user/brute_forcable' }
|
||||
let(:wordlist_iso) { fixtures_dir + '/wordlist-iso-8859-1.txt' }
|
||||
let(:wordlist_utf8) { fixtures_dir + '/wordlist-utf-8.txt' }
|
||||
let(:redirect_url) { 'http://www.example.com/asdf/' }
|
||||
let(:mod) { WpUser::BruteForcable }
|
||||
|
||||
before { Browser.instance.max_threads = 1 }
|
||||
|
||||
describe '#valid_password?' do
|
||||
let(:response) { Typhoeus::Response.new(resp_options) }
|
||||
let(:resp_options) { {} }
|
||||
|
||||
after do
|
||||
expect(wp_user.valid_password?(response, 'password', redirect_url)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when 302 and valid return_to parameter' do
|
||||
let(:resp_options) { { code: 302, headers: { 'Location' => redirect_url } } }
|
||||
|
||||
it 'returns true' do @expected = true end
|
||||
end
|
||||
|
||||
context 'when 302 and invalid return_to parameter' do
|
||||
let(:resp_options) { { code: 302, headers: { 'Location' => nil } } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
|
||||
context 'when login_error' do
|
||||
let(:resp_options) { { body: '<div id="login_error">' } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
|
||||
context 'when timeout' do
|
||||
let(:resp_options) { { return_code: :operation_timedout } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
|
||||
context 'when no response from server (status = 0)' do
|
||||
let(:resp_options) { { code: 0 } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
|
||||
context 'when error 50x' do
|
||||
let(:resp_options) { { code: 500 } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
|
||||
context 'when unknown response' do
|
||||
let(:resp_options) { { code: 202 } }
|
||||
|
||||
it 'returns false' do @expected = false end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO
|
||||
describe '#login_request' do
|
||||
|
||||
end
|
||||
|
||||
describe '#brute_force' do
|
||||
let(:login) { 'someuser' }
|
||||
let(:login_url) { uri.merge('wp-login.php').to_s }
|
||||
|
||||
after do
|
||||
[wordlist_utf8, wordlist_iso].each do |wordlist|
|
||||
wp_user.login = login
|
||||
wp_user.brute_force(wordlist, {}, redirect_url)
|
||||
expect(wp_user.password).to eq @expected
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no password is valid' do
|
||||
before do
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).
|
||||
# with(body: { log: login }). # produces an error : undefined method `split' for {:log=>"someuser", :pwd=>"password1"}:Hash
|
||||
# Fixed in WebMock 1.17.2, TODO: Modify the specs
|
||||
to_return(body: 'login_error')
|
||||
end
|
||||
|
||||
it 'does not set @password' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no redirect_url is given' do
|
||||
let(:redirect_url) { nil }
|
||||
|
||||
before do
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => 'wrong-location' })
|
||||
end
|
||||
|
||||
it 'does not set the @password' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a password is valid' do
|
||||
# Due to the error with .with(body: { log: login }) above
|
||||
# We can't use it to stub the request for a specific password
|
||||
# So, the first one will be valid
|
||||
# Fixed in WebMock 1.17.2, TODO: Modify the specs
|
||||
|
||||
before do
|
||||
stub_request(:get, login_url).to_return(status: 200)
|
||||
stub_request(:post, wp_user.login_url).to_return(status: 302, headers: { 'Location' => redirect_url })
|
||||
end
|
||||
|
||||
it 'sets the @password' do
|
||||
@expected = 'password1'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the login url is redirected to https' do
|
||||
let(:https_login_url) { 'https://example.com/wp-login.php' }
|
||||
|
||||
before do
|
||||
stub_request(:any, uri.merge('wp-login.php').to_s).to_return(status: 302, headers: { 'Location' => https_login_url})
|
||||
stub_request(:get, https_login_url).to_return(status: 200)
|
||||
stub_request(:post, https_login_url).with(body: hash_including({ log: 'someuser', pwd: 'root'})).to_return(status: 302, headers: { 'Location' => redirect_url })
|
||||
stub_request(:post, https_login_url).with(body: /pwd=(?!root)/).to_return(body: 'login_error')
|
||||
end
|
||||
|
||||
it 'does not raise any error' do
|
||||
@expected = 'root'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,202 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpUser::Existable' do
|
||||
let(:mod) { WpUser::Existable }
|
||||
let(:fixtures_dir) { File.join(MODELS_FIXTURES, 'wp_user', 'existable') }
|
||||
|
||||
describe '::login_from_author_pattern' do
|
||||
after do
|
||||
expect(mod.login_from_author_pattern(@text)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when no trailing slash' do
|
||||
it 'returns the correct login' do
|
||||
@text = '/aurhor/neo'
|
||||
@expeced = 'neo'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when trailing slash' do
|
||||
it 'returns the correct login' do
|
||||
@text = '/author/admin/'
|
||||
@expected = 'admin'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pattern not found' do
|
||||
it 'returns nil' do
|
||||
@text = 'im not from this world'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no author given' do
|
||||
it 'returns nil' do
|
||||
@text = '<a href="http://wp.lab/author/" class="btn btn-default">See Posts</a>'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::login_from_body' do
|
||||
after { expect(mod.login_from_body(body)).to eq @expected }
|
||||
|
||||
context 'when the author pattern is in the body' do
|
||||
let(:body) { '/author/admin' }
|
||||
|
||||
it 'returns it' do
|
||||
allow(mod).to receive(:login_from_body).with(body).and_return('admin')
|
||||
@expected = 'admin'
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
let(:body) { '<body class="archive author author-user2 author-1 custom-font-enabled single-author">' }
|
||||
|
||||
it 'gets the login from the body class' do
|
||||
@expected = 'user2'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::display_name_from_body' do
|
||||
after { expect(mod.display_name_from_body(@body)).to eq @expected }
|
||||
|
||||
context 'when pattern not found' do
|
||||
it 'returns nil' do
|
||||
@body = 'im not there'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the title tag is empty' do
|
||||
it 'returns nil' do
|
||||
@body = '<title></title>'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the body is an ASCII-8BIT' do
|
||||
it 'return the correct display_name' do
|
||||
@body = '<title>its me | wordpress</title>'.encode('ASCII-8BIT')
|
||||
@expected = 'its me'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when pattern is found' do
|
||||
context 'when unencoded extra chars' do
|
||||
it 'returns the display_name w/o extra chars' do
|
||||
@body = '<title>admin display | Wordpress-3.5.1</title>'
|
||||
@expected = 'admin display'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when encoded extra chars' do
|
||||
it 'returns the display_name w/o extra chars' do
|
||||
@body = '<title>user user | Wordpress-3.5.1</title>'
|
||||
@expected = 'user user'
|
||||
end
|
||||
|
||||
context 'when custom extra chars' do
|
||||
it 'detects them' do
|
||||
@body = '<title>admin « Wiener</title>'
|
||||
@expected = 'admin'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'decodes entities' do
|
||||
@body = '<title>user & nickname | Wordpress-3.5.1</title>'
|
||||
@expected = 'user & nickname'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load_from_response' do
|
||||
after do
|
||||
response = Typhoeus::Response.new(@resp_opt || resp_opt)
|
||||
subject.send(:load_from_response, response)
|
||||
|
||||
expect(subject.login).to eq @login
|
||||
expect(subject.display_name).to eq @display_name
|
||||
end
|
||||
|
||||
context 'with a 301' do
|
||||
let(:location) { 'http://lamp/wordpress-3.5.1/author/admin/' }
|
||||
let(:resp_opt) { { code: 301, headers: { 'Location' => location } } }
|
||||
|
||||
it 'loads the correct values' do
|
||||
stub_request(:get, location).to_return(body: '<title>admin name | wp</title>')
|
||||
|
||||
@login = 'admin'
|
||||
@display_name = 'admin name'
|
||||
end
|
||||
|
||||
context 'when the location is nil' do
|
||||
let(:location) { nil }
|
||||
|
||||
it 'returns nil' do
|
||||
@login = nil
|
||||
@display_name = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the location is empty' do
|
||||
let(:location) { '' }
|
||||
|
||||
it 'returns nil' do
|
||||
@login = nil
|
||||
@display_name = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a 200' do
|
||||
let(:resp_opt) { { code: 200, body: File.read(File.join(fixtures_dir, 'admin.html')) } }
|
||||
|
||||
it 'loads the correct values' do
|
||||
@login = 'admin'
|
||||
@display_name = 'admin d-name'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when chinese chars' do
|
||||
let(:resp_opt) { { code: 200, body: File.read(File.join(fixtures_dir, 'chinese_chars.html')) } }
|
||||
|
||||
it 'loads the correct values' do
|
||||
@login = '一路疯下去'
|
||||
@display_name = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
it 'does not do anything' do
|
||||
@resp_opt = { code: 404 }
|
||||
@login = nil
|
||||
@display_name = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#exists_from_response?' do
|
||||
after do
|
||||
response = Typhoeus::Response.new(@resp_opt || resp_opt)
|
||||
expect(subject.exists_from_response?(response)).to eq @expected
|
||||
end
|
||||
|
||||
context 'login not found' do
|
||||
it 'returns false' do
|
||||
@resp_opt = { code: 404 }
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'login found' do
|
||||
it 'returns true' do
|
||||
@resp_opt = { code: 200, body: File.new(fixtures_dir + '/admin.html').read }
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,22 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpUsers::BruteForcable' do
|
||||
|
||||
describe '#brute_force' do
|
||||
let(:range) { (1..10) }
|
||||
let(:wordlist) { 'somefile.txt'}
|
||||
let(:brute_force_opt) { {} }
|
||||
|
||||
it 'calls #brute_force on each wp_user' do
|
||||
range.each do |id|
|
||||
wp_user = WpUser.new(uri, id: id)
|
||||
expect(wp_user).to receive(:brute_force).with(wordlist, brute_force_opt)
|
||||
|
||||
wp_users << wp_user
|
||||
end
|
||||
|
||||
wp_users.brute_force(wordlist, brute_force_opt)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
shared_examples 'WpVersion::Vulnerable' do
|
||||
|
||||
describe '#db_file' do
|
||||
after { expect(subject.db_file).to eq @expected }
|
||||
|
||||
context 'when :db_file is no set' do
|
||||
it 'returns the default one' do
|
||||
@expected = WORDPRESSES_FILE
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the :db_file is already set' do
|
||||
it 'returns it' do
|
||||
@expected = 'test.json'
|
||||
subject.db_file = @expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#identifier' do
|
||||
its(:identifier) { should eq '1.2' }
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user