So long hombre
This commit is contained in:
@@ -1,264 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Browser do
|
||||
it_behaves_like 'Browser::Actions'
|
||||
it_behaves_like 'Browser::Options'
|
||||
|
||||
CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf.json'
|
||||
CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy.json'
|
||||
#CONFIG_FILE_WITH_PROXY_AND_AUTH = SPEC_FIXTURES_CONF_DIR + '/browser.conf_proxy_auth.json'
|
||||
|
||||
subject(:browser) {
|
||||
Browser.reset
|
||||
Browser.instance(options)
|
||||
}
|
||||
let(:options) { {} }
|
||||
let(:instance_vars_to_check) {
|
||||
['proxy', 'max_threads', 'cache_ttl', 'request_timeout', 'connect_timeout']
|
||||
}
|
||||
let(:json_config_without_proxy) { JSON.parse(File.read(CONFIG_FILE_WITHOUT_PROXY)) }
|
||||
let(:json_config_with_proxy) { JSON.parse(File.read(CONFIG_FILE_WITH_PROXY)) }
|
||||
|
||||
def check_instance_variables(browser, json_expected_vars)
|
||||
json_expected_vars['max_threads'] ||= 20 # max_thread can not be nil
|
||||
|
||||
instance_vars_to_check.each do |variable_name|
|
||||
expect(browser.send(:"#{variable_name}")).to be === json_expected_vars[variable_name]
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Singleton' do
|
||||
it 'should not allow #new' do
|
||||
expect { Browser.new }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '::instance' do
|
||||
after { check_instance_variables(browser, @json_expected_vars) }
|
||||
|
||||
context "when :config_file = #{CONFIG_FILE_WITH_PROXY}" do
|
||||
let(:options) { { config_file: CONFIG_FILE_WITH_PROXY } }
|
||||
|
||||
it 'will check the instance vars' do
|
||||
@json_expected_vars = json_config_with_proxy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when options[:cache_dir]' do
|
||||
let(:cache_dir) { CACHE_DIR + '/somewhere' }
|
||||
let(:options) { { cache_dir: cache_dir } }
|
||||
|
||||
after { expect(subject.cache_dir).to eq cache_dir }
|
||||
|
||||
it 'sets @cache_dir' do
|
||||
@json_expected_vars = json_config_without_proxy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load_config' do
|
||||
context 'when config_file is a symlink' do
|
||||
let(:config_file) { './rspec_symlink' }
|
||||
|
||||
it 'raises an error' do
|
||||
File.symlink('./testfile', config_file)
|
||||
expect { browser.load_config(config_file) }.to raise_error('[ERROR] Config file is a symlink.')
|
||||
File.unlink(config_file)
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
after do
|
||||
browser.load_config(@config_file)
|
||||
check_instance_variables(browser, @expected)
|
||||
end
|
||||
|
||||
it 'sets the correct variables' do
|
||||
@config_file = CONFIG_FILE_WITH_PROXY
|
||||
@expected = json_config_without_proxy.merge(json_config_with_proxy)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::append_params_header_field' do
|
||||
after :each do
|
||||
expect(Browser.append_params_header_field(
|
||||
@params,
|
||||
@field,
|
||||
@field_value
|
||||
)).to be === @expected
|
||||
end
|
||||
|
||||
context 'when there is no headers' do
|
||||
it 'create the header and set the field' do
|
||||
@params = { somekey: 'somevalue' }
|
||||
@field = 'User-Agent'
|
||||
@field_value = 'FakeOne'
|
||||
@expected = { somekey: 'somevalue', headers: { 'User-Agent' => 'FakeOne' } }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are headers' do
|
||||
context 'when the field already exists' do
|
||||
it 'does not replace it' do
|
||||
@params = { somekey: 'somevalue', headers: { 'Location' => 'SomeLocation' } }
|
||||
@field = 'Location'
|
||||
@field_value = 'AnotherLocation'
|
||||
@expected = @params
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the field is not present' do
|
||||
it 'sets the field' do
|
||||
@params = { somekey: 'somevalue', headers: { 'Auth' => 'user:pass' } }
|
||||
@field = 'UA'
|
||||
@field_value = 'FF'
|
||||
@expected = { somekey: 'somevalue', headers: { 'Auth' => 'user:pass', 'UA' => 'FF' } }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge_request_params' do
|
||||
let(:params) { {} }
|
||||
let(:cookie_jar) { CACHE_DIR + '/browser/cookie-jar' }
|
||||
let(:user_agent) { 'SomeUA' }
|
||||
let(:default_expectation) {
|
||||
{
|
||||
cache_ttl: 250,
|
||||
cookiejar: cookie_jar, cookiefile: cookie_jar,
|
||||
timeout: 60, connecttimeout: 10,
|
||||
maxredirs: 3,
|
||||
referer: nil
|
||||
}
|
||||
}
|
||||
|
||||
after :each do
|
||||
browser.user_agent = user_agent
|
||||
browser.cache_ttl = 250
|
||||
|
||||
expect(browser.merge_request_params(params)).to eq @expected
|
||||
expect(Typhoeus::Config.user_agent).to eq user_agent
|
||||
end
|
||||
|
||||
it 'sets the User-Agent header field and cache_ttl' do
|
||||
@expected = default_expectation
|
||||
end
|
||||
|
||||
context 'when @user_agent' do
|
||||
let(:user_agent) { 'test' }
|
||||
|
||||
it 'sets the User-Agent' do
|
||||
@expected = default_expectation
|
||||
end
|
||||
end
|
||||
|
||||
context 'when @proxy' do
|
||||
let(:proxy) { '127.0.0.1:9050' }
|
||||
let(:proxy_expectation) { default_expectation.merge(proxy: proxy) }
|
||||
|
||||
it 'merges the proxy' do
|
||||
browser.proxy = proxy
|
||||
@expected = proxy_expectation
|
||||
end
|
||||
|
||||
context 'when @proxy_auth' do
|
||||
it 'sets the proxy_auth' do
|
||||
browser.proxy = proxy
|
||||
browser.proxy_auth = 'user:pass'
|
||||
@expected = proxy_expectation.merge(proxyuserpwd: 'user:pass')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when @request_timeout' do
|
||||
it 'gives an Integer' do
|
||||
browser.request_timeout = '10'
|
||||
|
||||
@expected = default_expectation.merge(timeout: 10)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when @basic_auth' do
|
||||
it 'appends the basic_auth' do
|
||||
browser.basic_auth = 'user:pass'
|
||||
@expected = default_expectation.merge(
|
||||
headers: { 'Authorization' => 'Basic ' + Base64.encode64('user:pass').chomp }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the cache_ttl is alreday set' do
|
||||
let(:params) { { cache_ttl: 500 } }
|
||||
|
||||
it 'does not override it' do
|
||||
@expected = default_expectation.merge(params)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the maxredirs is alreday set' do
|
||||
let(:params) { { maxredirs: 100 } }
|
||||
|
||||
it 'does not override it' do
|
||||
@expected = default_expectation.merge(params)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when @cookie' do
|
||||
let(:cookie) { 'foor=bar;bar=foo' }
|
||||
before { browser.cookie = cookie }
|
||||
|
||||
it 'sets the cookie' do
|
||||
@expected = default_expectation.merge(cookie: cookie)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when @disable_tls_checks' do
|
||||
it 'disables tls checks' do
|
||||
browser.disable_tls_checks = true
|
||||
@expected = default_expectation.merge(ssl_verifypeer: 0, ssl_verifyhost: 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#forge_request' do
|
||||
let(:url) { 'http://example.localhost' }
|
||||
|
||||
it 'returns the correct Typhoeus::Request' do
|
||||
allow(subject).to receive_messages(merge_request_params: { cache_ttl: 10 })
|
||||
|
||||
request = subject.forge_request(url)
|
||||
expect(request).to be_a Typhoeus::Request
|
||||
expect(request.url).to eq url
|
||||
expect(request.cache_ttl).to eq 10
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'testing caching' do
|
||||
it 'should only do 1 request, and retrieve the other one from the cache' do
|
||||
|
||||
url = 'http://example.localhost'
|
||||
|
||||
stub_request(:get, url).to_return(status: 200, body: 'Hello World !')
|
||||
|
||||
response1 = Browser.get(url)
|
||||
response2 = Browser.get(url)
|
||||
|
||||
expect(response1.body).to eq response2.body
|
||||
#WebMock.should have_requested(:get, url).times(1) # This one fail, dunno why :s (but it works without mock)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'testing UTF8' do
|
||||
it 'should not throw an encoding exception' do
|
||||
url = SPEC_FIXTURES_DIR + '/utf8.html'
|
||||
stub_request(:get, url).to_return(status: 200, body: File.read(url))
|
||||
|
||||
response = Browser.get(url)
|
||||
expect { response.body }.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,102 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe CacheFileStore do
|
||||
let(:cache_dir) { SPEC_CACHE_DIR + '/cache_file_store' }
|
||||
|
||||
before :each do
|
||||
Dir.delete(cache_dir) rescue nil
|
||||
|
||||
@cache = CacheFileStore.new(cache_dir)
|
||||
end
|
||||
|
||||
after :each do
|
||||
@cache.clean
|
||||
end
|
||||
|
||||
describe '#storage_path' do
|
||||
it 'returns the storage path given in the #new' do
|
||||
expect(@cache.storage_path).to match(/#{cache_dir}/)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#serializer' do
|
||||
it 'should return the default serializer : Marshal' do
|
||||
expect(@cache.serializer).to eq Marshal
|
||||
expect(@cache.serializer).not_to eq YAML
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clean' do
|
||||
it "should remove all files from the cache dir (#{@cache_dir}" do
|
||||
# clean is executed by other tests before
|
||||
before = count_files_in_dir(@cache.cache_dir)
|
||||
test_dir = File.expand_path("#{@cache.cache_dir}/test")
|
||||
Dir.mkdir test_dir
|
||||
#change the modification date
|
||||
%x[ touch -t 200701310846.26 #{test_dir} ]
|
||||
expect(count_files_in_dir(@cache.cache_dir)).to eq (before + 1)
|
||||
@cache.clean
|
||||
expect(count_files_in_dir(@cache.cache_dir)).to eq before
|
||||
end
|
||||
end
|
||||
|
||||
describe '#read_entry' do
|
||||
after { expect(@cache.read_entry(key)).to eq @expected }
|
||||
|
||||
context 'when the entry does not exist' do
|
||||
let(:key) { Digest::SHA1.hexdigest('hello world') }
|
||||
|
||||
it 'should return nil' do
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the file exist but is empty (marshal data too short error)' do
|
||||
let(:key) { 'empty-file' }
|
||||
|
||||
it 'returns nil' do
|
||||
File.new(File.join(@cache.storage_path, key), File::CREAT)
|
||||
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#write_entry, #read_entry' do
|
||||
|
||||
after :each do
|
||||
@cache.write_entry(@key, @data, @timeout)
|
||||
expect(@cache.read_entry(@key)).to be === @expected
|
||||
end
|
||||
|
||||
it 'should get the correct entry (string)' do
|
||||
@timeout = 10
|
||||
@key = 'some_key'
|
||||
@data = 'Hello World !'
|
||||
@expected = @data
|
||||
end
|
||||
|
||||
it 'should not write the entry' do
|
||||
@timeout = 0
|
||||
@key = 'another_key'
|
||||
@data = 'Another Hello World !'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
## TODO write / read for an object
|
||||
end
|
||||
|
||||
describe '#storage_dir' do
|
||||
it 'should create a unique storage dir' do
|
||||
storage_dirs = []
|
||||
|
||||
(1..5).each do |_|
|
||||
storage_dirs << CacheFileStore.new(cache_dir).storage_path
|
||||
end
|
||||
|
||||
expect(storage_dirs.uniq.size).to eq 5
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,25 +0,0 @@
|
||||
#encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpItems do
|
||||
it_behaves_like 'WpItems::Detectable' do
|
||||
subject(:wp_items) { WpItems }
|
||||
let(:item_class) { WpItem }
|
||||
let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_items/detectable' }
|
||||
|
||||
let(:expected) do
|
||||
{
|
||||
request_params: { cache_ttl: 0, followlocation: true },
|
||||
targets_items_from_file: [ WpItem.new(uri, name: 'item1'),
|
||||
WpItem.new(uri, name: 'item-2'),
|
||||
WpItem.new(uri, name: 'mr-smith')],
|
||||
|
||||
vulnerable_targets_items: [ WpItem.new(uri, name: 'mr-smith'),
|
||||
WpItem.new(uri, name: 'neo')],
|
||||
|
||||
passive_detection: (1..15).reduce(WpItems.new) { |o, i| o << WpItem.new(uri, name: "detect-me-#{i}") }
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,116 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
require WPSCAN_LIB_DIR + '/wp_target'
|
||||
|
||||
describe 'WpPlugins::Detectable' do
|
||||
subject(:wp_plugins) { WpPlugins }
|
||||
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) }
|
||||
|
||||
describe '::from_header' do
|
||||
context 'when no header' do
|
||||
it 'returns an empty WpPlugins' do
|
||||
stub_request(:get, url).to_return(status: 200)
|
||||
expect(subject.send(:from_header, wp_target)).to eq subject.new
|
||||
end
|
||||
end
|
||||
|
||||
context 'when headers' do
|
||||
let(:headers) { { } }
|
||||
let(:expected) { subject.new(wp_target) }
|
||||
|
||||
after :each do
|
||||
stub_request(:get, url).to_return(status: 200, headers: headers, body: '')
|
||||
expect(subject.send(:from_header, wp_target)).to eq expected
|
||||
end
|
||||
|
||||
context 'when w3-total-cache detected' do
|
||||
it 'returns the w3-total-cache' do
|
||||
headers['X-Powered-BY'] = 'W3 Total Cache/0.9'
|
||||
expected.add('w3-total-cache', version: '0.9')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when wp-super-cache detected' do
|
||||
it 'returns the wp-super-cache' do
|
||||
headers['WP-Super-Cache'] = 'Served supercache file from PHP'
|
||||
expected.add('wp-super-cache')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a header key with mutiple values' do
|
||||
let(:headers) { { 'X-Powered-BY' => ['PHP/5.4.9', 'ASP.NET'] } }
|
||||
|
||||
context 'when no cache plugin' do
|
||||
it 'returns an empty WpPlugins' do
|
||||
# Handled
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a cache plugin' do
|
||||
it 'returns the correct plugin' do
|
||||
headers['X-Powered-BY'] << 'W3 Total Cache/0.9.2.5'
|
||||
|
||||
expected.add('w3-total-cache', version: '0.9.2.5')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::from_content' do
|
||||
context 'when no body' do
|
||||
it 'returns an empty WpPlugins' do
|
||||
stub_request(:get, url).to_return(status: 200, body: '')
|
||||
expect(subject.send(:from_content, wp_target)).to eq subject.new
|
||||
end
|
||||
end
|
||||
|
||||
context 'when body' do
|
||||
@body = ''
|
||||
let(:expected) { subject.new(wp_target) }
|
||||
|
||||
after :each do
|
||||
stub_request(:get, url).to_return(status: 200, body: @body)
|
||||
stub_request(:get, /readme\.txt/i).to_return(status: 404)
|
||||
expect(subject.send(:from_content, wp_target)).to eq expected
|
||||
end
|
||||
|
||||
context 'when w3 total cache detected' do
|
||||
it 'returns the w3-total-cache' do
|
||||
@body = 'w3 total cache'
|
||||
expected.add('w3-total-cache')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when wp-super-cache detected' do
|
||||
it 'returns the wp-super-cache' do
|
||||
@body = 'wp-super-cache'
|
||||
expected.add('wp-super-cache')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all-in-one-seo-pack detected' do
|
||||
it 'returns the all-in-one-seo-pack' do
|
||||
@body = '<!-- All in One SEO Pack 2.0.3.1 by Michael Torbert of Semper Fi Web Design[300,342] -->'
|
||||
expected.add('all-in-one-seo-pack', version: '2.0.3.1')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when google-universal-analytics detected' do
|
||||
it 'returns google-universal-analytics' do
|
||||
@body = '<!-- Google Universal Analytics for WordPress v2.4.2 -->'
|
||||
expected.add('google-universal-analytics', version: '2.4.2')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::passive_detection' do
|
||||
# TODO
|
||||
end
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
#encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpPlugins do
|
||||
it_behaves_like 'WpItems::Detectable' do
|
||||
subject(:wp_plugins) { WpPlugins }
|
||||
let(:item_class) { WpPlugin }
|
||||
let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_plugins/detectable' }
|
||||
|
||||
let(:expected) do
|
||||
{
|
||||
request_params: { cache_ttl: 0, followlocation: true },
|
||||
vulns_file: PLUGINS_FILE,
|
||||
targets_items_from_file: [ WpPlugin.new(uri, name: 'plugin1'),
|
||||
WpPlugin.new(uri, name:'plugin-2'),
|
||||
WpPlugin.new(uri, name: 'mr-smith')],
|
||||
|
||||
vulnerable_targets_items: [ WpPlugin.new(uri, name: 'mr-smith'),
|
||||
WpPlugin.new(uri, name: 'neo')],
|
||||
|
||||
passive_detection: WpPlugins.new << WpPlugin.new(uri, name: 'escaped-url') <<
|
||||
WpPlugin.new(uri, name: 'link-tag') <<
|
||||
WpPlugin.new(uri, name: 'script-tag') <<
|
||||
WpPlugin.new(uri, name: 'style-tag') <<
|
||||
WpPlugin.new(uri, name: 'style-tag-import')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,31 +0,0 @@
|
||||
#encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpThemes do
|
||||
before { stub_request(:get, /.+\/style.css$/).to_return(status: 200) }
|
||||
|
||||
it_behaves_like 'WpItems::Detectable' do
|
||||
subject(:wp_themes) { WpThemes }
|
||||
let(:item_class) { WpTheme }
|
||||
let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_themes/detectable' }
|
||||
|
||||
let(:expected) do
|
||||
{
|
||||
request_params: { cache_ttl: 0, followlocation: true },
|
||||
vulns_file: THEMES_FILE,
|
||||
targets_items_from_file: [ WpTheme.new(uri, name: '3colours'),
|
||||
WpTheme.new(uri, name:'42k'),
|
||||
WpTheme.new(uri, name: 'a-ri')],
|
||||
|
||||
vulnerable_targets_items: [ WpTheme.new(uri, name: 'shopperpress'),
|
||||
WpTheme.new(uri, name: 'webfolio')],
|
||||
|
||||
passive_detection: WpThemes.new << WpTheme.new(uri, name: 'theme1') <<
|
||||
WpTheme.new(uri, name: 'theme 2') <<
|
||||
WpTheme.new(uri, name: 'theme-3') <<
|
||||
WpTheme.new(uri, name: 'style-tag-import')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,123 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
require WPSCAN_LIB_DIR + '/wp_target'
|
||||
|
||||
describe 'WpTimthumbs::Detectable' do
|
||||
subject(:wp_timthumbs) { WpTimthumbs }
|
||||
let(:fixtures_dir) { COLLECTIONS_FIXTURES + '/wp_timthumbs/detectable' }
|
||||
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' }
|
||||
|
||||
let(:expected) do
|
||||
{
|
||||
targets_from_file: [WpTimthumb.new(uri, path: 'timthumb.php'),
|
||||
WpTimthumb.new(uri, path: '$wp-content$/timthumb.php'),
|
||||
WpTimthumb.new(uri, path: '$wp-plugins$/a-gallery/timthumb.php'),
|
||||
WpTimthumb.new(uri, path: '$wp-content$/themes/theme-name/timthumb.php')]
|
||||
|
||||
}
|
||||
end
|
||||
|
||||
def expected_targets_from_theme(theme_name)
|
||||
expected = []
|
||||
%w(
|
||||
timthumb.php lib/timthumb.php inc/timthumb.php includes/timthumb.php
|
||||
scripts/timthumb.php tools/timthumb.php functions/timthumb.php thumb.php
|
||||
).each do |file|
|
||||
path = "$wp-content$/themes/#{theme_name}/#{file}"
|
||||
expected << WpTimthumb.new(uri, path: path)
|
||||
end
|
||||
expected
|
||||
end
|
||||
|
||||
describe '::passive_detection' do
|
||||
it 'returns an empty WpTimthumbs' do
|
||||
expect(subject.passive_detection(wp_target)).to eq subject.new
|
||||
end
|
||||
end
|
||||
|
||||
describe '::targets_items_from_file' do
|
||||
after do
|
||||
targets = subject.send(:targets_items_from_file, file, wp_target)
|
||||
|
||||
expect(targets.map(&:url)).to eq @expected.map(&:url)
|
||||
end
|
||||
|
||||
context 'when an empty file' do
|
||||
let(:file) { empty_file }
|
||||
|
||||
it 'returns an empty Array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a non empty file' do
|
||||
let(:file) { targets_items_file }
|
||||
|
||||
it 'returns the correct Array of WpTimthumb' do
|
||||
@expected = expected[:targets_from_file]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::theme_timthumbs' do
|
||||
it 'returns the correct Array of WpTimthumb' do
|
||||
theme = 'hello-world'
|
||||
targets = subject.send(:theme_timthumbs, theme, wp_target)
|
||||
|
||||
expect(targets.map(&:url)).to eq expected_targets_from_theme(theme).map(&:url)
|
||||
end
|
||||
end
|
||||
|
||||
describe '::targets_items' do
|
||||
let(:options) { {} }
|
||||
|
||||
after do
|
||||
targets = subject.send(:targets_items, wp_target, options)
|
||||
|
||||
expect(targets.map(&:url)).to match_array(@expected.map(&:url))
|
||||
end
|
||||
|
||||
context 'when no :theme_name' do
|
||||
context 'when no :file' do
|
||||
it 'returns an empty Array' do
|
||||
@expected = []
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :file' do
|
||||
let(:options) { { file: targets_items_file } }
|
||||
|
||||
it 'returns the targets from the file' do
|
||||
@expected = expected[:targets_from_file]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :theme_name' do
|
||||
let(:theme) { 'theme-name' }
|
||||
|
||||
context 'when no :file' do
|
||||
let(:options) { { theme_name: theme } }
|
||||
|
||||
it 'returns targets from the theme' do
|
||||
@expected = expected_targets_from_theme(theme)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :file' do
|
||||
let(:options) { { theme_name: theme, file: targets_items_file } }
|
||||
|
||||
it 'returns merged targets from theme and file' do
|
||||
@expected = (expected_targets_from_theme('theme-name') + expected[:targets_from_file]).uniq { |i| i.url }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,59 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
require WPSCAN_LIB_DIR + '/wp_target'
|
||||
|
||||
describe 'WpUsers::Detectable' do
|
||||
subject(:wp_users) { WpUsers }
|
||||
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) }
|
||||
|
||||
def create_from_range(range)
|
||||
result = []
|
||||
|
||||
range.each do |current_id|
|
||||
result << WpUser.new(uri, id: current_id)
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
describe '::request_params' do
|
||||
it 'return an empty Hash' do
|
||||
expect(subject.request_params).to be === {}
|
||||
end
|
||||
end
|
||||
|
||||
describe '::passive_detection' do
|
||||
it 'return an empty WpUsers' do
|
||||
expect(subject.passive_detection(wp_target)).to eq subject.new
|
||||
end
|
||||
end
|
||||
|
||||
describe '::targets_items' do
|
||||
after do
|
||||
targets = subject.send(:targets_items, wp_target, options)
|
||||
|
||||
expect(targets).to eq @expected
|
||||
end
|
||||
|
||||
context 'when no :range' do
|
||||
let(:options) { {} }
|
||||
|
||||
it 'returns Array<WpUser> with id from 1 to 10' do
|
||||
@expected = create_from_range((1..10))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :range' do
|
||||
let(:options) { { range: (1..2) } }
|
||||
|
||||
it 'returns Array<WpUser> with id from 1 to 2' do
|
||||
@expected = create_from_range((1..2))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,86 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'WpUsers::Output' do
|
||||
subject(:wp_users) { WpUsers.new(0) }
|
||||
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) }
|
||||
|
||||
describe '#remove_junk_from_display_names' do
|
||||
it 'does not throw an exception' do
|
||||
expect { subject.remove_junk_from_display_names }.to_not raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_junk_from_display_names' do
|
||||
before :each do
|
||||
@input = WpUsers.new(0)
|
||||
end
|
||||
|
||||
after :each do
|
||||
subject.push(@input)
|
||||
subject.flatten!
|
||||
subject.remove_junk_from_display_names
|
||||
expect(subject).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns an empty array' do
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'returns input object' do
|
||||
@input.push(WpUser.new(nil))
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'returns input object' do
|
||||
@input.push(WpUser.new(''))
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should remove asdf' do
|
||||
@input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdf'))
|
||||
@input.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd asdf'))
|
||||
@expected = WpUsers.new(0)
|
||||
@expected.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh'))
|
||||
@expected.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd'))
|
||||
end
|
||||
|
||||
it 'returns unmodified input object' do
|
||||
@input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdfa'))
|
||||
@input.push(WpUser.new('', login: '', id: 2, display_name: 'ijrjd asdf'))
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'returns input object' do
|
||||
@input.push(WpUser.new('', login: '', id: 1, display_name: 'lkjh asdf'))
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'returns an empty display_name' do
|
||||
@input.push(WpUser.new('', login: '', id: 1, display_name: 'lkhj asdf'))
|
||||
@input.push(WpUser.new('', login: '', id: 2, display_name: 'lkhj asdf'))
|
||||
@expected = WpUsers.new(0)
|
||||
@expected.push(WpUser.new('', login: '', id: 1, display_name: ''))
|
||||
@expected.push(WpUser.new('', login: '', id: 2, display_name: ''))
|
||||
end
|
||||
|
||||
context 'when a user has no display_name' do
|
||||
it 'returns an empty display_name' do
|
||||
@input.push(WpUser.new('', login: '', id: 1, display_name: 'lkhj asdf'))
|
||||
@input.push(WpUser.new('', login: '', id: 2, display_name: 'lkhj asdf'))
|
||||
@input.push(WpUser.new('', login: '', id: 3))
|
||||
|
||||
@expected = WpUsers.new(0)
|
||||
|
||||
(1..3).each do |id|
|
||||
@expected.push(WpUser.new('', login: '', id: id, display_name: ''))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpUsers do
|
||||
it_behaves_like 'WpUsers::BruteForcable'
|
||||
|
||||
subject(:wp_users) { WpUsers.new }
|
||||
let(:url) { 'http://example.com/' }
|
||||
let(:uri) { URI.parse(url) }
|
||||
end
|
||||
@@ -1,170 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'common_helper' do
|
||||
describe '#get_equal_string' do
|
||||
after :each do
|
||||
output = get_equal_string_end(@input)
|
||||
|
||||
expect(output).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = %w()
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = []
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = ['asdf', nil]
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = [nil, 'asdf']
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns asdf' do
|
||||
@input = [nil, 'a asdf', nil, 'b asdf']
|
||||
@expected = ' asdf'
|
||||
end
|
||||
|
||||
it 'returns asdf' do
|
||||
@input = ['kjh asdf', 'oijr asdf']
|
||||
@expected = ' asdf'
|
||||
end
|
||||
|
||||
it 'returns « BlogName' do
|
||||
@input = ['user1 « BlogName',
|
||||
'user2 « BlogName',
|
||||
'user3 « BlogName',
|
||||
'user4 « BlogName']
|
||||
@expected = ' « BlogName'
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = %w{user1 user2 user3 user4}
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = ['user1 « BlogName',
|
||||
'user2 « BlogName',
|
||||
'user3 « BlogName',
|
||||
'user4 « BlogNamea']
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns an empty string' do
|
||||
@input = %w{ user1 }
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'returns | test' do
|
||||
@input = ['admin | test', 'test | test']
|
||||
@expected = ' | test'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_base64_images_from_html' do
|
||||
after :each do
|
||||
output = remove_base64_images_from_html(@html)
|
||||
expect(output).to eq @expected
|
||||
end
|
||||
|
||||
it 'removes the valid base64 image' do
|
||||
@html = '<img alt="" src="data:image/x-png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsTAAALEwEAmpwYAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAABLElEQVR42qSTQStFURSFP7f3XygyoAwoYSYMPCIpk2egMFSmUvwCRpSRDIwYGbwyVuYykB9y914m951z7nHe6J26dc9u77XXWmdvJLF7/audqx9JYuvyW92LL0li8K2df2r17CPEVk7ftXTclyQqAMmRCwC5I3fS42a4W7y74VYDNAAuJA8AaXIsSACsDgAdAJeFrnnyoMBygKZJJ3b1It0AmsTMDPdEgrujJqHEwCxqznMaD2KgyCDRnEuo8qJhHvx/hcQDbzGoix5Yi4G1TcwZWNEDKwJU+WDkhg2ToDaD+M65YcVB8jg3Y5IY5VQAyyf9gLJw+CqAuYNnAczsPQpgevtBU937kDexcdssj8Ti0ZskMd97CRs3u//U2sjJzbtwH1+/Cf8jS/gbAMmWc42HzdIjAAAAAElFTkSuQmCC" />'
|
||||
@expected = '<img alt="" src="" />'
|
||||
end
|
||||
|
||||
it 'ignores invalid base64 content' do
|
||||
@html = '<img alt="" src="data:image/x-png;base64,iVBORw0KGgo" />'
|
||||
@expected = @html
|
||||
end
|
||||
end
|
||||
|
||||
describe '#truncate' do
|
||||
after :each do
|
||||
output = truncate(@input, @length, @trailing)
|
||||
expect(output).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns nil on no input' do
|
||||
@input = nil
|
||||
@length = 1
|
||||
@expected = nil
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns input when length > input' do
|
||||
@input = '1234567890'
|
||||
@length = 13
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'truncates the input' do
|
||||
@input = '1234567890'
|
||||
@length = 6
|
||||
@expected = '123...'
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'adds own trailing' do
|
||||
@input = '1234567890'
|
||||
@length = 7
|
||||
@expected = '123xxxx'
|
||||
@trailing = 'xxxx'
|
||||
end
|
||||
|
||||
it 'accepts strings as length' do
|
||||
@input = '1234567890'
|
||||
@length = '6'
|
||||
@expected = '123...'
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'checks if trailing is longer than input' do
|
||||
@input = '1234567890'
|
||||
@length = 1
|
||||
@expected = @input
|
||||
@trailing = 'A' * 20
|
||||
end
|
||||
|
||||
it 'returns input on negative length' do
|
||||
@input = '1234567890'
|
||||
@length = -1
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns input on length == input.length' do
|
||||
@input = '1234567890'
|
||||
@length = '10'
|
||||
@expected = @input
|
||||
@trailing = '...'
|
||||
end
|
||||
|
||||
it 'returns cut string on nil trailing' do
|
||||
@input = '1234567890'
|
||||
@length = 9
|
||||
@expected = '123456789'
|
||||
@trailing = nil
|
||||
end
|
||||
|
||||
it 'trailing.length > length' do
|
||||
@input = '1234567890'
|
||||
@length = 1
|
||||
@expected = @input
|
||||
@trailing = 'A' * 20
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,155 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe CustomOptionParser do
|
||||
|
||||
let(:parser) { CustomOptionParser.new }
|
||||
|
||||
describe '#new' do
|
||||
|
||||
end
|
||||
|
||||
describe '::option_to_symbol' do
|
||||
after :each do
|
||||
if @exception
|
||||
expect { CustomOptionParser::option_to_symbol(@option) }.to raise_error(@exception)
|
||||
else
|
||||
expect(CustomOptionParser::option_to_symbol(@option)).to be === @expected
|
||||
end
|
||||
end
|
||||
|
||||
context 'without REQUIRED or OPTIONAL arguments' do
|
||||
context 'with short option' do
|
||||
it 'should return :test' do
|
||||
@option = ['-t', '--test', 'Testing']
|
||||
@expected = :test
|
||||
end
|
||||
|
||||
it 'should :its_a_long_option' do
|
||||
@option = ['-l', '--its-a-long-option', "Testing '-' replacement"]
|
||||
@expected = :its_a_long_option
|
||||
end
|
||||
end
|
||||
|
||||
context 'without short option' do
|
||||
it 'should return :long' do
|
||||
@option = ['--long', "The method should find the option name ('long')"]
|
||||
@expected = :long
|
||||
end
|
||||
|
||||
it 'should return :long_option' do
|
||||
@option = ['--long-option', 'No short !']
|
||||
@expected = :long_option
|
||||
end
|
||||
end
|
||||
|
||||
context 'without long option' do
|
||||
it 'should raise an arror' do
|
||||
@option = ['-v', 'The long option is missing there']
|
||||
@exception = 'Could not find the option name for ["-v", "The long option is missing there"]'
|
||||
end
|
||||
|
||||
it 'should raise an error' do
|
||||
@option = ['The long option is missing there']
|
||||
@exception = 'Could not find the option name for ["The long option is missing there"]'
|
||||
end
|
||||
end
|
||||
|
||||
context 'with multiple long option names (like alias)' do
|
||||
it 'should return :check_long and not :cl' do
|
||||
@option = ['--check-long', '--cl']
|
||||
@expected = :check_long
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with REQUIRED or OPTIONAL arguments' do
|
||||
it 'should removed the OPTIONAL argument' do
|
||||
@option = ['-p', '--page [PAGE_NUMBER]']
|
||||
@expected = :page
|
||||
end
|
||||
|
||||
it 'should removed the REQUIRED argument' do
|
||||
@option = ['--url TARGET_URL']
|
||||
@expected = :url
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '#add_option' do
|
||||
context 'exception throwing if' do
|
||||
after :each do
|
||||
expect { parser.add_option(@option) }.to raise_error(@exception)
|
||||
end
|
||||
|
||||
it 'argument passed is not an Array' do
|
||||
@option = 'a simple String'
|
||||
@exception = "The option must be an array, String supplied : 'a simple String'"
|
||||
end
|
||||
|
||||
it 'option name is already used' do
|
||||
@option = ['-v', '--verbose', 'Verbose mode']
|
||||
parser.add_option(@option)
|
||||
@exception = 'The option verbose is already used !'
|
||||
end
|
||||
end
|
||||
|
||||
it 'should have had 2 symbols (:verbose, :url) to @symbols_used' do
|
||||
parser.add_option(['-v', '--verbose'])
|
||||
parser.add_option(['--url TARGET_URL'])
|
||||
|
||||
expect(parser.symbols_used.sort).to be === [:url, :verbose]
|
||||
end
|
||||
|
||||
context 'parsing' do
|
||||
before :each do
|
||||
parser.add_option(['-u', '--url TARGET_URL', 'Set the target url'])
|
||||
end
|
||||
|
||||
it 'should raise an error if an unknown option is supplied' do
|
||||
expect { parser.parse!(['--verbose']) }.to raise_error(OptionParser::InvalidOption)
|
||||
end
|
||||
|
||||
it 'should raise an error if an option require an argument which is not supplied' do
|
||||
expect { parser.parse!(['--url']) }.to raise_error(OptionParser::MissingArgument)
|
||||
end
|
||||
|
||||
it 'should retrieve the correct argument' do
|
||||
parser.parse!(['-u', 'iam_the_target'])
|
||||
expect(parser.results).to be === { url: 'iam_the_target' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add' do
|
||||
it 'should raise an error if the argument is not an Array or Array(Array)' do
|
||||
expect { parser.add('Hello') }.to raise_error('Options must be at least an Array, or an Array(Array). String supplied')
|
||||
end
|
||||
|
||||
before :each do
|
||||
parser.add(['-u', '--url TARGET_URL'])
|
||||
end
|
||||
|
||||
context 'single option' do
|
||||
it 'should add the :url option, and retrieve the correct argument' do
|
||||
expect(parser.symbols_used).to be === [:url]
|
||||
expect(parser.results(['-u', 'target.com'])).to be === { url: 'target.com' }
|
||||
end
|
||||
end
|
||||
|
||||
context 'multiple options' do
|
||||
it 'should add 2 options, and retrieve the correct arguments' do
|
||||
parser.add([
|
||||
['-v', '--verbose'],
|
||||
['--test [TEST_NUMBER]']
|
||||
])
|
||||
|
||||
expect(parser.symbols_used.sort).to be === [:test, :url, :verbose]
|
||||
expect(parser.results(['-u', 'wp.com', '-v', '--test'])).to be === { test: nil, url: 'wp.com', verbose: true }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Vulnerability::Output do
|
||||
|
||||
describe '#output' do
|
||||
# How to test it ? oO
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,55 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Vulnerability do
|
||||
|
||||
describe '#new' do
|
||||
subject(:vulnerability) { Vulnerability.new(title, type, references, fixed_version) }
|
||||
let(:title) { 'A vulnerability title' }
|
||||
let(:type) { 'XSS' }
|
||||
let(:references) { {:url => 'example.com', :metasploit => 'm', :exploitdb => 'e'} }
|
||||
|
||||
context 'w/o metasploit and fixed version modules argument' do
|
||||
subject(:vulnerability) { Vulnerability.new(title, type, references) }
|
||||
|
||||
its(:title) { should be title }
|
||||
its(:references) { should be references }
|
||||
its(:type) { should be type }
|
||||
its(:fixed_in) { should be_empty }
|
||||
end
|
||||
|
||||
context 'with fixed version argument' do
|
||||
let(:fixed_version) { '1.0' }
|
||||
|
||||
its(:title) { should be title }
|
||||
its(:references) { should be references }
|
||||
its(:type) { should be type }
|
||||
its(:fixed_in) { should be fixed_version }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '::load_from_json_item' do
|
||||
subject(:vulnerability) { Vulnerability.load_from_json_item(item) }
|
||||
let(:item) {
|
||||
json(MODELS_FIXTURES + '/vulnerability/json_item.json')
|
||||
}
|
||||
|
||||
expected_refs = {
|
||||
'id' => ['3911'],
|
||||
'url' => ['Ref 1,Ref 2'],
|
||||
'cve' => ['2011-001'],
|
||||
'secunia' => ['secunia'],
|
||||
'osvdb' => ['osvdb'],
|
||||
'metasploit' => ['exploit/ex1'],
|
||||
'exploitdb' => ['exploitdb']
|
||||
}
|
||||
|
||||
its(:title) { should == 'Vuln Title' }
|
||||
its(:type) { should == 'CSRF' }
|
||||
its(:references) { should == expected_refs}
|
||||
its(:fixed_in) { should == '1.0'}
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,166 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpItem do
|
||||
it_behaves_like 'WpItem::Existable'
|
||||
it_behaves_like 'WpItem::Findable#Found_From='
|
||||
it_behaves_like 'WpItem::Infos' do
|
||||
let(:changelog_url) { uri.merge('changelog.txt').to_s }
|
||||
let(:error_log_url) { uri.merge('error_log').to_s }
|
||||
end
|
||||
it_behaves_like 'WpItem::Versionable'
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:db_file) { MODELS_FIXTURES + '/wp_item/vulnerable/items_vulns.json' }
|
||||
let(:identifier) { 'neo' }
|
||||
let(:expected_refs) { {
|
||||
'id' => [2993],
|
||||
'url' => ['Ref 1', 'Ref 2'],
|
||||
'cve' => ['2011-001'],
|
||||
'secunia' => ['secunia'],
|
||||
'osvdb' => ['osvdb'],
|
||||
'metasploit' => ['exploit/ex1'],
|
||||
'exploitdb' => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new(1, Vulnerability.new("I'm the one", 'XSS', expected_refs)) }
|
||||
end
|
||||
|
||||
subject(:wp_item) { WpItem.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com') }
|
||||
let(:options) { {} }
|
||||
|
||||
describe '#new' do
|
||||
context 'with no options' do
|
||||
its(:wp_content_dir) { is_expected.to eq 'wp-content' }
|
||||
its(:wp_plugins_dir) { is_expected.to eq 'wp-content/plugins' }
|
||||
its(:uri) { is_expected.to be uri }
|
||||
end
|
||||
|
||||
context 'with :wp_content_dir' do
|
||||
let(:options) { { wp_content_dir: 'custom' } }
|
||||
|
||||
its(:wp_content_dir) { is_expected.to eq 'custom' }
|
||||
its(:wp_plugins_dir) { is_expected.to eq 'custom/plugins' }
|
||||
end
|
||||
|
||||
context 'with :wp_plugins_dir' do
|
||||
let(:options) { { wp_plugins_dir: 'c-plugins' } }
|
||||
|
||||
its(:wp_content_dir) { is_expected.to eq 'wp-content' }
|
||||
its(:wp_plugins_dir) { is_expected.to eq 'c-plugins' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set_options' do
|
||||
context 'no an allowed option' do
|
||||
it 'ignores the option' do
|
||||
expect(wp_item).not_to receive(:not_allowed=)
|
||||
|
||||
wp_item.send(:set_options, { not_allowed: 'owned' })
|
||||
end
|
||||
end
|
||||
|
||||
context 'allowed option, w/o setter method' do
|
||||
it 'raises an error' do
|
||||
allow(wp_item).to receive(:allowed_options).and_return([:no_setter])
|
||||
|
||||
expect {
|
||||
wp_item.send(:set_options, { no_setter: 'hello' })
|
||||
}.to raise_error('WpItem does not respond to no_setter=')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#path=' do
|
||||
after do
|
||||
wp_item.path = @path
|
||||
expect(wp_item.path).to eq @expected
|
||||
end
|
||||
|
||||
context 'with default variable value' do
|
||||
it 'replaces $wp-content$ by wp-content' do
|
||||
@path = '$wp-content$/hello'
|
||||
@expected = 'wp-content/hello'
|
||||
end
|
||||
|
||||
it 'replaces $wp-plugins$ by wp-content/plugins' do
|
||||
@path = '$wp-plugins$/yolo/file.php'
|
||||
@expected = 'wp-content/plugins/yolo/file.php'
|
||||
end
|
||||
end
|
||||
|
||||
context 'whith custom variable values' do
|
||||
before {
|
||||
allow(wp_item).to receive(:wp_content_dir).and_return('custom-content')
|
||||
allow(wp_item).to receive(:wp_plugins_dir).and_return('plugins')
|
||||
}
|
||||
|
||||
it 'replaces $wp-content$ by custom-content' do
|
||||
@path = '$wp-content$/file.php'
|
||||
@expected = 'custom-content/file.php'
|
||||
end
|
||||
|
||||
it 'replaces $wp-plugins$ by plugins' do
|
||||
@path = '$wp-plugins$/readme.txt'
|
||||
@expected = 'plugins/readme.txt'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#uri' do
|
||||
context 'when the path is present' do
|
||||
it 'returns it with the uri' do
|
||||
path = 'somedir/somefile.php'
|
||||
wp_item.path = path
|
||||
|
||||
expect(wp_item.uri).to eq uri.merge(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#<=>' do
|
||||
it 'bases the comparaison on the :name' do
|
||||
wp_item.name = 'a-name'
|
||||
other = WpItem.new(uri, name: 'other-name')
|
||||
|
||||
expect(wp_item.<=>(other)).to be === 'a-name'.<=>('other-name')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#==' do
|
||||
context 'when the :name is the same' do
|
||||
it 'is ==' do
|
||||
wp_item.name = 'some-name'
|
||||
other = WpItem.new(uri, name: 'some-name')
|
||||
|
||||
expect(wp_item).to eq other
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
it 'is not ==' do
|
||||
wp_item.name = 'Test'
|
||||
other = WpItem.new(uri, name: 'hello')
|
||||
|
||||
expect(wp_item).not_to eq other
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#===' do
|
||||
let(:options) { { name: 'a-name', version: '1.2' } }
|
||||
|
||||
context 'when the :name and :version are the same' do
|
||||
it 'is ===' do
|
||||
expect(WpItem.new(uri, options)).to be === WpItem.new(uri.merge('yo'), options)
|
||||
end
|
||||
end
|
||||
|
||||
context 'otherwise' do
|
||||
it 'is not ===' do
|
||||
expect(WpItem.new(uri, options)).not_to be === WpItem.new(uri, options.merge(version: '1.0'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,30 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpPlugin do
|
||||
it_behaves_like 'WpPlugin::Vulnerable'
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:options) { { name: 'white-rabbit' } }
|
||||
let(:db_file) { MODELS_FIXTURES + '/wp_plugin/vulnerable/plugins.json' }
|
||||
let(:expected_refs) { {
|
||||
'id' => [2993],
|
||||
'url' => ['Ref 1', 'Ref 2'],
|
||||
'cve' => ['2011-001'],
|
||||
'secunia' => ['secunia'],
|
||||
'osvdb' => ['osvdb'],
|
||||
'metasploit' => ['exploit/ex1'],
|
||||
'exploitdb' => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('Follow me!', 'REDIRECT', expected_refs) }
|
||||
end
|
||||
|
||||
subject(:wp_plugin) { WpPlugin.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com') }
|
||||
let(:options) { { name: 'plugin-name' } }
|
||||
|
||||
describe '#forge_uri' do
|
||||
its('uri.to_s') { is_expected.to eq 'http://example.com/wp-content/plugins/plugin-name/' }
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,164 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'WpTheme::Findable' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_theme/findable' }
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
|
||||
describe '::find_from_css_link' do
|
||||
before do
|
||||
stub_request(:get, /.+\/style.css$/).to_return(status: 200)
|
||||
end
|
||||
|
||||
after do
|
||||
@body ||= File.new(fixtures_dir + '/css_link/' + @file)
|
||||
stub_request(:get, uri.to_s).to_return(status: 200, body: @body)
|
||||
|
||||
wp_theme = WpTheme.send(:find_from_css_link, uri)
|
||||
|
||||
expect(wp_theme).to be_a WpTheme if @expected
|
||||
expect(wp_theme).to eq @expected
|
||||
expect(wp_theme.wp_content_dir).to eql 'wp-content' if @expected
|
||||
end
|
||||
|
||||
context 'when theme is not present' do
|
||||
it 'returns nil' do
|
||||
@body = ''
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the theme name has spaces or special chars' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'theme-name-with-spaces.html'
|
||||
@expected = WpTheme.new(uri, name: 'Copia di simplefolio')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when <link> is inline' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'inline_link_tag.html'
|
||||
@expected = WpTheme.new(uri, name: 'inline')
|
||||
end
|
||||
end
|
||||
|
||||
# FIXME: the style_url should be checked in WpTheme for absolute / relative
|
||||
context 'when relative url is used' do
|
||||
context 'when leading slash' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'relative_urls.html'
|
||||
@expected = WpTheme.new(uri, name: 'theme_name')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no leading slash' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'relative_urls_missing_slash.html'
|
||||
@expected = WpTheme.new(uri, name: 'theme_name')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when other style.css is referenced' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'yootheme.html'
|
||||
@expected = WpTheme.new(uri, name: 'yoo_solar_wp', referenced_url: '/wp-content/themes/yoo_solar_wp/styles/wood/css/style.css')
|
||||
end
|
||||
end
|
||||
|
||||
# This one might introduce FP btw
|
||||
context 'when leaked from comments' do
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'comments.html'
|
||||
@expected = WpTheme.new(uri, name: 'debug')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find_from_wooframework' do
|
||||
before do
|
||||
stub_request(:get, /.+\/style.css$/).to_return(status: 200)
|
||||
end
|
||||
|
||||
after do
|
||||
@body ||= File.new(fixtures_dir + '/wooframework/' + @file)
|
||||
stub_request(:get, uri.to_s).to_return(status: 200, body: @body)
|
||||
|
||||
wp_theme = WpTheme.send(:find_from_wooframework, uri)
|
||||
|
||||
if @expected
|
||||
expect(wp_theme).to be_a WpTheme
|
||||
end
|
||||
expect(wp_theme).to eq @expected
|
||||
end
|
||||
|
||||
context 'when theme is not present' do
|
||||
it 'returns nil' do
|
||||
@body = ''
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the WpTheme' do
|
||||
@file = 'merchant-no-version.html'
|
||||
@expected = WpTheme.new(uri, name: 'Merchant')
|
||||
end
|
||||
|
||||
context 'when the version is present' do
|
||||
it 'returns the WpTheme with it' do
|
||||
@file = 'editorial-1.3.5.html'
|
||||
@expected = WpTheme.new(uri, name: 'Editorial', version: '1.3.5')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find' do
|
||||
# Stub all WpTheme::find_from_* to return nil
|
||||
def stub_all_to_nil
|
||||
WpTheme.methods.grep(/^find_from_/).each do |method|
|
||||
allow(WpTheme).to receive(method).and_return(nil)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a method is named s_find_from_s' do
|
||||
it 'does not call it' do
|
||||
class WpTheme
|
||||
module Findable
|
||||
extend self
|
||||
def s_find_from_s(s); raise 'I should not be called by ::find' end
|
||||
end
|
||||
end
|
||||
|
||||
stub_all_to_nil
|
||||
|
||||
expect { WpTheme.find(uri) }.to_not raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the theme is not found' do
|
||||
it 'returns nil' do
|
||||
stub_all_to_nil
|
||||
|
||||
expect(WpTheme.find(uri)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the theme is found' do
|
||||
it 'returns it, with the :found_from set' do
|
||||
stub_all_to_nil
|
||||
stub_request(:get, /.+\/the-oracle\/style.css$/).to_return(status: 200)
|
||||
expected = WpTheme.new(uri, name: 'the-oracle')
|
||||
|
||||
allow(WpTheme).to receive(:find_from_css_link).and_return(expected)
|
||||
wp_theme = WpTheme.find(uri)
|
||||
|
||||
expect(wp_theme).to be_a WpTheme
|
||||
expect(wp_theme).to eq expected
|
||||
expect(wp_theme.found_from).to be === 'css link'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpTheme do
|
||||
it_behaves_like 'WpTheme::Versionable'
|
||||
it_behaves_like 'WpTheme::Vulnerable'
|
||||
it_behaves_like 'WpItem::Vulnerable' do
|
||||
let(:options) { { name: 'the-oracle' } }
|
||||
let(:db_file) { MODELS_FIXTURES + '/wp_theme/vulnerable/themes_vulns.json' }
|
||||
let(:expected_refs) { {
|
||||
'id' => [2993],
|
||||
'url' => ['Ref 1', 'Ref 2'],
|
||||
'cve' => ['2011-001'],
|
||||
'secunia' => ['secunia'],
|
||||
'osvdb' => ['osvdb'],
|
||||
'metasploit' => ['exploit/ex1'],
|
||||
'exploitdb' => ['exploitdb']
|
||||
} }
|
||||
let(:expected_vulns) { Vulnerabilities.new << Vulnerability.new('I see you', 'FPD', expected_refs) }
|
||||
end
|
||||
|
||||
subject(:wp_theme) { WpTheme.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
let(:options) { { name: 'theme-name' } }
|
||||
let(:theme_path) { 'wp-content/themes/theme-name/' }
|
||||
|
||||
describe '#allowed_options' do
|
||||
its(:allowed_options) { is_expected.to include :referenced_url }
|
||||
end
|
||||
|
||||
describe '#forge_uri' do
|
||||
its(:uri) { is_expected.to eq uri.merge(theme_path) }
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,33 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpTimthumb do
|
||||
it_behaves_like 'WpTimthumb::Existable'
|
||||
it_behaves_like 'WpTimthumb::Versionable'
|
||||
|
||||
subject(:wp_timthumb) { WpTimthumb.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
let(:options) { { path: 'path-to/a/timtuhumb.php' } }
|
||||
|
||||
describe '#==' do
|
||||
context 'when both url are equal' do
|
||||
it 'returns true' do
|
||||
expect(WpTimthumb.new(uri, path: 'timtuhumb.php')).
|
||||
to eq(
|
||||
WpTimthumb.new(uri, path: 'timtuhumb.php')
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when urls are different' do
|
||||
it 'returns false' do
|
||||
expect(WpTimthumb.new(uri, path: 'hello/timtuhumb.php')).
|
||||
not_to eq(
|
||||
WpTimthumb.new(uri, path: 'some-dir/timtuhumb.php')
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,88 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpUser do
|
||||
it_behaves_like 'WpUser::Existable'
|
||||
it_behaves_like 'WpUser::BruteForcable'
|
||||
|
||||
subject(:wp_user) { WpUser.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com') }
|
||||
let(:options) { {} }
|
||||
|
||||
describe '#allowed_options' do
|
||||
[:id, :login, :display_name, :password].each do |sym|
|
||||
its(:allowed_options) { is_expected.to include sym }
|
||||
end
|
||||
|
||||
its(:allowed_options) { is_expected.not_to include :name }
|
||||
end
|
||||
|
||||
describe '#uri' do
|
||||
context 'when the id is not set' do
|
||||
it 'raises an error' do
|
||||
expect { wp_user.uri }.to raise_error('The id is nil')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the id is set' do
|
||||
it 'returns the uri to the auhor page' do
|
||||
wp_user.id = 2
|
||||
|
||||
expect(wp_user.uri).to eq uri.merge('?author=2')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
after do
|
||||
subject.id = 1
|
||||
expect(subject.to_s).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns @id' do
|
||||
@expected = '1'
|
||||
end
|
||||
|
||||
context 'when @login' do
|
||||
it 'returns @id | @login' do
|
||||
subject.login = 'admin'
|
||||
|
||||
@expected = '1 | admin'
|
||||
end
|
||||
|
||||
context 'when @display_name' do
|
||||
it 'returns @id | @login | @display_name' do
|
||||
subject.login = 'admin'
|
||||
subject.display_name = 'real name'
|
||||
|
||||
@expected = '1 | admin | real name'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#<=>' do
|
||||
it 'bases the comparaison on the :id' do
|
||||
wp_user.id = 1
|
||||
other = WpUser.new(uri, id: 3)
|
||||
|
||||
expect(wp_user.<=>(other)).to be === 1.<=>(3)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#===, #==' do
|
||||
context 'when the :id and :login are the same' do
|
||||
it 'is ===, and ==' do
|
||||
expect(WpUser.new(uri, id: 1, name: 'yo')).to eq WpUser.new(uri, id: 1, name: 'yo')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :id and :login are different' do
|
||||
it 'is not === or ==' do
|
||||
expect(WpUser.new(uri, id: 1, name: 'yo')).not_to eq WpUser.new(uri, id: 2, name:'yo')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,232 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'WpVersion::Findable' do
|
||||
let(:fixtures_dir) { MODELS_FIXTURES + '/wp_version/findable/' }
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
let(:generator_urls) {
|
||||
{
|
||||
rss_generator: uri.merge('feed/').to_s,
|
||||
rdf_generator: uri.merge('feed/rdf/').to_s,
|
||||
atom_generator: uri.merge('feed/atom/').to_s,
|
||||
comments_rss_generator: uri.merge('comments/feed/').to_s,
|
||||
sitemap_generator: uri.merge('sitemap.xml').to_s
|
||||
}
|
||||
}
|
||||
|
||||
# Dynamic creation for all generator methods
|
||||
WpVersion.methods.grep(/^find_from_.*_generator$/).each do |method|
|
||||
dir_name = method.to_s[%r{^find_from_(.*)$}, 1]
|
||||
|
||||
describe "::#{method}" do
|
||||
let(:url) { generator_urls[dir_name.to_sym] || uri.to_s }
|
||||
|
||||
after do
|
||||
fixture = fixtures_dir + dir_name + @fixture
|
||||
stub_request_to_fixture(url: url, fixture: fixture)
|
||||
|
||||
expect(WpVersion.send(method, uri)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when generator not found' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/no_generator.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when version not found' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/no_version.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid version' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/invalid_version.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 3.3.2' do
|
||||
@fixture = '/3.3.2.html'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it 'returns 3.4-beta4' do
|
||||
@fixture = '/3.4-beta4.html'
|
||||
@expected = '3.4-beta4'
|
||||
end
|
||||
|
||||
if method == :find_from_meta_generator
|
||||
it 'returns 3.5' do
|
||||
@fixture = '/3.5_minified.html'
|
||||
@expected = '3.5'
|
||||
end
|
||||
|
||||
it 'returns 3.5.1' do
|
||||
@fixture = '/3.5.1_mobile.html'
|
||||
@expected = '3.5.1'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find_from_advanced_fingerprinting' do
|
||||
let(:fixture_dir) { fixtures_dir + 'advanced_fingerprinting/' }
|
||||
let(:wp_content_dir) { 'wp-content' }
|
||||
let(:wp_plugins_dir) { wp_content_dir + '/plugins' }
|
||||
let(:versions_xml) { fixture_dir + 'wp_versions.xml' }
|
||||
|
||||
after do
|
||||
version = WpVersion.send(
|
||||
:find_from_advanced_fingerprinting,
|
||||
uri, wp_content_dir, wp_plugins_dir, versions_xml
|
||||
)
|
||||
expect(version).to eq @expected
|
||||
end
|
||||
|
||||
context 'when' do
|
||||
it 'returns nil' do
|
||||
stub_request(:get, /.*/).to_return(status: 404, body: '')
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 3.2.1' do
|
||||
stub_request_to_fixture(
|
||||
url: uri.merge('wp-admin/js/wp-fullscreen.js').to_s,
|
||||
fixture: fixture_dir + '3.2.1.js'
|
||||
)
|
||||
|
||||
@expected = '3.2.1'
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find_from_readme' do
|
||||
let(:url) { uri.merge('readme.html').to_s }
|
||||
|
||||
after do
|
||||
fixture = fixtures_dir + 'readme' + @fixture
|
||||
stub_request_to_fixture(url: url, fixture: fixture)
|
||||
|
||||
expect(WpVersion.send(:find_from_readme, uri)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when version not found' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/empty_version.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when invalid version' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/invalid_version.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns 3.3.2' do
|
||||
@fixture = '/3.3.2.html'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
context 'when version >= 4.7' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/4.7.2.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find_from_links_opml' do
|
||||
let(:url) { uri.merge('wp-links-opml.php') }
|
||||
|
||||
after do
|
||||
fixture = fixtures_dir + 'links_opml' + @fixture
|
||||
stub_request_to_fixture(url: url, fixture: fixture)
|
||||
|
||||
expect(WpVersion.send(:find_from_links_opml, uri)).to eq @expected
|
||||
end
|
||||
|
||||
it 'returns 3.4.2' do
|
||||
@fixture = '/3.4.2.xml'
|
||||
@expected = '3.4.2'
|
||||
end
|
||||
|
||||
context 'when no generator' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/no_generator.xml'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find_from_stylesheets_numbers' do
|
||||
after do
|
||||
fixture = fixtures_dir + 'stylesheet_numbers' + @fixture
|
||||
stub_request_to_fixture(url: uri, fixture: fixture)
|
||||
|
||||
expect(WpVersion.send(:find_from_stylesheets_numbers, uri)).to eq @expected
|
||||
end
|
||||
|
||||
context 'invalid url' do
|
||||
it 'returns nil' do
|
||||
@fixture = '/invalid_url.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '::find' do
|
||||
# Stub all WpVersion::find_from_* to return nil
|
||||
def stub_all_to_nil
|
||||
WpVersion.methods.grep(/^find_from_/).each do |method|
|
||||
allow(WpVersion).to receive(method).and_return(nil)
|
||||
end
|
||||
end
|
||||
|
||||
let(:wp_content_dir) { 'wp-content' }
|
||||
let(:wp_plugins_dir) { wp_content_dir + '/plugins' }
|
||||
let(:version_xml) {}
|
||||
|
||||
after do
|
||||
stub_request(:get, /#{uri.to_s}.*/).to_return(status: 0)
|
||||
|
||||
version = WpVersion.find(uri, wp_content_dir, wp_plugins_dir, version_xml)
|
||||
expect(version).to eq @expected
|
||||
if @expected
|
||||
expect(version.found_from).to eq @found_from
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no version found' do
|
||||
it 'returns nil' do
|
||||
stub_all_to_nil
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
WpVersion.methods.grep(/^find_from_/).each do |method|
|
||||
number = "#{rand(5)}.#{rand(3)}"
|
||||
found_from = method[/^find_from_(.*)/, 1].sub('_', ' ')
|
||||
|
||||
context "when found from #{found_from}" do
|
||||
it 'returns the correct WpVersion' do
|
||||
stub_all_to_nil
|
||||
|
||||
allow(WpVersion).to receive(method).and_return(number)
|
||||
|
||||
@expected = WpVersion.new(uri, number: number)
|
||||
@found_from = found_from
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,26 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe WpVersion do
|
||||
it_behaves_like 'WpVersion::Vulnerable'
|
||||
|
||||
subject(:wp_version) { WpVersion.new(uri, options) }
|
||||
let(:uri) { URI.parse('http://example.com/') }
|
||||
let(:options) { { number: '1.2' } }
|
||||
|
||||
describe '#allowed_options' do
|
||||
[:number, :found_from].each do |sym|
|
||||
its(:allowed_options) { is_expected.to include sym }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#all' do
|
||||
let(:versions_file) { File.join(MODELS_FIXTURES, 'wp_version', 'findable', 'advanced_fingerprinting', 'wp_versions.xml') }
|
||||
|
||||
it 'returns the array containign the two versions' do
|
||||
expect(WpVersion.all(versions_file)).to eq ['3.2.1', '3.2']
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,54 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Plugin do
|
||||
subject(:plugin) { Plugin.new }
|
||||
|
||||
describe '#new' do
|
||||
context 'with some infos' do
|
||||
subject(:plugin) { Plugin.new(infos) }
|
||||
let(:infos) { { author: 'John' } }
|
||||
|
||||
its(:author) { is_expected.to be === infos[:author] }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#run' do
|
||||
it 'should raise a NotImplementedError' do
|
||||
expect { plugin.run }.to raise_error(NotImplementedError)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#register_options' do
|
||||
after :each do
|
||||
if @exception
|
||||
expect { plugin.register_options(*@options) }.to raise_error(@exception)
|
||||
else
|
||||
plugin.register_options(*@options)
|
||||
expect(plugin.registered_options.sort).to be === @expected.sort
|
||||
end
|
||||
end
|
||||
|
||||
context 'when an option is not an Array' do
|
||||
it 'should raise an error' do
|
||||
@options = [
|
||||
['-v', '--verbose', 'It\'s a valid option'],
|
||||
'Not a valid one'
|
||||
]
|
||||
@exception = 'Each option must be an array, String supplied'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when options are Arrays' do
|
||||
it 'should register the options' do
|
||||
@options = [
|
||||
['-v', '--verbose', 'Verbose mode'],
|
||||
['-u', '--url TARGET_URL']
|
||||
]
|
||||
@expected = *@options
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,97 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
class TestPlugin < Plugin
|
||||
def initialize
|
||||
register_options(['-u', '--url'])
|
||||
end
|
||||
end
|
||||
|
||||
class AnotherPlugin < Plugin
|
||||
def initialize
|
||||
super(author: 'John')
|
||||
# No Options
|
||||
end
|
||||
end
|
||||
|
||||
describe Plugins do
|
||||
subject(:plugins) { Plugins.new }
|
||||
|
||||
let(:test_plugin) { TestPlugin.new }
|
||||
let(:another_plugin) { AnotherPlugin.new }
|
||||
|
||||
describe '#new' do
|
||||
context 'without argument' do
|
||||
its(:option_parser) { is_expected.to be_a CustomOptionParser }
|
||||
|
||||
it 'should be an Array' do
|
||||
expect(plugins).to be_an Array
|
||||
end
|
||||
end
|
||||
|
||||
context 'with an option_parser argument' do
|
||||
subject(:plugin) { Plugins.new(CustomOptionParser.new('the banner')) }
|
||||
|
||||
its(:option_parser) { is_expected.to be_a CustomOptionParser }
|
||||
its('option_parser.banner') { is_expected.to be === 'the banner' }
|
||||
|
||||
it 'should raise an eror if the parser is not an instance of CustomOptionParser' do
|
||||
expect { Plugins.new(OptionParser.new) }.to raise_error('The parser must be an instance of CustomOptionParser, OptionParser supplied')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#register_plugin' do
|
||||
after :each do
|
||||
if @exception
|
||||
expect { plugins.register_plugin(@plugin) }.to raise_error(@exception)
|
||||
else
|
||||
plugins.register_plugin(@plugin)
|
||||
expect(plugins).to include(@plugin)
|
||||
expect(plugins).to be === @expected
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the argument supplied is not an instance of Plugin' do
|
||||
it 'should raise an error' do
|
||||
@plugin = "I'am a String"
|
||||
@exception = 'The argument must be an instance of Plugin, String supplied'
|
||||
end
|
||||
end
|
||||
|
||||
it 'should register the plugin' do
|
||||
@plugin = TestPlugin.new
|
||||
@expected = [@plugin]
|
||||
end
|
||||
|
||||
it 'should register 2 plugins (the order is important)' do
|
||||
plugins.register_plugin(test_plugin)
|
||||
|
||||
@plugin = another_plugin
|
||||
@expected = [test_plugin, @plugin]
|
||||
end
|
||||
end
|
||||
|
||||
describe '#register' do
|
||||
after :each do
|
||||
plugins.register(*@plugins_to_register)
|
||||
|
||||
@plugins_to_register.each do |plugin|
|
||||
expect(plugins).to include(plugin)
|
||||
end
|
||||
|
||||
# For the correct order
|
||||
expect(plugins).to be === @plugins_to_register
|
||||
end
|
||||
|
||||
it 'should register 1 plugin' do
|
||||
@plugins_to_register = [test_plugin]
|
||||
end
|
||||
|
||||
it 'should register 2 plugins' do
|
||||
@plugins_to_register = [another_plugin, test_plugin]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,3 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
# TODO
|
||||
@@ -1,247 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'VersionCompare' do
|
||||
describe '::lesser_or_equal?' do
|
||||
context 'version checked is newer' do
|
||||
after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_truthy }
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '2.0'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '1.1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0a'
|
||||
@version2 = '1.0b'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '5000000'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '0'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '0.4.2b'
|
||||
@version2 = '2.3.3'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '.47'
|
||||
@version2 = '.50.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'version checked is older' do
|
||||
after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1'
|
||||
@version2 = '0'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '0.5'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '500000'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1.6.3.7.3.4'
|
||||
@version2 = '1.2.4.567.679.8.e'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '.47'
|
||||
@version2 = '.46.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'version checked is the same' do
|
||||
after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_truthy }
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = 'a'
|
||||
@version2 = 'a'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'version number causes Gem::Version new Exception' do
|
||||
after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = 'a'
|
||||
@version2 = 'b'
|
||||
end
|
||||
end
|
||||
|
||||
context 'one version number is not set' do
|
||||
after { expect(VersionCompare::lesser_or_equal?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false (version2 nil)' do
|
||||
@version1 = '1'
|
||||
@version2 = nil
|
||||
end
|
||||
|
||||
it 'returns false (version1 nil)' do
|
||||
@version1 = nil
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns false (version2 empty)' do
|
||||
@version1 = '1'
|
||||
@version2 = ''
|
||||
end
|
||||
|
||||
it 'returns false (version1 empty)' do
|
||||
@version1 = ''
|
||||
@version2 = '1'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe '::lesser?' do
|
||||
context 'version checked is newer' do
|
||||
after { expect(VersionCompare::lesser?(@version1, @version2)).to be_truthy }
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '2.0'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '1.1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0a'
|
||||
@version2 = '1.0b'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '5000000'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '0'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '0.4.2b'
|
||||
@version2 = '2.3.3'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '.47'
|
||||
@version2 = '.50.3'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '2.5.9'
|
||||
@version2 = '2.5.10'
|
||||
end
|
||||
end
|
||||
|
||||
context 'version checked is older' do
|
||||
after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1'
|
||||
@version2 = '0'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1.0'
|
||||
@version2 = '0.5'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '500000'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '1.6.3.7.3.4'
|
||||
@version2 = '1.2.4.567.679.8.e'
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = '.47'
|
||||
@version2 = '.46.3'
|
||||
end
|
||||
end
|
||||
|
||||
context 'version checked is the same' do
|
||||
after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = '1'
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@version1 = 'a'
|
||||
@version2 = 'a'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'version number causes Gem::Version new Exception' do
|
||||
after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false' do
|
||||
@version1 = 'a'
|
||||
@version2 = 'b'
|
||||
end
|
||||
end
|
||||
|
||||
context 'one version number is not set' do
|
||||
after { expect(VersionCompare::lesser?(@version1, @version2)).to be_falsey }
|
||||
|
||||
it 'returns false (version2 nil)' do
|
||||
@version1 = '1'
|
||||
@version2 = nil
|
||||
end
|
||||
|
||||
it 'returns false (version1 nil)' do
|
||||
@version1 = nil
|
||||
@version2 = '1'
|
||||
end
|
||||
|
||||
it 'returns false (version2 empty)' do
|
||||
@version1 = '1'
|
||||
@version2 = ''
|
||||
end
|
||||
|
||||
it 'returns false (version1 empty)' do
|
||||
@version1 = ''
|
||||
@version2 = '1'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,240 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'WebSite' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WEB_SITE_DIR }
|
||||
subject(:web_site) { WebSite.new('http://example.localhost/') }
|
||||
|
||||
it_behaves_like 'WebSite::RobotsTxt'
|
||||
it_behaves_like 'WebSite::InterestingHeaders'
|
||||
|
||||
before :all do
|
||||
Browser::reset
|
||||
Browser.instance(
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json',
|
||||
cache_ttl: 0
|
||||
)
|
||||
end
|
||||
|
||||
describe '#new' do
|
||||
its(:url) { is_expected.to be === 'http://example.localhost/' }
|
||||
end
|
||||
|
||||
describe '#url=' do
|
||||
after :each do
|
||||
web_site.url = @uri
|
||||
expect(web_site.url).to be === @expected
|
||||
end
|
||||
|
||||
context 'when protocol or trailing slash is missing' do
|
||||
it 'should add them' do
|
||||
@uri = 'example.localhost'
|
||||
@expected = 'http://example.localhost/'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is a protocol or a trailing slash' do
|
||||
it 'should not add them' do
|
||||
@uri = 'http://example.localhost/'
|
||||
@expected = @uri
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#online?' do
|
||||
it 'should not be considered online if the status code is 0' do
|
||||
stub_request(:get, web_site.url).to_return(status: 0)
|
||||
expect(web_site).not_to be_online
|
||||
end
|
||||
|
||||
it 'should be considered online if the status code is != 0' do
|
||||
stub_request(:get, web_site.url).to_return(status: 200)
|
||||
expect(web_site).to be_online
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_basic_auth?' do
|
||||
it 'should detect that the wpsite is basic auth protected' do
|
||||
stub_request(:get, web_site.url).to_return(status: 401)
|
||||
expect(web_site).to have_basic_auth
|
||||
end
|
||||
|
||||
it 'should not have a basic auth for a 200' do
|
||||
stub_request(:get, web_site.url).to_return(status: 200)
|
||||
expect(web_site).not_to have_basic_auth
|
||||
end
|
||||
end
|
||||
|
||||
describe '#xml_rpc_url' do
|
||||
it 'returns the xmlrpc url' do
|
||||
expect(web_site.xml_rpc_url).to be === 'http://example.localhost/xmlrpc.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_xml_rpc?' do
|
||||
it 'returns true' do
|
||||
stub_request(:get, web_site.xml_rpc_url).
|
||||
to_return(status: 200, body: 'XML-RPC server accepts POST requests only')
|
||||
|
||||
expect(web_site).to have_xml_rpc
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:get, web_site.xml_rpc_url).to_return(status: 200)
|
||||
expect(web_site).not_to have_xml_rpc
|
||||
end
|
||||
end
|
||||
|
||||
describe '#redirection' do
|
||||
it 'returns nil if no redirection detected' do
|
||||
stub_request(:get, web_site.url).to_return(status: 200, body: '')
|
||||
|
||||
expect(web_site.redirection).to be_nil
|
||||
end
|
||||
|
||||
[301, 302].each do |status_code|
|
||||
it "returns http://new-location.com if the status code is #{status_code}" do
|
||||
new_location = 'http://new-location.com'
|
||||
|
||||
stub_request(:get, web_site.url).
|
||||
to_return(status: status_code, headers: { location: new_location })
|
||||
|
||||
stub_request(:get, new_location).to_return(status: 200)
|
||||
|
||||
expect(web_site.redirection).to be === 'http://new-location.com'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when relative URI in Location' do
|
||||
it 'returns the absolute URI' do
|
||||
relative_location = '/blog/'
|
||||
absolute_location = web_site.uri.merge(relative_location).to_s
|
||||
|
||||
stub_request(:get, web_site.url).to_return(status: 301, headers: { location: relative_location })
|
||||
stub_request(:get, absolute_location)
|
||||
|
||||
expect(web_site.redirection).to eql absolute_location
|
||||
end
|
||||
|
||||
context 'when starts with a ?' do
|
||||
it 'returns the absolute URI' do
|
||||
relative_location = '?p=blog'
|
||||
absolute_location = web_site.uri.merge(relative_location).to_s
|
||||
|
||||
stub_request(:get, web_site.url).to_return(status: 301, headers: { location: relative_location })
|
||||
stub_request(:get, absolute_location)
|
||||
|
||||
expect(web_site.redirection).to eql absolute_location
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when multiple redirections' do
|
||||
it 'returns the last redirection' do
|
||||
first_redirection = 'http://www.redirection.com'
|
||||
last_redirection = 'http://redirection.com'
|
||||
|
||||
stub_request(:get, web_site.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)
|
||||
|
||||
expect(web_site.redirection).to be === last_redirection
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#page_hash' do
|
||||
after { expect(WebSite.page_hash(page)).to eq Digest::MD5.hexdigest(@expected) }
|
||||
|
||||
context 'when the page is an url' do
|
||||
let(:page) { 'http://e.localhost/somepage.php' }
|
||||
|
||||
it 'returns the MD5 hash of the page' do
|
||||
body = 'Hello World !'
|
||||
stub_request(:get, page).to_return(body: body)
|
||||
|
||||
@expected = body
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the page is a Typhoeus::Response' do
|
||||
let(:page) { Typhoeus::Response.new(body: 'Hello Example!') }
|
||||
|
||||
it 'returns the correct hash' do
|
||||
@expected = 'Hello Example!'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are comments' do
|
||||
let(:page) {
|
||||
body = "yolo\n\n<!--I should <script>no longer be</script> there -->\nworld!"
|
||||
Typhoeus::Response.new(body: body)
|
||||
}
|
||||
|
||||
it 'removes them' do
|
||||
@expected = "yolo\n\n\nworld!"
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are scripts' do
|
||||
let(:page) {
|
||||
body = "yolo\n\n<script type=\"text/javascript\">alert('Hi');</script>\nworld!"
|
||||
Typhoeus::Response.new(body: body)
|
||||
}
|
||||
|
||||
it 'removes them' do
|
||||
@expected = "yolo\n\n\nworld!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#homepage_hash' do
|
||||
it 'returns the MD5 hash of the homepage' do
|
||||
body = 'Hello World'
|
||||
|
||||
stub_request(:get, web_site.url).to_return(body: body)
|
||||
expect(web_site.homepage_hash).to be === Digest::MD5.hexdigest(body)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#error_404_hash' do
|
||||
it 'returns the md5sum of the 404 page' do
|
||||
stub_request(:any, /.*/).
|
||||
to_return(status: 404, body: '404 page !')
|
||||
|
||||
expect(web_site.error_404_hash).to be === Digest::MD5.hexdigest('404 page !')
|
||||
end
|
||||
end
|
||||
|
||||
describe '::has_log?' do
|
||||
let(:log_url) { web_site.uri.merge('log.txt').to_s }
|
||||
let(:pattern) { %r{PHP Fatal error} }
|
||||
|
||||
after do
|
||||
stub_request_to_fixture(url: log_url, fixture: fixtures_dir + "/has_log/#{@file}")
|
||||
expect(WebSite.has_log?(log_url, pattern)).to eq @expected
|
||||
end
|
||||
|
||||
context 'when the pattern does not match' do
|
||||
it 'returns false' do
|
||||
@file = 'no_match.txt'
|
||||
@expected = false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the pattern matches' do
|
||||
it 'returns true' do
|
||||
@file = 'matches.txt'
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
# This doesn't work in rspec, WebMock or Typhoeus returns the whole file
|
||||
# See https://github.com/bblimke/webmock/issues/277
|
||||
#it 'only checks the first 700 bytes' do
|
||||
# @file = 'matches_after_700_bytes.txt'
|
||||
# @expected = false
|
||||
#end
|
||||
end
|
||||
end
|
||||
@@ -1,218 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require File.expand_path(File.join(__dir__, 'wpscan_helper'))
|
||||
|
||||
describe WpTarget do
|
||||
subject(:wp_target) { WpTarget.new(target_url, options) }
|
||||
subject(:wp_target_custom) { WpTarget.new(target_url, options_custom) }
|
||||
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.conf.json',
|
||||
cache_ttl: 0,
|
||||
wp_content_dir: 'wp-content',
|
||||
wp_plugins_dir: 'wp-content/plugins'
|
||||
}
|
||||
}
|
||||
let(:options_custom) {
|
||||
{
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser.conf.json',
|
||||
cache_ttl: 0,
|
||||
wp_content_dir: 'custom-content',
|
||||
wp_plugins_dir: 'custom-content/plugins'
|
||||
}
|
||||
}
|
||||
|
||||
before { Browser::reset }
|
||||
|
||||
it_behaves_like 'WpTarget::WpReadme'
|
||||
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
|
||||
expect { WpTarget.new(nil) }.to raise_error
|
||||
expect { Wptarget.new('') }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '#login_url' do
|
||||
it 'returns the login url of the target' do
|
||||
stub_request(:get, login_url).to_return(status: 200, body: '')
|
||||
|
||||
expect(wp_target.login_url).to be === login_url
|
||||
end
|
||||
|
||||
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)
|
||||
|
||||
expect(wp_target.login_url).to be === 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')})
|
||||
|
||||
# Preventing redirection check from login_url()
|
||||
allow(wp_target).to receive_messages(redirection: nil)
|
||||
|
||||
[wp_target.login_url, wp_target.xml_rpc_url].each do |url|
|
||||
stub_request(:get, url).to_return(status: 404, body: '')
|
||||
end
|
||||
end
|
||||
|
||||
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')
|
||||
|
||||
expect(wp_target).to be_wordpress
|
||||
end
|
||||
|
||||
it 'returns true if a custom content directory is detected' do
|
||||
stub_request_to_fixture(url: wp_target_custom.url, fixture: fixtures_dir + '/wp_content_dir/wordpress-3.4.1-custom.htm')
|
||||
expect(wp_target_custom).to be_wordpress
|
||||
end
|
||||
|
||||
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'))
|
||||
|
||||
expect(wp_target).to be_wordpress
|
||||
end
|
||||
|
||||
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'))
|
||||
|
||||
expect(wp_target).to be_wordpress
|
||||
end
|
||||
|
||||
it 'returns false if both files are not found (404)' do
|
||||
expect(wp_target).not_to 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.')
|
||||
|
||||
expect(wp_target).not_to be_wordpress
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the response is a 403' do
|
||||
before { stub_request(:any, /.*/).to_return(status: 403) }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { wp_target.wordpress? }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wordpress_hosted?' do
|
||||
it 'returns true if target url is a wordpress.com subdomain' do
|
||||
target = WpTarget.new('http://test.wordpress.com/')
|
||||
expect(target.wordpress_hosted?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns true if target url is a wordpress.com subdomain and has querystring' do
|
||||
target = WpTarget.new('http://test.wordpress.com/path/file.php?a=b')
|
||||
expect(target.wordpress_hosted?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if target url is not a wordpress.com subdomain' do
|
||||
target = WpTarget.new('http://test.example.com/')
|
||||
expect(target.wordpress_hosted?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#debug_log_url' do
|
||||
it "returns 'http://example.localhost/wp-content/debug.log" do
|
||||
allow(wp_target).to receive_messages(wp_content_dir: 'wp-content')
|
||||
expect(wp_target.debug_log_url).to be === 'http://example.localhost/wp-content/debug.log'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_debug_log?' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_TARGET_DIR + '/debug_log' }
|
||||
|
||||
after :each do
|
||||
allow(wp_target).to receive_messages(wp_content_dir: 'wp-content')
|
||||
stub_request_to_fixture(url: wp_target.debug_log_url, fixture: @fixture)
|
||||
expect(wp_target.has_debug_log?).to be === @expected
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
@fixture = SPEC_FIXTURES_DIR + '/empty-file'
|
||||
@expected = false
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@fixture = fixtures_dir + '/debug.log'
|
||||
@expected = true
|
||||
end
|
||||
|
||||
it 'should also detect it if there are PHP notice' do
|
||||
@fixture = fixtures_dir + '/debug-notice.log'
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#search_replace_db_2_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(wp_target.search_replace_db_2_url).to eq 'http://example.localhost/searchreplacedb2.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#search_replace_db_2_exists?' do
|
||||
it 'returns true' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 200, body: 'asdf by interconnect asdf')
|
||||
expect(wp_target.search_replace_db_2_exists?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500)
|
||||
expect(wp_target.search_replace_db_2_exists?).to be_falsey
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.search_replace_db_2_url).to_return(status: 500, body: 'asdf by interconnect asdf')
|
||||
expect(wp_target.search_replace_db_2_exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#emergency_url' do
|
||||
it 'returns the correct url' do
|
||||
expect(wp_target.emergency_url).to eq 'http://example.localhost/emergency.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#emergency_exists?' do
|
||||
it 'returns true' do
|
||||
stub_request(:any, wp_target.emergency_url).to_return(status: 200, body: 'enter your password here')
|
||||
expect(wp_target.emergency_exists?).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.emergency_url).to_return(status: 500)
|
||||
expect(wp_target.emergency_exists?).to be_falsey
|
||||
end
|
||||
|
||||
it 'returns false' do
|
||||
stub_request(:any, wp_target.emergency_url).to_return(status: 500, body: 'enter your password here')
|
||||
expect(wp_target.emergency_exists?).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,13 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require WPSCAN_LIB_DIR + '/wpscan_helper'
|
||||
|
||||
SPEC_FIXTURES_WPSCAN_DIR = SPEC_FIXTURES_DIR + '/wpscan'
|
||||
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'
|
||||
@@ -1,392 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require File.expand_path(File.join(__dir__, 'wpscan_helper'))
|
||||
|
||||
describe 'WpscanOptions' do
|
||||
|
||||
before :each do
|
||||
@wpscan_options = WpscanOptions.new
|
||||
end
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should set all options to nil' do
|
||||
WpscanOptions::ACCESSOR_OPTIONS.each do |option|
|
||||
expect(@wpscan_options.send(option)).to be === nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#url=' do
|
||||
it 'should raise an error if en empty or nil url is supplied' do
|
||||
expect { @wpscan_options.url = '' }.to raise_error
|
||||
expect { @wpscan_options.url = nil }.to raise_error
|
||||
end
|
||||
|
||||
it 'should add the http protocol if not present' do
|
||||
@wpscan_options.url = 'example.com'
|
||||
expect(@wpscan_options.url).to be === 'http://example.com'
|
||||
end
|
||||
|
||||
it "should not add the http protocol if it's already present" do
|
||||
url = 'http://example.com'
|
||||
@wpscan_options.url = url
|
||||
expect(@wpscan_options.url).to be === url
|
||||
end
|
||||
|
||||
it 'should encode IDN' do
|
||||
@wpscan_options.url = 'http://пример.испытание/'
|
||||
expect(@wpscan_options.url).to be === 'http://xn--e1afmkfd.xn--80akhbyknj4f/'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#threads=' do
|
||||
it 'should convert an integer in a string into an integr' do
|
||||
@wpscan_options.threads = '10'
|
||||
expect(@wpscan_options.threads).to be_an Integer
|
||||
expect(@wpscan_options.threads).to be === 10
|
||||
end
|
||||
|
||||
it 'should set to correct number of threads' do
|
||||
@wpscan_options.threads = 15
|
||||
expect(@wpscan_options.threads).to be_an Integer
|
||||
expect(@wpscan_options.threads).to be === 15
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wordlist=' do
|
||||
it 'should raise an error if the wordlist file does not exist' do
|
||||
expect { @wpscan_options.wordlist = '/i/do/not/exist.txt' }.to raise_error
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
wordlist_file = "#{SPEC_FIXTURES_WPSCAN_WPSCAN_OPTIONS_DIR}/wordlist.txt"
|
||||
|
||||
@wpscan_options.wordlist = wordlist_file
|
||||
expect(@wpscan_options.wordlist).to be === wordlist_file
|
||||
end
|
||||
end
|
||||
|
||||
describe '#proxy=' do
|
||||
it 'should raise an error' do
|
||||
expect { @wpscan_options.proxy = 'invalidproxy' }.to raise_error
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
proxy = '127.0.0.1:3038'
|
||||
@wpscan_options.proxy = proxy
|
||||
expect(@wpscan_options.proxy).to be === proxy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#proxy_auth=' do
|
||||
it 'should raise an error if the format is not correct' do
|
||||
expect { @wpscan_options.proxy_auth = 'invalidauth' }.to raise_error
|
||||
end
|
||||
|
||||
it 'should not raise en error' do
|
||||
proxy_auth = 'user:pass'
|
||||
@wpscan_options.proxy_auth = proxy_auth
|
||||
expect(@wpscan_options.proxy_auth).to be === proxy_auth
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_plugins=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_only_vulnerable_plugins = true
|
||||
expect { @wpscan_options.enumerate_plugins = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one plugin enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_only_vulnerable_plugins = false
|
||||
@wpscan_options.enumerate_plugins = true
|
||||
|
||||
expect(@wpscan_options.enumerate_plugins).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_themes=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_only_vulnerable_themes = true
|
||||
expect { @wpscan_options.enumerate_themes = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one theme enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_only_vulnerable_themes = false
|
||||
@wpscan_options.enumerate_themes = true
|
||||
|
||||
expect(@wpscan_options.enumerate_themes).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_only_vulnerable_plugins=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_plugins = true
|
||||
expect { @wpscan_options.enumerate_only_vulnerable_plugins = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one plugin enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_plugins = false
|
||||
@wpscan_options.enumerate_only_vulnerable_plugins = true
|
||||
|
||||
expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_only_vulnerable_themes=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_themes = true
|
||||
expect { @wpscan_options.enumerate_only_vulnerable_themes = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one theme enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_themes = false
|
||||
@wpscan_options.enumerate_only_vulnerable_themes = true
|
||||
|
||||
expect(@wpscan_options.enumerate_only_vulnerable_themes).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_all_themes=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_themes = true
|
||||
expect { @wpscan_options.enumerate_all_themes = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one theme enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_themes = false
|
||||
@wpscan_options.enumerate_all_themes = true
|
||||
|
||||
expect(@wpscan_options.enumerate_all_themes).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_all_plugins=' do
|
||||
it 'should raise an error' do
|
||||
@wpscan_options.enumerate_plugins = true
|
||||
expect { @wpscan_options.enumerate_all_plugins = true }.to raise_error(
|
||||
RuntimeError, 'Please choose only one plugin enumeration option'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should not raise an error' do
|
||||
@wpscan_options.enumerate_plugins = false
|
||||
@wpscan_options.enumerate_all_plugins = true
|
||||
|
||||
expect(@wpscan_options.enumerate_all_plugins).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_options?' do
|
||||
it 'should return false' do
|
||||
expect(@wpscan_options.has_options?).to be_falsey
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
@wpscan_options.verbose = false
|
||||
expect(@wpscan_options.has_options?).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_h' do
|
||||
it 'should return an empty hash' do
|
||||
expect(@wpscan_options.to_h).to be_a Hash
|
||||
expect(@wpscan_options.to_h).to be_empty
|
||||
end
|
||||
|
||||
it 'should return a hash with :verbose = true' do
|
||||
expected = {verbose: true}
|
||||
@wpscan_options.verbose = true
|
||||
|
||||
expect(@wpscan_options.to_h).to be === expected
|
||||
end
|
||||
end
|
||||
|
||||
describe '#clean_option' do
|
||||
after :each do
|
||||
expect(WpscanOptions.clean_option(@option)).to be === @expected
|
||||
end
|
||||
|
||||
it "should return 'url'" do
|
||||
@option = '--url'
|
||||
@expected = 'url'
|
||||
end
|
||||
|
||||
it "should return 'u'" do
|
||||
@option = '-u'
|
||||
@expected = 'u'
|
||||
end
|
||||
|
||||
it "should return 'follow_redirection'" do
|
||||
@option = '--follow-redirection'
|
||||
@expected = 'follow_redirection'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#option_to_instance_variable_setter' do
|
||||
after :each do
|
||||
expect(WpscanOptions.option_to_instance_variable_setter(@argument)).to be === @expected
|
||||
end
|
||||
|
||||
it 'should return :url=' do
|
||||
@argument = '--url'
|
||||
@expected = :url=
|
||||
end
|
||||
|
||||
it 'should return :verbose=' do
|
||||
@argument = '--verbose'
|
||||
@expected = :verbose=
|
||||
end
|
||||
|
||||
it 'should return :proxy= for --proxy' do
|
||||
@argument = '--proxy'
|
||||
@expected = :proxy=
|
||||
end
|
||||
|
||||
it 'should return nil for --enumerate' do
|
||||
@argument = '--enumerate'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return :proxy_auth= for --proxy_auth' do
|
||||
@argument = '--proxy_auth'
|
||||
@expected = :proxy_auth=
|
||||
end
|
||||
end
|
||||
|
||||
describe '#is_long_option?' do
|
||||
it 'should return true' do
|
||||
expect(WpscanOptions.is_long_option?('--url')).to be_truthy
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
expect(WpscanOptions.is_long_option?('hello')).to be_falsey
|
||||
expect(WpscanOptions.is_long_option?('--enumerate')).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '#enumerate_options_from_string' do
|
||||
after :each do
|
||||
if @argument
|
||||
wpscan_options = WpscanOptions.new
|
||||
wpscan_options.enumerate_options_from_string(@argument)
|
||||
expect(wpscan_options.to_h).to be === @expected_hash
|
||||
end
|
||||
end
|
||||
|
||||
it 'should raise an error if p and p! are ' do
|
||||
expect { @wpscan_options.enumerate_options_from_string('p,vp') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should set enumerate_plugins to true' do
|
||||
@argument = 'p'
|
||||
@expected_hash = {enumerate_plugins: true}
|
||||
end
|
||||
|
||||
it 'should set enumerate_only_vulnerable_plugins to tue' do
|
||||
@argument = 'vp'
|
||||
@expected_hash = {enumerate_only_vulnerable_plugins: true}
|
||||
end
|
||||
|
||||
it 'should set enumerate_timthumbs to true' do
|
||||
@argument = 'tt'
|
||||
@expected_hash = {enumerate_timthumbs: true}
|
||||
end
|
||||
|
||||
it 'should set enumerate_usernames to true' do
|
||||
@argument = 'u'
|
||||
@expected_hash = {enumerate_usernames: true}
|
||||
end
|
||||
|
||||
it 'should set enumerate_usernames to true and enumerate_usernames_range to (1..20)' do
|
||||
@argument = 'u[1-20]'
|
||||
@expected_hash = {enumerate_usernames: true, enumerate_usernames_range: (1..20)}
|
||||
end
|
||||
|
||||
# Let's try some multiple choices
|
||||
it 'should set enumerate_timthumbs to true, enumerate_usernames to true, enumerate_usernames_range to (1..2)' do
|
||||
@argument = 'u[1-2],tt'
|
||||
@expected_hash = {
|
||||
enumerate_usernames: true, enumerate_usernames_range: (1..2),
|
||||
enumerate_timthumbs: true
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe '#set_option_from_cli' do
|
||||
it 'should raise an error with unknow option' do
|
||||
expect { @wpscan_options.set_option_from_cli('hello', '') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should set @url to example.com' do
|
||||
@wpscan_options.set_option_from_cli('--url', 'example.com')
|
||||
expect(@wpscan_options.url).to be === 'http://example.com'
|
||||
end
|
||||
|
||||
it 'should set @enumerate_plugins to true' do
|
||||
@wpscan_options.set_option_from_cli('--enumerate', 'p')
|
||||
expect(@wpscan_options.enumerate_plugins).to be_truthy
|
||||
expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_nil
|
||||
end
|
||||
|
||||
it 'should set @enumerate_only_vulnerable_plugins, @enumerate_timthumbs and @enumerate_usernames to true if no argument is given' do
|
||||
@wpscan_options.set_option_from_cli('--enumerate', '')
|
||||
expect(@wpscan_options.enumerate_only_vulnerable_plugins).to be_truthy
|
||||
expect(@wpscan_options.enumerate_timthumbs).to be_truthy
|
||||
expect(@wpscan_options.enumerate_usernames).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load_from_arguments' do
|
||||
after :each do
|
||||
set_argv(@argv)
|
||||
wpscan_options = WpscanOptions.load_from_arguments
|
||||
expect(wpscan_options.to_h).to be === @expected_hash
|
||||
end
|
||||
|
||||
it 'should return {}' do
|
||||
@argv = ''
|
||||
@expected_hash = {}
|
||||
end
|
||||
|
||||
it "should return {:url => 'example.com'}" do
|
||||
@argv = '--url example.com'
|
||||
@expected_hash = { url: 'http://example.com' }
|
||||
end
|
||||
|
||||
it "should return {:url => 'example.com'}" do
|
||||
@argv = '-u example.com'
|
||||
@expected_hash = { url: 'http://example.com' }
|
||||
end
|
||||
|
||||
it "should return {:username => 'admin'}" do
|
||||
@argv = '--username admin'
|
||||
@expected_hash = { username: 'admin' }
|
||||
end
|
||||
|
||||
it "should return {:username => 'Youhou'}" do
|
||||
@argv = '-U Youhou'
|
||||
@expected_hash = { username: 'Youhou' }
|
||||
end
|
||||
|
||||
it "should return {:url => 'example.com', :threads => 5, :force => ''}" do
|
||||
@argv = '-u example.com --force -t 5'
|
||||
@expected_hash = { url: 'http://example.com', threads: 5, force: '' }
|
||||
end
|
||||
|
||||
it "should return {:url => 'example.com', :enumerate_plugins => true, :enumerate_timthumbs => true}" do
|
||||
@argv = '-u example.com -e p,tt'
|
||||
@expected_hash = { url: 'http://example.com', enumerate_plugins: true, enumerate_timthumbs: true }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user