New enumeration system
This commit is contained in:
@@ -1,76 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '../../../lib/wpscan/wpscan_helper')
|
||||
|
||||
describe 'common_helper' do
|
||||
describe '#get_equal_string' do
|
||||
after :each do
|
||||
output = get_equal_string_end(@input)
|
||||
|
||||
output.should == @expected
|
||||
end
|
||||
|
||||
it 'sould return an empty string' do
|
||||
@input = ['']
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'sould return an empty string' do
|
||||
@input = []
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'sould return asdf' do
|
||||
@input = ['kjh asdf', 'oijr asdf']
|
||||
@expected = ' asdf'
|
||||
end
|
||||
|
||||
it 'sould return « BlogName' do
|
||||
@input = ['user1 « BlogName',
|
||||
'user2 « BlogName',
|
||||
'user3 « BlogName',
|
||||
'user4 « BlogName']
|
||||
@expected = ' « BlogName'
|
||||
end
|
||||
|
||||
it 'sould return an empty string' do
|
||||
@input = %w{user1 user2 user3 user4}
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'sould return an empty string' do
|
||||
@input = ['user1 « BlogName',
|
||||
'user2 « BlogName',
|
||||
'user3 « BlogName',
|
||||
'user4 « BlogNamea']
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'sould return an empty string' do
|
||||
@input = %w{ user1 }
|
||||
@expected = ''
|
||||
end
|
||||
|
||||
it 'sould return | test' do
|
||||
@input = ['admin | test', 'test | test']
|
||||
@expected = ' | test'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -59,7 +59,7 @@ shared_examples_for 'BruteForce' do
|
||||
)
|
||||
end
|
||||
|
||||
user = WpUser.new('admin', 1, nil)
|
||||
user = WpUser.new(@module.uri, login: 'admin')
|
||||
result = @module.brute_force([user], @wordlist)
|
||||
|
||||
result.length.should == 1
|
||||
@@ -69,7 +69,7 @@ shared_examples_for 'BruteForce' do
|
||||
it 'should cover the timeout branch and return an empty array' do
|
||||
stub_request(:post, @module.login_url).to_timeout
|
||||
|
||||
user = WpUser.new('admin', 1, nil)
|
||||
user = WpUser.new(@module.uri, login: 'admin')
|
||||
result = @module.brute_force([user], @wordlist)
|
||||
result.should == []
|
||||
end
|
||||
|
||||
@@ -22,6 +22,7 @@ shared_examples_for 'WpLoginProtection' do
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new('http://example.localhost')
|
||||
@module.extend(WpLoginProtection)
|
||||
@module.stub(:wp_plugins_dir).and_return('wp-content/plugins')
|
||||
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_login_protection'
|
||||
end
|
||||
@@ -70,10 +71,10 @@ shared_examples_for 'WpLoginProtection' do
|
||||
expected = plugin_name_from_fixture === plugin_name_from_symbol ? true : false
|
||||
|
||||
it "#{symbol_to_call} with #{fixture} should return #{expected}" do
|
||||
@plugin_name = plugin_name_from_fixture
|
||||
@fixture = @fixtures_dir + '/' + fixture
|
||||
@plugin_name = plugin_name_from_fixture
|
||||
@fixture = @fixtures_dir + '/' + fixture
|
||||
@symbol_to_call = symbol_to_call
|
||||
@expected = expected
|
||||
@expected = expected
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -89,33 +90,25 @@ shared_examples_for 'WpLoginProtection' do
|
||||
stub_request(:get, @module.send(:limit_login_attempts_url).to_s).to_return(status: 404)
|
||||
stub_request(:get, @module.send(:bluetrait_event_viewer_url).to_s).to_return(status: 404)
|
||||
|
||||
@module.login_protection_plugin().should === @plugin_expected
|
||||
@module.login_protection_plugin().should == @plugin_expected
|
||||
@module.has_login_protection?.should === @has_protection_expected
|
||||
end
|
||||
|
||||
it 'should return nil if no protection is present' do
|
||||
@fixture = @fixtures_dir + '/wp-login-clean.php'
|
||||
@plugin_expected = nil
|
||||
@fixture = @fixtures_dir + '/wp-login-clean.php'
|
||||
@plugin_expected = nil
|
||||
@has_protection_expected = false
|
||||
end
|
||||
|
||||
it 'should return a login-lockdown WpPlugin object' do
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lockdown.php'
|
||||
@plugin_expected = WpPlugin.new(
|
||||
base_url: @module.url,
|
||||
path: '/plugins/login-lockdown/',
|
||||
name: 'login-lockdown'
|
||||
)
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lockdown.php'
|
||||
@plugin_expected = WpPlugin.new(@module.uri, name: 'login-lockdown')
|
||||
@has_protection_expected = true
|
||||
end
|
||||
|
||||
it 'should return a login-lock WpPlugin object' do
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lock.php'
|
||||
@plugin_expected = WpPlugin.new(
|
||||
base_url: @module.url,
|
||||
path: '/plugins/login-lock/',
|
||||
name: 'login-lock'
|
||||
)
|
||||
@fixture = @fixtures_dir + '/wp-login-login_lock.php'
|
||||
@plugin_expected = WpPlugin.new(@module.uri, name: 'login-lock')
|
||||
@has_protection_expected = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
shared_examples_for 'WpPlugins' do
|
||||
|
||||
before :all do
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_plugins'
|
||||
@plugins_file = @fixtures_dir + '/plugins.txt'
|
||||
@plugin_vulns_file = @fixtures_dir + '/plugin_vulns.xml'
|
||||
|
||||
@wp_url = 'http://example.localhost/'
|
||||
end
|
||||
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new(@wp_url)
|
||||
@module.error_404_hash = Digest::MD5.hexdigest('Error 404!')
|
||||
@module.homepage_hash = Digest::MD5.hexdigest('Homepage!')
|
||||
@module.extend(WpPlugins)
|
||||
|
||||
@options = {
|
||||
base_url: @wp_url,
|
||||
only_vulnerable_ones: false,
|
||||
show_progression: false,
|
||||
error_404_hash: @module.error_404_hash,
|
||||
homepage_hash: @module.homepage_hash,
|
||||
vulns_file: @plugin_vulns_file,
|
||||
file: @plugins_file,
|
||||
type: 'plugins',
|
||||
wp_content_dir: 'wp-content',
|
||||
vulns_xpath_2: '//plugin'
|
||||
}
|
||||
File.exist?(@plugin_vulns_file).should == true
|
||||
File.exist?(@plugins_file).should == true
|
||||
|
||||
# These targets are listed in @fixtures_dir + '/plugins.txt'
|
||||
# TODO : load them directly from the fixture file
|
||||
@targets = [
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'exclude-pages/exclude_pages.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'exclude-pages'
|
||||
}),
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'display-widgets/display-widgets.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'display-widgets'
|
||||
}),
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'media-library',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'media-library'
|
||||
}),
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'deans',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'deans'
|
||||
}),
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'formidable/formidable.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'formidable'
|
||||
}),
|
||||
WpPlugin.new(
|
||||
{
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'regenerate-thumbnails/readme.txt',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'regenerate-thumbnails'
|
||||
})
|
||||
]
|
||||
end
|
||||
|
||||
describe '#plugins_from_passive_detection' do
|
||||
let(:passive_detection_fixtures) { @fixtures_dir + '/passive_detection' }
|
||||
|
||||
it 'should return an empty array' do
|
||||
stub_request_to_fixture(url: @module.url, fixture: File.new(passive_detection_fixtures + '/no_plugins.htm'))
|
||||
plugins = @module.plugins_from_passive_detection(base_url: @module.url, wp_content_dir: 'wp-content')
|
||||
plugins.should be_empty
|
||||
end
|
||||
|
||||
it 'should return the expected plugins' do
|
||||
stub_request_to_fixture(url: @module.url, fixture: File.new(passive_detection_fixtures + '/various_plugins.htm'))
|
||||
|
||||
expected_plugin_names = %w{
|
||||
wp-minify
|
||||
comment-info-tip
|
||||
tweet-blender
|
||||
optinpop
|
||||
s2member
|
||||
wp-polls
|
||||
commentluv
|
||||
}
|
||||
expected_plugins = []
|
||||
expected_plugin_names.each do |plugin_name|
|
||||
expected_plugins << WpPlugin.new(
|
||||
base_url: @module.url,
|
||||
path: "/plugins/#{plugin_name}/",
|
||||
name: plugin_name
|
||||
)
|
||||
end
|
||||
|
||||
plugins = @module.plugins_from_passive_detection(base_url: @module.url, wp_content_dir: 'wp-content')
|
||||
plugins.should_not be_empty
|
||||
plugins.length.should == expected_plugins.length
|
||||
plugins.sort.should == expected_plugins.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe '#plugins_from_aggressive_detection' do
|
||||
|
||||
before :each do
|
||||
stub_request(:get, @module.uri.to_s).to_return(status: 200)
|
||||
# Point all targets to a 404
|
||||
@targets.each do |target|
|
||||
stub_request(:get, target.get_full_url.to_s).to_return(status: 404)
|
||||
# to_s calls readme_url
|
||||
stub_request(:get, target.readme_url.to_s).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
after :each do
|
||||
@passive_detection_fixture = SPEC_FIXTURES_DIR + '/empty-file' unless @passive_detection_fixture
|
||||
stub_request_to_fixture(url: "#{@module.uri}/".sub(/\/\/$/, '/'), fixture: @passive_detection_fixture)
|
||||
detected = @module.plugins_from_aggressive_detection(@options)
|
||||
detected.length.should == @expected_plugins.length
|
||||
detected.sort.should == @expected_plugins.sort
|
||||
end
|
||||
|
||||
it 'should return an empty array' do
|
||||
@expected_plugins = []
|
||||
end
|
||||
|
||||
it 'should return an array with 3 WpPlugin (1 detected from passive method)' do
|
||||
@passive_detection_fixture = @fixtures_dir + '/passive_detection/one_plugin.htm'
|
||||
@expected_plugins = @targets.sample(2)
|
||||
@expected_plugins.each do |p|
|
||||
stub_request(:get, p.get_full_url.to_s).to_return(status: 200)
|
||||
end
|
||||
new_plugin = WpPlugin.new(
|
||||
base_url: 'http://example.localhost/',
|
||||
path: '/plugins/comment-info-tip/',
|
||||
name: 'comment-info-tip'
|
||||
)
|
||||
stub_request(:get, new_plugin.readme_url.to_s).to_return(status: 200)
|
||||
@expected_plugins << new_plugin
|
||||
end
|
||||
|
||||
# testing response codes
|
||||
WpTarget.valid_response_codes.each do |valid_response_code|
|
||||
it "should detect the plugin if the reponse.code is #{valid_response_code}" do
|
||||
@expected_plugins = []
|
||||
plugin_url = [@targets.sample(1)[0]]
|
||||
plugin_url.should_not be_nil
|
||||
plugin_url.length.should == 1
|
||||
@expected_plugins = plugin_url
|
||||
stub_request(:get, plugin_url[0].get_full_url.to_s).to_return(status: valid_response_code)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should not detect the plugin if there is a redirection to the homepage' do
|
||||
# Let's pick up 2 plugins (The first one will redirect to the homepage)
|
||||
plugins = @targets.sample(2)
|
||||
stub_request(:get, plugins[0].get_full_url.to_s).to_return(status: 200, body: 'Homepage!')
|
||||
stub_request(:get, plugins[1].get_full_url.to_s).to_return(status: 200)
|
||||
|
||||
@expected_plugins = [plugins[1]]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,211 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
shared_examples_for 'WpThemes' do
|
||||
|
||||
before :all do
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_themes'
|
||||
@themes_file = @fixtures_dir + '/themes.txt'
|
||||
@theme_vulns_file = @fixtures_dir + '/theme_vulns.xml'
|
||||
|
||||
@wp_url = 'http://example.localhost/'
|
||||
end
|
||||
|
||||
before :each do
|
||||
@module = WpScanModuleSpec.new(@wp_url)
|
||||
@module.error_404_hash = Digest::MD5.hexdigest('Error 404!')
|
||||
@module.extend(WpThemes)
|
||||
|
||||
@options = {
|
||||
base_url: @wp_url,
|
||||
only_vulnerable_ones: false,
|
||||
show_progression: false,
|
||||
error_404_hash: Digest::MD5.hexdigest('Error 404!'),
|
||||
vulns_file: @theme_vulns_file,
|
||||
file: @themes_file,
|
||||
type: 'themes',
|
||||
wp_content_dir: 'wp-content',
|
||||
vulns_xpath_2: '//theme'
|
||||
}
|
||||
File.exist?(@theme_vulns_file).should == true
|
||||
File.exist?(@themes_file).should == true
|
||||
@targets = [
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zenpro/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zenpro'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zeta-zip/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zeta-zip'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zfirst/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zfirst'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zgrey/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zgrey'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zindi-ii/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zindi-ii'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zindi/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zindi'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zombie-apocalypse/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zombie-apocalypse'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zsofa/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zsofa'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'zwei-seiten/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'zwei-seiten'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'twentyten/404.php',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'twentyten'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'shopperpress',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'shopperpress'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'wise',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'wise'
|
||||
}),
|
||||
WpTheme.new({
|
||||
base_url: 'http://example.localhost/',
|
||||
path: 'webfolio',
|
||||
wp_content_dir: 'wp-content',
|
||||
name: 'webfolio'
|
||||
})
|
||||
]
|
||||
end
|
||||
|
||||
describe '#themes_from_passive_detection' do
|
||||
let(:passive_detection_fixtures) { @fixtures_dir + '/passive_detection' }
|
||||
|
||||
it 'should return an empty array' do
|
||||
stub_request_to_fixture(url: @module.url, fixture: File.new(passive_detection_fixtures + '/no_theme.htm'))
|
||||
themes = @module.themes_from_passive_detection(base_url: @module.url, wp_content_dir: 'wp-content')
|
||||
themes.should be_empty
|
||||
end
|
||||
|
||||
it 'should return the expected themes' do
|
||||
stub_request_to_fixture(url: @module.url, fixture: File.new(passive_detection_fixtures + '/various_themes.htm'))
|
||||
|
||||
expected_theme_names = %w{ theme1 theme2 theme3 }
|
||||
expected_themes = []
|
||||
expected_theme_names.each do |theme_name|
|
||||
expected_themes << WpTheme.new(
|
||||
base_url: @module.url,
|
||||
path: "/themes/#{theme_name}/",
|
||||
name: theme_name
|
||||
)
|
||||
end
|
||||
|
||||
themes = @module.themes_from_passive_detection(base_url: @module.url, wp_content_dir: 'wp-content')
|
||||
themes.should_not be_empty
|
||||
themes.length.should == expected_themes.length
|
||||
themes.sort.should == expected_themes.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe '#themes_from_aggressive_detection' do
|
||||
|
||||
before :each do
|
||||
stub_request(:get, @module.uri.to_s).to_return(status: 200)
|
||||
# Point all targets to a 404
|
||||
@targets.each do |target|
|
||||
stub_request(:get, target.get_full_url.to_s).to_return(status: 404)
|
||||
# to_s calls readme_url
|
||||
stub_request(:get, target.readme_url.to_s).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
after :each do
|
||||
@passive_detection_fixture = SPEC_FIXTURES_DIR + '/empty-file' unless @passive_detection_fixture
|
||||
stub_request_to_fixture(url: "#{@module.uri}/".sub(/\/\/$/, '/'), fixture: @passive_detection_fixture)
|
||||
detected = @module.themes_from_aggressive_detection(@options)
|
||||
detected.length.should == @expected_themes.length
|
||||
detected.sort.should == @expected_themes.sort
|
||||
end
|
||||
|
||||
it 'should return an empty array' do
|
||||
@expected_themes = []
|
||||
end
|
||||
|
||||
it 'should return an array with 3 WpTheme (1 detected from passive method)' do
|
||||
@passive_detection_fixture = @fixtures_dir + '/passive_detection/one_theme.htm'
|
||||
@expected_themes = @targets.sample(2)
|
||||
@expected_themes.each do |p|
|
||||
stub_request(:get, p.get_full_url.to_s).to_return(status: 200)
|
||||
end
|
||||
new_theme = WpTheme.new(
|
||||
base_url: 'http://example.localhost/',
|
||||
path: '/themes/custom-twentyten/',
|
||||
name: 'custom-twentyten'
|
||||
)
|
||||
stub_request(:get, new_theme.readme_url.to_s).to_return(status: 200)
|
||||
@expected_themes << new_theme
|
||||
end
|
||||
|
||||
# testing response codes
|
||||
WpTarget.valid_response_codes.each do |valid_response_code|
|
||||
it "should detect the theme if the reponse.code is #{valid_response_code}" do
|
||||
@expected_themes = []
|
||||
theme_url = [@targets.sample(1)[0]]
|
||||
theme_url.should_not be_nil
|
||||
theme_url.length.should == 1
|
||||
@expected_themes = theme_url
|
||||
stub_request(:get, theme_url[0].get_full_url.to_s).to_return(status: valid_response_code)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,115 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
shared_examples_for 'WpTimthumbs' do
|
||||
|
||||
before :each do
|
||||
@options = {}
|
||||
@url = 'http://example.localhost/'
|
||||
@theme_name = 'bueno'
|
||||
@options[:base_url] = @url
|
||||
@options[:wp_content_dir] = 'wp-content'
|
||||
@options[:name] = @theme_name
|
||||
@options[:error_404_hash] = 'xx'
|
||||
@options[:show_progression] = false
|
||||
@options[:only_vulnerable_ones] = false
|
||||
@options[:vulns_file] = 'xx'
|
||||
@options[:type] = 'timthumbs'
|
||||
@module = WpScanModuleSpec.new(@url)
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_timthumbs'
|
||||
@timthumbs_file = @fixtures_dir + '/timthumbs.txt'
|
||||
@targets_from_file = %w{
|
||||
http://example.localhost/wp-content/plugins/fotoslide/timthumb.php
|
||||
http://example.localhost/wp-content/plugins/feature-slideshow/timthumb.php
|
||||
}
|
||||
@targets_from_theme =
|
||||
[
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/lib/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/inc/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/includes/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/scripts/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/tools/timthumb.php',
|
||||
'http://example.localhost/wp-content/themes/' + @theme_name + '/functions/timthumb.php'
|
||||
]
|
||||
|
||||
@module.extend(WpTimthumbs)
|
||||
end
|
||||
|
||||
describe '#targets_url_from_theme' do
|
||||
it 'should return the targets for the theme' do
|
||||
targets = @module.send(:targets_url_from_theme, @theme_name, @options)
|
||||
|
||||
targets.should_not be_empty
|
||||
targets.length.should > 0
|
||||
temp = []
|
||||
targets.each do |t|
|
||||
temp << t.get_full_url.to_s
|
||||
end
|
||||
temp.sort.should === @targets_from_theme.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe '#timthumbs and #has_timthumbs?' do
|
||||
before :each do
|
||||
@options[:file] = @timthumbs_file
|
||||
@targets_from_file.each do |url|
|
||||
stub_request(:get, url).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return an empty array' do
|
||||
timthumbs = @module.timthumbs(nil, @options)
|
||||
timthumbs.should be_empty
|
||||
@module.has_timthumbs?(nil, @options).should be_false
|
||||
end
|
||||
|
||||
it 'should return an array with 7 elements (from passive detection)' do
|
||||
stub_request(:get, %r{http://example\.localhost/wp-content/themes/my-theme/.*}).to_return(status: 200)
|
||||
timthumbs = @module.timthumbs('my-theme', @options)
|
||||
timthumbs.length.should == 7
|
||||
end
|
||||
|
||||
it 'should return an array with 2 timthumbs url' do
|
||||
expected = []
|
||||
urls = []
|
||||
urls_hash = WpEnumerator.generate_items(@options)
|
||||
urls_hash.each do |u|
|
||||
url = u.get_full_url.to_s
|
||||
urls << url
|
||||
stub_request(:get, url).to_return(status: 404)
|
||||
end
|
||||
urls.sample(2).each do |target_url|
|
||||
expected << target_url
|
||||
stub_request(:get, target_url).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/timthumb.php'))
|
||||
end
|
||||
|
||||
timthumbs = @module.timthumbs(nil, @options)
|
||||
timthumbs.should_not be_empty
|
||||
|
||||
temp = []
|
||||
timthumbs.each do |t|
|
||||
temp << t.get_full_url.to_s
|
||||
end
|
||||
temp.sort.should === expected.sort
|
||||
@module.has_timthumbs?(nil).should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,279 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
shared_examples_for 'WpUsernames' do
|
||||
|
||||
before :each do
|
||||
@target_url = 'http://example.localhost/'
|
||||
@module = WpScanModuleSpec.new(@target_url)
|
||||
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + '/wp_usernames'
|
||||
|
||||
@module.extend(WpUsernames)
|
||||
end
|
||||
|
||||
describe '#author_url' do
|
||||
it 'should return the auhor url according to his id' do
|
||||
@module.author_url(1).should === "#@target_url?author=1"
|
||||
end
|
||||
end
|
||||
|
||||
describe '#usernames' do
|
||||
before :each do
|
||||
(1..10).each do |index|
|
||||
stub_request(:get, @module.author_url(index)).to_return(status: 404)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return an empty array' do
|
||||
@module.usernames.should be_empty
|
||||
end
|
||||
|
||||
it 'should return an array with 1 username (from header location)' do
|
||||
stub_request(:get, @module.author_url(3)).
|
||||
to_return(status: 301, headers: {'location' => '/author/Youhou'})
|
||||
|
||||
usernames = @module.usernames
|
||||
usernames.should_not be_empty
|
||||
usernames.length.should == 1
|
||||
usernames[0].id.should == 3
|
||||
usernames[0].name.should == 'Youhou'
|
||||
usernames[0].nickname.should == 'empty'
|
||||
end
|
||||
|
||||
it 'should return an array with 1 username (from in the body response)' do
|
||||
stub_request(:get, @module.author_url(2)).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/test.html'))
|
||||
|
||||
usernames = @module.usernames(range: (1..2))
|
||||
usernames.should_not be_empty
|
||||
usernames.should === ([WpUser.new('test', 2, 'first last | user's Blog!')])
|
||||
end
|
||||
|
||||
it 'should return an array with 2 usernames (one is a duplicate and should not be present twice)' do
|
||||
stub_request(:get, @module.author_url(4)).
|
||||
to_return(status: 301, headers: {'location' => '/author/Youhou/'})
|
||||
|
||||
stub_request(:get, @module.author_url(2)).
|
||||
to_return(status: 200, body: File.new(@fixtures_dir + '/test.html'))
|
||||
|
||||
usernames = @module.usernames(range: (1..5))
|
||||
usernames.should_not be_empty
|
||||
expected = [
|
||||
WpUser.new('test', 2, 'first last | user's Blog!'),
|
||||
WpUser.new('Youhou', 4, 'empty')
|
||||
]
|
||||
|
||||
usernames.sort_by { |u| u.name }.should === expected.sort_by { |u| u.name }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_nickname_from_url' do
|
||||
after :each do
|
||||
url = 'http://example.localhost/'
|
||||
stub_request(:get, url).to_return(status: @status, body: @content)
|
||||
username = @module.get_nickname_from_url(url)
|
||||
username.should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 200
|
||||
@content = ''
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 400
|
||||
@content = ''
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return admin' do
|
||||
@status = 200
|
||||
@content = '<title>admin</title>'
|
||||
@expected = 'admin'
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 201
|
||||
@content = '<title>admin</title>'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_nickname_from_response' do
|
||||
after :each do
|
||||
url = 'http://example.localhost/'
|
||||
stub_request(:get, url).to_return(status: @status, body: @content)
|
||||
resp = Browser.instance.get(url)
|
||||
nickname = @module.get_nickname_from_response(resp)
|
||||
nickname.should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 200
|
||||
@content = ''
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 400
|
||||
@content = ''
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return admin' do
|
||||
@status = 200
|
||||
@content = '<title>admin</title>'
|
||||
@expected = 'admin'
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@status = 201
|
||||
@content = '<title>admin</title>'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_username_from_response' do
|
||||
after :each do
|
||||
url = @module.url
|
||||
stub_request_to_fixture(url: url, fixture: File.new(@fixtures_dir + @file))
|
||||
resp = Browser.instance.get(url)
|
||||
username = @module.get_username_from_response(resp)
|
||||
username.should === @expected
|
||||
end
|
||||
|
||||
# No Permalinks
|
||||
it 'should return admin' do
|
||||
@file = '/admin.html'
|
||||
@expected = 'admin'
|
||||
end
|
||||
|
||||
# With Permalinks
|
||||
it 'should return test' do
|
||||
@file = '/test.html'
|
||||
@expected = 'test'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#extract_nickname_from_body' do
|
||||
after :each do
|
||||
result = @module.extract_nickname_from_body(@body)
|
||||
result.should === @expected
|
||||
end
|
||||
|
||||
it 'should return admin' do
|
||||
@body = '<title>admin</title>'
|
||||
@expected = 'admin'
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@body = '<title>adm<in</title>'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@body = '<titler>admin</titler>'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return admin | ' do
|
||||
@body = '<title>admin | </title>'
|
||||
@expected = 'admin | '
|
||||
end
|
||||
|
||||
it 'should return an empty string' do
|
||||
@body = '<title></title>'
|
||||
@expected = ''
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_junk_from_nickname' do
|
||||
it 'should throw an exception' do
|
||||
@input = nil
|
||||
expect { @module.remove_junk_from_nickname(@input) }.to raise_error(RuntimeError, 'Need an array as input')
|
||||
end
|
||||
|
||||
it 'should not throw an exception' do
|
||||
@input = []
|
||||
expect { @module.remove_junk_from_nickname(@input) }.to_not raise_error
|
||||
end
|
||||
|
||||
it 'should throw an exception' do
|
||||
@input = [WpOptions.new]
|
||||
expect { @module.remove_junk_from_nickname(@input) }.to raise_error(RuntimeError, 'Items must be of type WpUser')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_junk_from_nickname' do
|
||||
after :each do
|
||||
result = @module.remove_junk_from_nickname(@input)
|
||||
result.should === @expected
|
||||
end
|
||||
|
||||
it 'should return an empty array' do
|
||||
@input = []
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should return input object' do
|
||||
@input = [WpUser.new(nil, nil, nil)]
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should return input object' do
|
||||
@input = [WpUser.new('', '', '')]
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should remove asdf' do
|
||||
@input = [WpUser.new(nil, nil, 'lkjh asdf'), WpUser.new(nil, nil, 'ijrjd asdf')]
|
||||
@expected = [WpUser.new(nil, nil, 'lkjh'), WpUser.new(nil, nil, 'ijrjd')]
|
||||
end
|
||||
|
||||
it 'should return unmodified input object' do
|
||||
@input = [WpUser.new(nil, nil, 'lkjh asdfa'), WpUser.new(nil, nil, 'ijrjd asdf')]
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should return input object' do
|
||||
@input = [WpUser.new(nil, nil, 'lkjh asdf')]
|
||||
@expected = @input
|
||||
end
|
||||
|
||||
it 'should return lkhj asdf' do
|
||||
@input = [WpUser.new(nil, nil, 'lkhj asdf'), WpUser.new(nil, nil, 'lkhj asdf')]
|
||||
@expected = [WpUser.new(nil, nil, ''), WpUser.new(nil, nil, '')]
|
||||
end
|
||||
end
|
||||
|
||||
# Issue 66
|
||||
describe '#remove_junk_from_nickname' do
|
||||
it 'should contain the string empty' do
|
||||
input = [WpUser.new('admin', 1, 'admin | Wordpress 3.4.2'), WpUser.new('', 2, 'Wordpress 3.4.2')]
|
||||
result = @module.remove_junk_from_nickname(input)
|
||||
result[0].nickname.should === 'admin | '
|
||||
result[0].name.should === 'admin'
|
||||
result[0].id.should === 1
|
||||
result[1].nickname.should === 'empty'
|
||||
result[1].name.should === 'empty'
|
||||
result[1].id.should === 2
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,24 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpDetector do
|
||||
# TODO
|
||||
end
|
||||
@@ -1,24 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpEnumerator do
|
||||
# TODO
|
||||
end
|
||||
@@ -1,587 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpPlugin do
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should create a correct instance' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
instance.wp_content_dir.should == 'wp-content'
|
||||
instance.base_url.should == 'http://sub.example.com/path/to/wordpress/'
|
||||
instance.path.should == 'test/asdf.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_full_url' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins',
|
||||
wp_content_dir: @wp_content_dir
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
instance.get_full_url.to_s.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the correct url' do
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test/asdf.php'
|
||||
end
|
||||
|
||||
it 'should return the correct url (custom wp_content_dir)' do
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/asdf.php'
|
||||
end
|
||||
|
||||
it 'should trim / and add missing / before concatenating url' do
|
||||
@wp_content_dir = '/custom/'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/asdf.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_url_without_filename' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: @base_url || 'http://sub.example.com/path/to/wordpress/',
|
||||
path: @path || 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins',
|
||||
wp_content_dir: @wp_content_dir
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
instance.get_url_without_filename.to_s.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the correct url' do
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test/'
|
||||
end
|
||||
|
||||
it 'should return the correct url (custom wp_content_dir)' do
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/'
|
||||
end
|
||||
|
||||
it 'should trim / and add missing / before concatenating url' do
|
||||
@wp_content_dir = '/custom/'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/'
|
||||
end
|
||||
|
||||
it 'should not remove the last foldername' do
|
||||
@path = 'test/'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test/'
|
||||
end
|
||||
|
||||
it 'should return the correct url (https)' do
|
||||
@base_url = 'https://sub.example.com/path/to/wordpress/'
|
||||
@expected = 'https://sub.example.com/path/to/wordpress/wp-content/plugins/test/'
|
||||
end
|
||||
|
||||
it "should add the last slash if it's not present" do
|
||||
@path = 'test-one'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test-one/'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR + '/version' }
|
||||
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return a version number' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 200, body: 'Stable tag: 1.2.4.3.2.1')
|
||||
@instance.version.should == '1.2.4.3.2.1'
|
||||
end
|
||||
|
||||
it 'should not return a version number' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 200, body: 'Stable tag: trunk')
|
||||
@instance.version.should be nil
|
||||
end
|
||||
|
||||
it 'should return nil if the version is invalid (IE : trunk etc)' do
|
||||
stub_request_to_fixture(url: @instance.readme_url.to_s, fixture: fixtures_dir + '/trunk-version.txt')
|
||||
@instance.version.should be_nil
|
||||
end
|
||||
|
||||
it 'should return the version 0.4' do
|
||||
stub_request_to_fixture(url: @instance.readme_url.to_s, fixture: fixtures_dir + '/simple-login-lockdown-0.4.txt')
|
||||
@instance.version.should === '0.4'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#directory_listing?' do
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:get, @instance.get_url_without_filename.to_s)
|
||||
.to_return(status: 200, body: '<html><head><title>Index of asdf</title></head></html>')
|
||||
|
||||
@instance.directory_listing?.should == true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:get, @instance.get_url_without_filename.to_s)
|
||||
.to_return(status: 200, body: '<html><head><title>My Wordpress Site</title></head></html>')
|
||||
|
||||
@instance.directory_listing?.should == false
|
||||
end
|
||||
|
||||
it 'should return false on a 404' do
|
||||
stub_request(:get, @instance.get_url_without_filename.to_s.to_s).to_return(status: 404)
|
||||
@instance.directory_listing?.should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#extract_name_from_url' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: @path || 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: @type || 'plugins',
|
||||
wp_content_dir: @wp_content_dir
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
instance.extract_name_from_url.should === @expected
|
||||
end
|
||||
|
||||
it 'should extract the correct name' do
|
||||
@expected = 'test'
|
||||
end
|
||||
|
||||
it 'should extract the correct name (custom wp_content_dir)' do
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'test'
|
||||
end
|
||||
|
||||
it 'should extract the correct name' do
|
||||
@path = 'test2/asdf.php'
|
||||
@wp_content_dir = '/custom/'
|
||||
@expected = 'test2'
|
||||
end
|
||||
|
||||
it 'should extract the correct plugin name' do
|
||||
@path = 'testplugin/'
|
||||
@expected = 'testplugin'
|
||||
end
|
||||
|
||||
it 'should extract the correct theme name' do
|
||||
@path = 'testtheme/'
|
||||
@type = 'themes'
|
||||
@expected = 'testtheme'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_s' do
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return the name including a version number' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 200, body: 'Stable tag: 1.2.4.3.2.1')
|
||||
@instance.to_s.should == 'test v1.2.4.3.2.1'
|
||||
end
|
||||
|
||||
it 'should not return the name without a version number' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 200, body: 'Stable tag: trunk')
|
||||
@instance.to_s.should == 'test'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#==' do
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
instance2 = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'newname/asdf.php',
|
||||
type: 'plugins',
|
||||
vulns_file: 'XXX.xml',
|
||||
vulns_xpath: 'XX'
|
||||
)
|
||||
(@instance == instance2).should == false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
instance2 = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
type: 'plugins',
|
||||
vulns_file: 'XXX.xml',
|
||||
vulns_xpath: 'XX'
|
||||
)
|
||||
(@instance == instance2).should == true
|
||||
end
|
||||
end
|
||||
|
||||
describe '#get_sub_folder' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
wp_content_dir: 'wp-content',
|
||||
wp_plugins_dir: 'wp-content/plugins',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: @type || 'themes'
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
|
||||
if @raise_error
|
||||
expect { instance.get_sub_folder }.to @raise_error
|
||||
else
|
||||
instance.get_sub_folder.should === @expected
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return themes' do
|
||||
@expected = 'themes'
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
@type = 'timthumbs'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should raise an exception' do
|
||||
@type = 'type'
|
||||
@raise_error = raise_error(RuntimeError, 'unknown type type')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#readme_url' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: @type || 'plugins',
|
||||
wp_content_dir: @wp_content_dir
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
instance.readme_url.to_s.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the corrent plugin readme url' do
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test/readme.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent plugin readme url (custom wp_content)' do
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/readme.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent theme readme url' do
|
||||
@type = 'themes'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/themes/test/readme.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent theme readme url (custom wp_content)' do
|
||||
@type = 'themes'
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/themes/test/readme.txt'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#changelog_url' do
|
||||
after :each do
|
||||
arguments = {
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: @type || 'plugins',
|
||||
wp_content_dir: @wp_content_dir
|
||||
}
|
||||
|
||||
instance = WpItem.new(arguments)
|
||||
instance.changelog_url.to_s.should === @expected
|
||||
end
|
||||
|
||||
it 'should return the corrent plugin changelog url' do
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/plugins/test/changelog.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent plugin changelog url (custom wp_content)' do
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/plugins/test/changelog.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent theme changelog url' do
|
||||
@type = 'themes'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/wp-content/themes/test/changelog.txt'
|
||||
end
|
||||
|
||||
it 'should return the corrent theme changelog url (custom wp_content)' do
|
||||
@type = 'themes'
|
||||
@wp_content_dir = 'custom'
|
||||
@expected = 'http://sub.example.com/path/to/wordpress/custom/themes/test/changelog.txt'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_readme?' do
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 200)
|
||||
@instance.has_readme?.should == true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:get, @instance.readme_url.to_s).to_return(status: 403)
|
||||
@instance.has_readme?.should == false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_changelog?' do
|
||||
before :each do
|
||||
@instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:get, @instance.changelog_url.to_s).to_return(status: 200)
|
||||
@instance.has_changelog?.should == true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:get, @instance.changelog_url.to_s).to_return(status: 403)
|
||||
@instance.has_changelog?.should == false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_org_url' do
|
||||
it 'sould return a themes url' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'themes'
|
||||
)
|
||||
instance.wp_org_url.to_s.should == 'http://wordpress.org/extend/themes/test/'
|
||||
end
|
||||
|
||||
it 'sould return a plugins url' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
instance.wp_org_url.to_s.should == 'http://wordpress.org/extend/plugins/test/'
|
||||
end
|
||||
|
||||
it 'sould raise an exception' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'invalid'
|
||||
)
|
||||
expect { instance.wp_org_url }.to raise_error(RuntimeError, 'No Wordpress URL for invalid')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#wp_org_item?' do
|
||||
it 'sould return true' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'w3-total-cache',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
instance.wp_org_item?.should be_true
|
||||
end
|
||||
|
||||
it 'sould return true' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'twentyten',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'themes'
|
||||
)
|
||||
instance.wp_org_item?.should be_true
|
||||
end
|
||||
|
||||
it 'sould return false' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'can_not_be_in_repository',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins'
|
||||
)
|
||||
instance.wp_org_item?.should be_false
|
||||
end
|
||||
|
||||
it 'sould return false' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'can_not_be_in_repository',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'themes'
|
||||
)
|
||||
instance.wp_org_item?.should be_false
|
||||
end
|
||||
|
||||
it 'sould raise an exception' do
|
||||
instance = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'test',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'invalid'
|
||||
)
|
||||
expect { instance.wp_org_item? }.to raise_error(RuntimeError, 'Unknown type invalid')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#error_log_url' do
|
||||
it 'should return a correct url' do
|
||||
temp = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'name/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'name',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins')
|
||||
temp.error_log_url.to_s.should == 'http://sub.example.com/path/to/wordpress/wp-content/plugins/name/error_log'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#error_log?' do
|
||||
before :each do
|
||||
@temp = WpItem.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
name: 'name',
|
||||
vulns_xpath: 'XX',
|
||||
type: 'plugins')
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
stub_request(:get, @temp.error_log_url.to_s).to_return(status: 200, body: 'PHP Fatal error')
|
||||
@temp.error_log?.should be true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
stub_request(:get, @temp.error_log_url.to_s).to_return(status: 500, body: 'Access denied')
|
||||
@temp.error_log?.should be false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
fixtures_dir = SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR + '/error_log'
|
||||
stub_request(:get, @temp.error_log_url.to_s).to_return(
|
||||
status: 200,
|
||||
body: File.new(fixtures_dir + '/error_log')
|
||||
)
|
||||
|
||||
@temp.error_log?.should be true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,139 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpOptions do
|
||||
describe '#check_options' do
|
||||
before :each do
|
||||
@options = {}
|
||||
@options[:base_url] = 'url'
|
||||
@options[:only_vulnerable_ones] = false
|
||||
@options[:file] = 'file'
|
||||
@options[:vulns_file] = 'vulns_file'
|
||||
@options[:vulns_xpath] = 'vulns_xpath'
|
||||
@options[:vulns_xpath_2] = 'vulns_xpath_2'
|
||||
@options[:wp_content_dir] = 'wp_content_dir'
|
||||
@options[:show_progression] = true
|
||||
@options[:error_404_hash] = 'error_404_hash'
|
||||
@options[:type] = 'type'
|
||||
|
||||
@message = ''
|
||||
end
|
||||
|
||||
after :each do
|
||||
expect { WpOptions.check_options(@options) }.to raise_error(RuntimeError, @message)
|
||||
end
|
||||
|
||||
it 'should raise an exception (base_url empty)' do
|
||||
@options[:base_url] = ''
|
||||
@message = 'base_url must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (base_url nil)' do
|
||||
@options[:base_url] = nil
|
||||
@message = 'base_url must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (only_vulnerable_ones nil)' do
|
||||
@options[:only_vulnerable_ones] = nil
|
||||
@message = 'only_vulnerable_ones must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (file empty)' do
|
||||
@options[:file] = ''
|
||||
@message = 'file must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (file nil)' do
|
||||
@options[:file] = nil
|
||||
@message = 'file must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_file empty)' do
|
||||
@options[:vulns_file] = ''
|
||||
@message = 'vulns_file must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_file nil)' do
|
||||
@options[:vulns_file] = nil
|
||||
@message = 'vulns_file must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_xpath empty)' do
|
||||
@options[:vulns_xpath] = ''
|
||||
@message = 'vulns_xpath must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_xpath nil)' do
|
||||
@options[:vulns_xpath] = nil
|
||||
@message = 'vulns_xpath must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_xpath_2 empty)' do
|
||||
@options[:vulns_xpath_2] = ''
|
||||
@message = 'vulns_xpath_2 must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (vulns_xpath_2 nil)' do
|
||||
@options[:vulns_xpath_2] = nil
|
||||
@message = 'vulns_xpath_2 must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (wp_content_dir empty)' do
|
||||
@options[:wp_content_dir] = ''
|
||||
@message = 'wp_content_dir must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (wp_content_dir nil)' do
|
||||
@options[:wp_content_dir] = nil
|
||||
@message = 'wp_content_dir must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (show_progression nil)' do
|
||||
@options[:show_progression] = nil
|
||||
@message = 'show_progression must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (error_404_hash empty)' do
|
||||
@options[:error_404_hash] = ''
|
||||
@message = 'error_404_hash must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (error_404_hash nil)' do
|
||||
@options[:error_404_hash] = nil
|
||||
@message = 'error_404_hash must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (type empty)' do
|
||||
@options[:type] = ''
|
||||
@message = 'type must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (type nil)' do
|
||||
@options[:type] = nil
|
||||
@message = 'type must be set'
|
||||
end
|
||||
|
||||
it 'should raise an exception (type unknown)' do
|
||||
@options[:type] = 'unknown'
|
||||
@message = 'Unknown type unknown'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,44 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpPlugin do
|
||||
describe '#initialize' do
|
||||
it 'should not raise an exception' do
|
||||
expect { WpPlugin.new(base_url: 'url', path: 'path', wp_content_dir: 'dir', name: 'name') }.to_not raise_error
|
||||
end
|
||||
|
||||
it 'should not raise an exception (wp_content_dir not set)' do
|
||||
expect { WpPlugin.new(base_url: 'url', path: 'path', name: 'name') }.to_not raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (base_url not set)' do
|
||||
expect { WpPlugin.new(path: 'path', wp_content_dir: 'dir', name: 'name') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (path not set)' do
|
||||
expect { WpPlugin.new(base_url: 'url', wp_content_dir: 'dir', name: 'name') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (name not set)' do
|
||||
expect { WpPlugin.new(base_url: 'url', path: 'path', wp_content_dir: 'dir') }.to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -41,10 +41,6 @@ describe WpTarget do
|
||||
it_should_behave_like 'WpLoginProtection'
|
||||
it_should_behave_like 'Malwares'
|
||||
it_should_behave_like 'BruteForce'
|
||||
it_should_behave_like 'WpUsernames'
|
||||
it_should_behave_like 'WpTimthumbs'
|
||||
it_should_behave_like 'WpPlugins'
|
||||
it_should_behave_like 'WpThemes'
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should raise an error if the target_url is nil or empty' do
|
||||
|
||||
@@ -1,289 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpTheme do
|
||||
before :all do
|
||||
@target_uri = URI.parse('http://example.localhost/')
|
||||
|
||||
Browser.instance(
|
||||
config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json',
|
||||
cache_timeout: 0
|
||||
)
|
||||
end
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should not raise an exception' do
|
||||
expect { WpTheme.new(base_url: 'url', path: 'path', wp_content_dir: 'dir', name: 'name') }.to_not raise_error
|
||||
end
|
||||
|
||||
it 'should not raise an exception (wp_content_dir not set)' do
|
||||
expect { WpTheme.new(base_url: 'url', path: 'path', name: 'name') }.to_not raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (base_url not set)' do
|
||||
expect { WpTheme.new(path: 'path', wp_content_dir: 'dir', name: 'name') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (path not set)' do
|
||||
expect { WpTheme.new(base_url: 'url', wp_content_dir: 'dir', name: 'name') }.to raise_error
|
||||
end
|
||||
|
||||
it 'should raise an exception (name not set)' do
|
||||
expect { WpTheme.new(base_url: 'url', path: 'path', wp_content_dir: 'dir') }.to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_css_link' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_THEME_DIR + '/find/css_link' }
|
||||
|
||||
after :each do
|
||||
if @expected_name
|
||||
stub_request_to_fixture(url: @target_uri.to_s, fixture: @fixture)
|
||||
|
||||
wp_theme = WpTheme.find_from_css_link(@target_uri)
|
||||
wp_theme.should be_a WpTheme
|
||||
wp_theme.name.should === @expected_name
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return nil if no theme is present' do
|
||||
stub_request(:get, @target_uri.to_s).to_return(status: 200, body: '')
|
||||
|
||||
WpTheme.find_from_css_link(@target_uri).should be_nil
|
||||
end
|
||||
|
||||
it 'should return a WpTheme object with .name = twentyeleven' do
|
||||
@fixture = fixtures_dir + '/wordpress-twentyeleven.htm'
|
||||
@expected_name = 'twentyeleven'
|
||||
end
|
||||
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=131
|
||||
# Theme name with spaces raises bad URI(is not URI?)
|
||||
it 'should not raise an error if the theme name has spaces or special chars' do
|
||||
@fixture = fixtures_dir + '/theme-name-with-spaces.html'
|
||||
@expected_name = 'Copia di simplefolio'
|
||||
end
|
||||
|
||||
# https://github.com/wpscanteam/wpscan/issues/18
|
||||
it 'should get the theme if the <link> is inline with some other tags' do
|
||||
@fixture = fixtures_dir + '/inline_link_tag.html'
|
||||
@expected_name = 'inline'
|
||||
end
|
||||
|
||||
it 'should get the theme name even if relative URLs are used' do
|
||||
@fixture = fixtures_dir + '/relative_urls.html'
|
||||
@expected_name = 'theme_name'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_wooframework' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_THEME_DIR + '/find/wooframework' }
|
||||
|
||||
after :each do
|
||||
stub_request_to_fixture(url: @target_uri.to_s, fixture: @fixture)
|
||||
|
||||
wp_theme = WpTheme.find_from_wooframework(@target_uri)
|
||||
|
||||
stub_request(:get, wp_theme.default_style_url.to_s).to_return(status: 200)
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 200)
|
||||
|
||||
wp_theme.should be_a WpTheme unless wp_theme.nil?
|
||||
wp_theme.should === @expected_theme
|
||||
end
|
||||
|
||||
it "should return a WpTheme object with .name 'Editorial' and .version '1.3.5'" do
|
||||
@fixture = fixtures_dir + '/editorial-1.3.5.html'
|
||||
@expected_theme = WpTheme.new(name: 'Editorial', version: '1.3.5', base_url: 'http://example.localhost/', path: 'Editorial')
|
||||
end
|
||||
|
||||
it "should return a WpTheme object with .name 'Merchant'" do
|
||||
@fixture = fixtures_dir + '/merchant-no-version.html'
|
||||
@expected_theme = WpTheme.new(name: 'Merchant', base_url: 'http://example.localhost/', path: 'Merchant')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_THEME_DIR + '/find' }
|
||||
|
||||
after :each do
|
||||
stub_request_to_fixture(url: @target_uri.to_s, fixture: @fixture)
|
||||
|
||||
wp_theme = WpTheme.find(@target_uri)
|
||||
|
||||
if @expected_name
|
||||
wp_theme.should be_a WpTheme
|
||||
wp_theme.name.should === @expected_name
|
||||
else
|
||||
wp_theme.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return nil if no theme is found' do
|
||||
@fixture = SPEC_FIXTURES_DIR + '/empty-file'
|
||||
@expected_name = nil
|
||||
end
|
||||
|
||||
it "should return a WpTheme object with .name 'twentyeleven'" do
|
||||
@fixture = fixtures_dir + '/css_link/wordpress-twentyeleven.htm'
|
||||
@expected_name = 'twentyeleven'
|
||||
end
|
||||
|
||||
it "should a WpTheme object with .name 'Merchant'" do
|
||||
@fixture = fixtures_dir + '/wooframework/merchant-no-version.html'
|
||||
@expected_name = 'Merchant'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#version' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_THEME_DIR + '/version' }
|
||||
let(:theme_style_url) { @target_uri.merge('wp-content/themes/spec-theme/style.css').to_s }
|
||||
|
||||
after :each do
|
||||
if @fixture
|
||||
stub_request_to_fixture(url: theme_style_url, fixture: @fixture)
|
||||
|
||||
wp_theme = WpTheme.new(name: 'spec-theme', style_url: theme_style_url, base_url: 'http://example.localhost/', path: 'spec-theme')
|
||||
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 200)
|
||||
|
||||
wp_theme.version.should === @expected
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return nil if the version is not found' do
|
||||
@fixture = fixtures_dir + '/twentyeleven-unknow.css'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the style_url is nil' do
|
||||
wp_theme = WpTheme.new(name: 'hello-world', base_url: 'http://example.localhost/', path: 'hello-world')
|
||||
stub_request(:get, wp_theme.default_style_url.to_s).to_return(status: 200)
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 200)
|
||||
wp_theme.version.should be_nil
|
||||
end
|
||||
|
||||
it 'should return 1.3' do
|
||||
@fixture = fixtures_dir + '/twentyeleven-1.3.css'
|
||||
@expected = '1.3'
|
||||
end
|
||||
|
||||
it 'should return 1.5.1' do
|
||||
@fixture = fixtures_dir + '/bueno-1.5.1.css'
|
||||
@expected = '1.5.1'
|
||||
end
|
||||
|
||||
it 'should get the version from default style.css url' do
|
||||
wp_theme = WpTheme.new(name: 'hello-world', base_url: 'http://example.localhost/', path: 'hello-world')
|
||||
stub_request(:get, wp_theme.default_style_url.to_s).to_return(status: 200, body: 'Version: 1.3.4.5')
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 404)
|
||||
wp_theme.version.should === '1.3.4.5'
|
||||
end
|
||||
|
||||
it 'should get the version from custom style.css url' do
|
||||
style_url = 'http://example.localhost/custom_style.css'
|
||||
wp_theme = WpTheme.new(name: 'hello-world', base_url: 'http://example.localhost/', path: 'hello-world', style_url: style_url)
|
||||
stub_request(:get, style_url).to_return(status: 200, body: 'Version: 1.3.4.5')
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 404)
|
||||
wp_theme.version.should === '1.3.4.5'
|
||||
end
|
||||
|
||||
it 'should get the version from readme.txt' do
|
||||
wp_theme = WpTheme.new(name: 'hello-world', base_url: 'http://example.localhost/', path: 'hello-world')
|
||||
stub_request(:get, wp_theme.default_style_url.to_s).to_return(status: 404)
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 200, body: 'Stable Tag: 1.2.3.4')
|
||||
wp_theme.version.should === '1.2.3.4'
|
||||
end
|
||||
|
||||
it 'should get the version from readme.txt' do
|
||||
wp_theme = WpTheme.new(name: 'hello-world', base_url: 'http://example.localhost/', path: 'hello-world')
|
||||
stub_request(:get, wp_theme.default_style_url.to_s).to_return(status: 200)
|
||||
stub_request(:get, wp_theme.readme_url.to_s).to_return(status: 200, body: 'Stable Tag: 1.2.3.4')
|
||||
wp_theme.version.should === '1.2.3.4'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#===' do
|
||||
it 'should return false (name not equal)' do
|
||||
instance = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/name/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
instance2 = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/newname/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
(instance === instance2).should == false
|
||||
end
|
||||
|
||||
it 'should return false (version not equal)' do
|
||||
instance = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/name/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
instance2 = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/name/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '2.0'
|
||||
)
|
||||
(instance === instance2).should == false
|
||||
end
|
||||
|
||||
it 'should return false (version and name not equal)' do
|
||||
instance = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/name/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
instance2 = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/newname/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '2.0'
|
||||
)
|
||||
(instance === instance2).should == false
|
||||
end
|
||||
|
||||
it 'should return true' do
|
||||
instance = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
instance2 = WpTheme.new(
|
||||
base_url: 'http://sub.example.com/path/to/wordpress/',
|
||||
path: 'themes/test/asdf.php',
|
||||
vulns_file: 'XXX.xml',
|
||||
version: '1.0'
|
||||
)
|
||||
(instance === instance2).should == true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,86 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpUser do
|
||||
describe '#initialize' do
|
||||
it 'should replace nil with empty' do
|
||||
user = WpUser.new(nil, nil, nil)
|
||||
user.name.should == 'empty'
|
||||
user.id.should == 'empty'
|
||||
user.nickname == 'empty'
|
||||
end
|
||||
|
||||
it 'should initialize a user object' do
|
||||
user = WpUser.new('name', 'id', 'nickname')
|
||||
user.name.should == 'name'
|
||||
user.id.should == 'id'
|
||||
user.nickname == 'nickname'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#<=>' do
|
||||
it 'should return -1' do
|
||||
user1 = WpUser.new('b', nil, nil)
|
||||
user2 = WpUser.new('a', nil, nil)
|
||||
(user1 <=> user2).should === -1
|
||||
end
|
||||
|
||||
it 'should return 0' do
|
||||
user1 = WpUser.new('a', nil, nil)
|
||||
user2 = WpUser.new('a', nil, nil)
|
||||
(user1 <=> user2).should === 0
|
||||
end
|
||||
|
||||
it 'should return 1' do
|
||||
user1 = WpUser.new('a', nil, nil)
|
||||
user2 = WpUser.new('b', nil, nil)
|
||||
(user1 <=> user2).should === 1
|
||||
end
|
||||
end
|
||||
|
||||
describe '#===' do
|
||||
it 'should return true' do
|
||||
user1 = WpUser.new('a', 'id', 'nick')
|
||||
user2 = WpUser.new('a', 'id', 'nick')
|
||||
(user1 === user2).should be_true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
user1 = WpUser.new('a', 'id', 'nick')
|
||||
user2 = WpUser.new('b', 'id', 'nick')
|
||||
(user1 === user2).should be_false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#eql?' do
|
||||
it 'should return true' do
|
||||
user1 = WpUser.new('a', 'id', 'nick')
|
||||
user2 = WpUser.new('a', 'id', 'nick')
|
||||
(user1.eql? user2).should be_true
|
||||
end
|
||||
|
||||
it 'should return false' do
|
||||
user1 = WpUser.new('a', 'id', 'nick')
|
||||
user2 = WpUser.new('b', 'id', 'nick')
|
||||
(user1.eql? user2).should be_false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,306 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#++
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/wpscan_helper')
|
||||
|
||||
describe WpVersion do
|
||||
|
||||
before :all do
|
||||
@target_uri = URI.parse('http://example.localhost/')
|
||||
@browser = Browser.instance(config_file: SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json')
|
||||
end
|
||||
|
||||
describe '#find_from_meta_generator' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/meta-generator' }
|
||||
|
||||
after :each do
|
||||
stub_request_to_fixture(url: @target_uri.to_s, fixture: @fixture)
|
||||
WpVersion.find_from_meta_generator(base_uri: @target_uri.to_s).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil if the meta-generator is not found' do
|
||||
@fixture = fixtures_dir + '/no-meta-generator.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return 3.3.2' do
|
||||
@fixture = fixtures_dir + '/3.3.2.htm'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it 'should return 3.4-beta4' do
|
||||
@fixture = fixtures_dir + '/3.4-beta4.htm'
|
||||
@expected = '3.4-beta4'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@fixture = fixtures_dir + '/invalid_version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return 3.5' do
|
||||
@fixture = fixtures_dir + '/3.5_minified.htm'
|
||||
@expected = '3.5'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_rss_generator' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/rss-generator' }
|
||||
|
||||
after :each do
|
||||
@status_code ||= 200
|
||||
stub_request_to_fixture(url: @target_uri.merge('feed/').to_s, status: @status_code, fixture: @fixture)
|
||||
WpVersion.find_from_rss_generator(base_uri: @target_uri).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil on a 404' do
|
||||
@status_code = 404
|
||||
@fixture = SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/404.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the rss-generator is not found' do
|
||||
@fixture = fixtures_dir + '/no-rss-generator.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the version is not found (but the rss-generator is present)' do
|
||||
@fixture = fixtures_dir + '/no-version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'shuld return 3.3.2' do
|
||||
@fixture = fixtures_dir + '/3.3.2.htm'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it 'should return 3.4-beta4' do
|
||||
@fixture = fixtures_dir + '/3.4-beta4.htm'
|
||||
@expected = '3.4-beta4'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@fixture = fixtures_dir + '/invalid_version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_rdf_generator' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/rdf-generator' }
|
||||
|
||||
after :each do
|
||||
@status_code ||= 200
|
||||
stub_request_to_fixture(url: @target_uri.merge('feed/rdf/').to_s, status: @status_code, fixture: @fixture)
|
||||
WpVersion.find_from_rdf_generator(base_uri: @target_uri).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil on a 404' do
|
||||
@status_code = 404
|
||||
@fixture = SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/404.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the rdf-generator is not found' do
|
||||
@fixture = fixtures_dir + '/no-rdf-generator.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the version is not found (but the rdf-generator is present)' do
|
||||
@fixture = fixtures_dir + '/no-version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'shuld return 3.3.2' do
|
||||
@fixture = fixtures_dir + '/3.3.2.htm'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it 'should return 3.4-beta4' do
|
||||
@fixture = fixtures_dir + '/3.4-beta4.htm'
|
||||
@expected = '3.4-beta4'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@fixture = fixtures_dir + '/invalid_version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_atom_generator' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/atom-generator' }
|
||||
|
||||
after :each do
|
||||
@status_code ||= 200
|
||||
stub_request_to_fixture(url: @target_uri.merge('feed/atom/').to_s, status: @status_code, fixture: @fixture)
|
||||
WpVersion.find_from_atom_generator(base_uri: @target_uri).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil on a 404' do
|
||||
@status_code = 404
|
||||
@fixture = SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/404.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the atom-generator is not found' do
|
||||
@fixture = fixtures_dir + '/no-atom-generator.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the version is not found (but the atom-generator is present)' do
|
||||
@fixture = fixtures_dir + '/no-version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'shuld return 3.3.2' do
|
||||
@fixture = fixtures_dir + '/3.3.2.htm'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it 'should return 3.4-beta4' do
|
||||
@fixture = fixtures_dir + '/3.4-beta4.htm'
|
||||
@expected = '3.4-beta4'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@fixture = fixtures_dir + '/invalid_version.htm'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_sitemap_generator' do
|
||||
after :each do
|
||||
stub_request(:get, @target_uri.merge('sitemap.xml').to_s).
|
||||
to_return(status: 200, body: @body)
|
||||
|
||||
WpVersion.find_from_sitemap_generator(base_uri: @target_uri).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil if the generator is not found' do
|
||||
@body = ''
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return the version : 3.3.2' do
|
||||
@body = '<!-- generator="wordpress/3.3.2" -->'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@body = '<!-- generator="wordpress/5065" -->'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_readme' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/readme' }
|
||||
|
||||
after :each do
|
||||
@status_code ||= 200
|
||||
stub_request_to_fixture(url: @target_uri.merge('readme.html').to_s, status: @status_code, fixture: @fixture)
|
||||
|
||||
WpVersion.find_from_readme(base_uri: @target_uri).should === @expected
|
||||
end
|
||||
|
||||
it 'should return nil on a 404' do
|
||||
@status_code = 404
|
||||
@fixture = SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/404.htm'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return nil if the version number is not present' do
|
||||
@fixture = fixtures_dir + '/empty-version.html'
|
||||
@expected = nil
|
||||
end
|
||||
|
||||
it 'should return 3.3.2' do
|
||||
@fixture = fixtures_dir + '/readme-3.3.2.html'
|
||||
@expected = '3.3.2'
|
||||
end
|
||||
|
||||
it "should return nil if it's not a valid version, must contains at least one '.'" do
|
||||
@fixture = fixtures_dir + '/invalid_version.html'
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_advanced_fingerprinting' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/advanced' }
|
||||
|
||||
it 'should return 3.2.1' do
|
||||
stub_request_to_fixture(
|
||||
url: @target_uri.merge('wp-admin/js/wp-fullscreen.js').to_s,
|
||||
fixture: "#{fixtures_dir}/3.2.1.js"
|
||||
)
|
||||
version = WpVersion.find_from_advanced_fingerprinting(
|
||||
base_uri: @target_uri,
|
||||
wp_content_dir: 'wp-content',
|
||||
version_xml: "#{fixtures_dir}/wp_versions.xml"
|
||||
)
|
||||
version.should == '3.2.1'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find_from_links_opml' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/opml' }
|
||||
|
||||
it 'should return 3.4.2' do
|
||||
stub_request_to_fixture(
|
||||
url: @target_uri.merge('wp-links-opml.php').to_s,
|
||||
fixture: "#{fixtures_dir}/wp-links-opml.xml"
|
||||
)
|
||||
version = WpVersion.find_from_links_opml(base_uri: @target_uri)
|
||||
version.should == '3.4.2'
|
||||
end
|
||||
|
||||
it 'should return nil' do
|
||||
stub_request_to_fixture(
|
||||
url: @target_uri.merge('wp-links-opml.php').to_s,
|
||||
fixture: "#{fixtures_dir}/wp-links-opml-nogenerator.xml"
|
||||
)
|
||||
version = WpVersion.find_from_links_opml(base_uri: @target_uri)
|
||||
version.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#initialize' do
|
||||
it 'should initialize a WpVersion object' do
|
||||
v = WpVersion.new(1, {discovery_method: 'method', vulns_file: 'asdf.xml'})
|
||||
v.number.should == 1
|
||||
v.discovery_method.should == 'method'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#find' do
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR + '/advanced' }
|
||||
|
||||
it 'should find all versions' do
|
||||
# All requests get a HTTP 404
|
||||
stub_request(:any, /.*/).to_return(status: 404)
|
||||
# Wordpress Version 3.2.1
|
||||
stub_request_to_fixture(
|
||||
url: @target_uri.merge('wp-admin/js/wp-fullscreen.js').to_s,
|
||||
fixture: "#{fixtures_dir}/3.2.1.js"
|
||||
)
|
||||
version = WpVersion.find(@target_uri, 'wp-content')
|
||||
version.number.should == '3.2.1'
|
||||
version.discovery_method.should == 'advanced fingerprinting'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,37 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
# TODO
|
||||
|
||||
describe '#vulnerabilities' do
|
||||
let(:location_url) { 'http://example.localhost/' }
|
||||
let(:fixtures_dir) { SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR + '/vulnerabilities' }
|
||||
let(:vulns_file) { fixtures_dir + '/plugin_vulns.xml' }
|
||||
let(:wp_plugin) do
|
||||
WpPlugin.new(
|
||||
base_url: location_url,
|
||||
name: 'spec-plugin',
|
||||
path: 'plugins/spec-plugin/',
|
||||
vulns_file: vulns_file
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
it 'should return an empty array when no vulnerabilities are found' do
|
||||
WpPlugin.new(
|
||||
base_url: 'http://example.localhost/',
|
||||
name: 'no-vulns',
|
||||
path: 'plugins/no-vulns/',
|
||||
vulns_file: vulns_file
|
||||
).vulnerabilities.should be_empty
|
||||
end
|
||||
|
||||
it 'should return an arry with 2 vulnerabilities' do
|
||||
vulnerabilities = wp_plugin.vulnerabilities
|
||||
|
||||
vulnerabilities.should_not be_empty
|
||||
vulnerabilities.length.should == 2
|
||||
vulnerabilities.each { |vulnerability| vulnerability.should be_a WpVulnerability }
|
||||
vulnerabilities[0].title.should === 'WPScan Spec'
|
||||
vulnerabilities[1].title.should === 'Spec SQL Injection'
|
||||
end
|
||||
end
|
||||
@@ -54,17 +54,15 @@ describe 'StatsPlugin' do
|
||||
|
||||
describe '#total_plugins' do
|
||||
it 'should return the correct numer' do
|
||||
xml = "#{SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR}/vulnerabilities/plugin_vulns.xml"
|
||||
file = "#{SPEC_FIXTURES_WPSCAN_WP_PLUGIN_DIR}/plugins.txt"
|
||||
@stats.total_plugins(file, xml).should == 4
|
||||
@stats.total_plugins(file).should == 4
|
||||
end
|
||||
end
|
||||
|
||||
describe '#total_themes' do
|
||||
it 'should return the correct numer' do
|
||||
xml = "#{SPEC_FIXTURES_WPSCAN_WP_THEME_DIR}/vulnerabilities/theme_vulns.xml"
|
||||
file = "#{SPEC_FIXTURES_WPSCAN_WP_THEME_DIR}/themes.txt"
|
||||
@stats.total_themes(file, xml).should == 5
|
||||
@stats.total_themes(file).should == 5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user