Moves Models into their own namespace - Ref #1315
This commit is contained in:
@@ -95,7 +95,7 @@ module WPScan
|
|||||||
mod = CMSScanner::Target::Server.const_get(server)
|
mod = CMSScanner::Target::Server.const_get(server)
|
||||||
|
|
||||||
target.extend mod
|
target.extend mod
|
||||||
WPScan::WpItem.include mod
|
Model::WpItem.include mod
|
||||||
|
|
||||||
server
|
server
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ module WPScan
|
|||||||
@attacker ||= attacker_from_cli_options || attacker_from_automatic_detection
|
@attacker ||= attacker_from_cli_options || attacker_from_automatic_detection
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ WPScan::XMLRPC ]
|
# @return [ Model::XMLRPC ]
|
||||||
def xmlrpc
|
def xmlrpc
|
||||||
@xmlrpc ||= target.xmlrpc
|
@xmlrpc ||= target.xmlrpc
|
||||||
end
|
end
|
||||||
@@ -95,7 +95,7 @@ module WPScan
|
|||||||
return target.users unless parsed_options[:usernames]
|
return target.users unless parsed_options[:usernames]
|
||||||
|
|
||||||
parsed_options[:usernames].reduce([]) do |acc, elem|
|
parsed_options[:usernames].reduce([]) do |acc, elem|
|
||||||
acc << CMSScanner::User.new(elem.chomp)
|
acc << Model::User.new(elem.chomp)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ module WPScan
|
|||||||
# Might need to improve that
|
# Might need to improve that
|
||||||
next unless res.body =~ /define/i && res.body !~ /<\s?html/i
|
next unless res.body =~ /define/i && res.body !~ /<\s?html/i
|
||||||
|
|
||||||
found << WPScan::ConfigBackup.new(res.request.url, found_by: DIRECT_ACCESS, confidence: 100)
|
found << Model::ConfigBackup.new(res.request.url,
|
||||||
|
found_by: DIRECT_ACCESS,
|
||||||
|
confidence: 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ module WPScan
|
|||||||
enumerate(potential_urls(opts), opts) do |res|
|
enumerate(potential_urls(opts), opts) do |res|
|
||||||
next unless res.code == 200 && res.body =~ /INSERT INTO/
|
next unless res.code == 200 && res.body =~ /INSERT INTO/
|
||||||
|
|
||||||
found << WPScan::DbExport.new(res.request.url, found_by: DIRECT_ACCESS, confidence: 100)
|
found << Model::DbExport.new(res.request.url,
|
||||||
|
found_by: DIRECT_ACCESS,
|
||||||
|
confidence: 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless [200, 403].include?(res.code) && !target.homepage_or_404?(res)
|
return unless [200, 403].include?(res.code) && !target.homepage_or_404?(res)
|
||||||
|
|
||||||
WPScan::BackupDB.new(
|
Model::BackupDB.new(
|
||||||
url,
|
url,
|
||||||
confidence: 70,
|
confidence: 70,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless target.debug_log?(path)
|
return unless target.debug_log?(path)
|
||||||
|
|
||||||
WPScan::DebugLog.new(
|
Model::DebugLog.new(
|
||||||
target.url(path),
|
target.url(path),
|
||||||
confidence: 100, found_by: DIRECT_ACCESS,
|
confidence: 100, found_by: DIRECT_ACCESS,
|
||||||
references: { url: 'https://codex.wordpress.org/Debugging_in_WordPress' }
|
references: { url: 'https://codex.wordpress.org/Debugging_in_WordPress' }
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless res.body =~ /DUPLICATOR INSTALL-LOG/
|
return unless res.body =~ /DUPLICATOR INSTALL-LOG/
|
||||||
|
|
||||||
WPScan::DuplicatorInstallerLog.new(
|
Model::DuplicatorInstallerLog.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless res.code == 200 && !target.homepage_or_404?(res)
|
return unless res.code == 200 && !target.homepage_or_404?(res)
|
||||||
|
|
||||||
WPScan::EmergencyPwdResetScript.new(
|
Model::EmergencyPwdResetScript.new(
|
||||||
url,
|
url,
|
||||||
confidence: res.body =~ /password/i ? 100 : 40,
|
confidence: res.body =~ /password/i ? 100 : 40,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
|
|
||||||
return if fpd_entries.empty?
|
return if fpd_entries.empty?
|
||||||
|
|
||||||
WPScan::FullPathDisclosure.new(
|
Model::FullPathDisclosure.new(
|
||||||
target.url(path),
|
target.url(path),
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module WPScan
|
|||||||
|
|
||||||
url = target.url('wp-content/mu-plugins/')
|
url = target.url('wp-content/mu-plugins/')
|
||||||
|
|
||||||
return WPScan::MuPlugins.new(
|
return Model::MuPlugins.new(
|
||||||
url,
|
url,
|
||||||
confidence: 70,
|
confidence: 70,
|
||||||
found_by: 'URLs In Homepage (Passive Detection)',
|
found_by: 'URLs In Homepage (Passive Detection)',
|
||||||
@@ -35,7 +35,7 @@ module WPScan
|
|||||||
|
|
||||||
target.mu_plugins = true
|
target.mu_plugins = true
|
||||||
|
|
||||||
WPScan::MuPlugins.new(
|
Model::MuPlugins.new(
|
||||||
url,
|
url,
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module WPScan
|
|||||||
|
|
||||||
target.multisite = true
|
target.multisite = true
|
||||||
|
|
||||||
WPScan::Multisite.new(
|
Model::Multisite.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
res = Browser.get(url)
|
res = Browser.get(url)
|
||||||
|
|
||||||
if res.code == 200 && res.body =~ /wordpress/i
|
if res.code == 200 && res.body =~ /wordpress/i
|
||||||
return WPScan::Readme.new(url, confidence: 100, found_by: DIRECT_ACCESS)
|
return Model::Readme.new(url, confidence: 100, found_by: DIRECT_ACCESS)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
nil
|
nil
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ module WPScan
|
|||||||
|
|
||||||
target.registration_enabled = true
|
target.registration_enabled = true
|
||||||
|
|
||||||
WPScan::Registration.new(
|
Model::Registration.new(
|
||||||
res.effective_url,
|
res.effective_url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless res.code == 200 && res.headers['Content-Type'] =~ %r{\Aapplication/zip}i
|
return unless res.code == 200 && res.headers['Content-Type'] =~ %r{\Aapplication/zip}i
|
||||||
|
|
||||||
WPScan::TmmDbMigrate.new(
|
Model::TmmDbMigrate.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module WPScan
|
|||||||
|
|
||||||
url = target.url(path)
|
url = target.url(path)
|
||||||
|
|
||||||
WPScan::UploadDirectoryListing.new(
|
Model::UploadDirectoryListing.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless res.code == 200 && res.body =~ SQL_PATTERN
|
return unless res.code == 200 && res.body =~ SQL_PATTERN
|
||||||
|
|
||||||
WPScan::UploadSQLDump.new(
|
Model::UploadSQLDump.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: DIRECT_ACCESS
|
found_by: DIRECT_ACCESS
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless res.code == 200
|
return unless res.code == 200
|
||||||
|
|
||||||
WPScan::WPCron.new(
|
Model::WPCron.new(
|
||||||
wp_cron_url,
|
wp_cron_url,
|
||||||
confidence: 60,
|
confidence: 60,
|
||||||
found_by: DIRECT_ACCESS,
|
found_by: DIRECT_ACCESS,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module WPScan
|
|||||||
include Finders::WpItems::URLsInHomepage
|
include Finders::WpItems::URLsInHomepage
|
||||||
|
|
||||||
def create_theme(slug, style_url, opts)
|
def create_theme(slug, style_url, opts)
|
||||||
WPScan::Theme.new(
|
Model::Theme.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by, confidence: 70, style_url: style_url)
|
opts.merge(found_by: found_by, confidence: 70, style_url: style_url)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module WPScan
|
|||||||
slugs = items_from_links('themes', false) + items_from_codes('themes', false)
|
slugs = items_from_links('themes', false) + items_from_codes('themes', false)
|
||||||
|
|
||||||
slugs.each_with_object(Hash.new(0)) { |slug, counts| counts[slug] += 1 }.each do |slug, occurences|
|
slugs.each_with_object(Hash.new(0)) { |slug, counts| counts[slug] += 1 }.each do |slug, occurences|
|
||||||
found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 2 * occurences))
|
found << Model::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 2 * occurences))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
def passive(opts = {})
|
def passive(opts = {})
|
||||||
return unless target.homepage_res.body =~ PATTERN
|
return unless target.homepage_res.body =~ PATTERN
|
||||||
|
|
||||||
WPScan::Theme.new(
|
Model::Theme.new(
|
||||||
Regexp.last_match[1],
|
Regexp.last_match[1],
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by, confidence: 80)
|
opts.merge(found_by: found_by, confidence: 80)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module WPScan
|
|||||||
enumerate(target_urls(opts), opts) do |res|
|
enumerate(target_urls(opts), opts) do |res|
|
||||||
next unless res.code == 200
|
next unless res.code == 200
|
||||||
|
|
||||||
found << WPScan::Media.new(res.effective_url, opts.merge(found_by: found_by, confidence: 100))
|
found << Model::Media.new(res.effective_url, opts.merge(found_by: found_by, confidence: 100))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ module WPScan
|
|||||||
target.multi_call(methods).run
|
target.multi_call(methods).run
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ Array<CMSScanner::User> ] users
|
# @param [ Array<Model::User> ] users
|
||||||
# @param [ Array<String> ] passwords
|
# @param [ Array<String> ] passwords
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
# @option opts [ Boolean ] :show_progression
|
# @option opts [ Boolean ] :show_progression
|
||||||
# @option opts [ Integer ] :multicall_max_passwords
|
# @option opts [ Integer ] :multicall_max_passwords
|
||||||
#
|
#
|
||||||
# @yield [ CMSScanner::User ] When a valid combination is found
|
# @yield [ Model::User ] When a valid combination is found
|
||||||
#
|
#
|
||||||
# TODO: Make rubocop happy about metrics etc
|
# TODO: Make rubocop happy about metrics etc
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module WPScan
|
|||||||
class Base
|
class Base
|
||||||
include CMSScanner::Finders::UniqueFinder
|
include CMSScanner::Finders::UniqueFinder
|
||||||
|
|
||||||
# @param [ WPScan::Plugin ] plugin
|
# @param [ Model::Plugin ] plugin
|
||||||
def initialize(plugin)
|
def initialize(plugin)
|
||||||
finders << PluginVersion::Readme.new(plugin)
|
finders << PluginVersion::Readme.new(plugin)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ module WPScan
|
|||||||
|
|
||||||
# Load the finders associated with the plugin
|
# Load the finders associated with the plugin
|
||||||
#
|
#
|
||||||
# @param [ WPScan::Plugin ] plugin
|
# @param [ Model::Plugin ] plugin
|
||||||
def load_specific_finders(plugin)
|
def load_specific_finders(plugin)
|
||||||
module_name = plugin.classify
|
module_name = plugin.classify
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ module WPScan
|
|||||||
def aggressive(_opts = {})
|
def aggressive(_opts = {})
|
||||||
found_by_msg = 'Readme - %s (Aggressive Detection)'
|
found_by_msg = 'Readme - %s (Aggressive Detection)'
|
||||||
|
|
||||||
WPScan::WpItem::READMES.each do |file|
|
Model::WpItem::READMES.each do |file|
|
||||||
url = target.url(file)
|
url = target.url(file)
|
||||||
res = Browser.get(url)
|
res = Browser.get(url)
|
||||||
|
|
||||||
next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?
|
next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?
|
||||||
|
|
||||||
return numbers.reduce([]) do |a, e|
|
return numbers.reduce([]) do |a, e|
|
||||||
a << WPScan::Version.new(
|
a << Model::Version.new(
|
||||||
e[0],
|
e[0],
|
||||||
found_by: format(found_by_msg, e[1]),
|
found_by: format(found_by_msg, e[1]),
|
||||||
confidence: e[2],
|
confidence: e[2],
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module WPScan
|
|||||||
def process_response(opts, response, slug, klass, config)
|
def process_response(opts, response, slug, klass, config)
|
||||||
return unless response.body =~ config['pattern']
|
return unless response.body =~ config['pattern']
|
||||||
|
|
||||||
Plugin.new(
|
Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ module WPScan
|
|||||||
|
|
||||||
next unless comment =~ config['pattern']
|
next unless comment =~ config['pattern']
|
||||||
|
|
||||||
return Plugin.new(
|
return Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ module WPScan
|
|||||||
# when checking for plugins
|
# when checking for plugins
|
||||||
#
|
#
|
||||||
|
|
||||||
Plugin.new(
|
Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ module WPScan
|
|||||||
configs.each do |klass, config|
|
configs.each do |klass, config|
|
||||||
next unless headers[config['header']] && headers[config['header']].to_s =~ config['pattern']
|
next unless headers[config['header']] && headers[config['header']].to_s =~ config['pattern']
|
||||||
|
|
||||||
found << Plugin.new(
|
found << Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module WPScan
|
|||||||
response.html.xpath(config['xpath'] || '//script[not(@src)]').each do |node|
|
response.html.xpath(config['xpath'] || '//script[not(@src)]').each do |node|
|
||||||
next if config['pattern'] && !node.text.match(config['pattern'])
|
next if config['pattern'] && !node.text.match(config['pattern'])
|
||||||
|
|
||||||
return Plugin.new(
|
return Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
enumerate(target_urls(opts), opts) do |_res, slug|
|
enumerate(target_urls(opts), opts) do |_res, slug|
|
||||||
found << WPScan::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
found << Model::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
(items_from_links('plugins') + items_from_codes('plugins')).uniq.sort.each do |slug|
|
(items_from_links('plugins') + items_from_codes('plugins')).uniq.sort.each do |slug|
|
||||||
found << Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
found << Model::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ module WPScan
|
|||||||
response.html.xpath(config['xpath']).each do |node|
|
response.html.xpath(config['xpath']).each do |node|
|
||||||
next if config['pattern'] && !node.text.match(config['pattern'])
|
next if config['pattern'] && !node.text.match(config['pattern'])
|
||||||
|
|
||||||
return Plugin.new(
|
return Model::Plugin.new(
|
||||||
slug,
|
slug,
|
||||||
target,
|
target,
|
||||||
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module WPScan
|
|||||||
class Base
|
class Base
|
||||||
include CMSScanner::Finders::UniqueFinder
|
include CMSScanner::Finders::UniqueFinder
|
||||||
|
|
||||||
# @param [ WPScan::Theme ] theme
|
# @param [ Model::Theme ] theme
|
||||||
def initialize(theme)
|
def initialize(theme)
|
||||||
finders <<
|
finders <<
|
||||||
ThemeVersion::Style.new(theme) <<
|
ThemeVersion::Style.new(theme) <<
|
||||||
@@ -19,7 +19,7 @@ module WPScan
|
|||||||
|
|
||||||
# Load the finders associated with the theme
|
# Load the finders associated with the theme
|
||||||
#
|
#
|
||||||
# @param [ WPScan::Theme ] theme
|
# @param [ Model::Theme ] theme
|
||||||
def load_specific_finders(theme)
|
def load_specific_finders(theme)
|
||||||
module_name = theme.classify
|
module_name = theme.classify
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ module WPScan
|
|||||||
def style_version
|
def style_version
|
||||||
return unless Browser.get(target.style_url).body =~ /Version:[\t ]*(?!trunk)([0-9a-z\.-]+)/i
|
return unless Browser.get(target.style_url).body =~ /Version:[\t ]*(?!trunk)([0-9a-z\.-]+)/i
|
||||||
|
|
||||||
WPScan::Version.new(
|
Model::Version.new(
|
||||||
Regexp.last_match[1],
|
Regexp.last_match[1],
|
||||||
found_by: found_by,
|
found_by: found_by,
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module WPScan
|
|||||||
|
|
||||||
return unless Regexp.last_match[1] == target.slug
|
return unless Regexp.last_match[1] == target.slug
|
||||||
|
|
||||||
WPScan::Version.new(Regexp.last_match[2], found_by: found_by, confidence: 80)
|
Model::Version.new(Regexp.last_match[2], found_by: found_by, confidence: 80)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
enumerate(target_urls(opts), opts) do |_res, slug|
|
enumerate(target_urls(opts), opts) do |_res, slug|
|
||||||
found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
found << Model::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
(items_from_links('themes') + items_from_codes('themes')).uniq.sort.each do |slug|
|
(items_from_links('themes') + items_from_codes('themes')).uniq.sort.each do |slug|
|
||||||
found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
found << Model::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module WPScan
|
|||||||
class Base
|
class Base
|
||||||
include CMSScanner::Finders::UniqueFinder
|
include CMSScanner::Finders::UniqueFinder
|
||||||
|
|
||||||
# @param [ WPScan::Timthumb ] target
|
# @param [ Model::Timthumb ] target
|
||||||
def initialize(target)
|
def initialize(target)
|
||||||
finders << TimthumbVersion::BadRequest.new(target)
|
finders << TimthumbVersion::BadRequest.new(target)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ module WPScan
|
|||||||
def aggressive(_opts = {})
|
def aggressive(_opts = {})
|
||||||
return unless Browser.get(target.url).body =~ /(TimThumb version\s*: ([^<]+))/
|
return unless Browser.get(target.url).body =~ /(TimThumb version\s*: ([^<]+))/
|
||||||
|
|
||||||
WPScan::Version.new(
|
Model::Version.new(
|
||||||
Regexp.last_match[2],
|
Regexp.last_match[2],
|
||||||
found_by: 'Bad Request (Aggressive Detection)',
|
found_by: 'Bad Request (Aggressive Detection)',
|
||||||
confidence: 90,
|
confidence: 90,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
enumerate(target_urls(opts), opts) do |res|
|
enumerate(target_urls(opts), opts) do |res|
|
||||||
found << WPScan::Timthumb.new(res.request.url, opts.merge(found_by: found_by, confidence: 100))
|
found << Model::Timthumb.new(res.request.url, opts.merge(found_by: found_by, confidence: 100))
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ module WPScan
|
|||||||
|
|
||||||
next unless username
|
next unless username
|
||||||
|
|
||||||
found << CMSScanner::User.new(
|
found << Model::User.new(
|
||||||
username,
|
username,
|
||||||
id: id,
|
id: id,
|
||||||
found_by: format(found_by_msg, found_by),
|
found_by: format(found_by_msg, found_by),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ module WPScan
|
|||||||
found_by_msg = 'Author Posts - %s (Passive Detection)'
|
found_by_msg = 'Author Posts - %s (Passive Detection)'
|
||||||
|
|
||||||
usernames(opts).reduce([]) do |a, e|
|
usernames(opts).reduce([]) do |a, e|
|
||||||
a << CMSScanner::User.new(
|
a << Model::User.new(
|
||||||
e[0],
|
e[0],
|
||||||
found_by: format(found_by_msg, e[1]),
|
found_by: format(found_by_msg, e[1]),
|
||||||
confidence: e[2]
|
confidence: e[2]
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ module WPScan
|
|||||||
|
|
||||||
next unless error =~ /The password you entered for the username|Incorrect Password/i
|
next unless error =~ /The password you entered for the username|Incorrect Password/i
|
||||||
|
|
||||||
found << CMSScanner::User.new(username, found_by: found_by, confidence: 100)
|
found << Model::User.new(username, found_by: found_by, confidence: 100)
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ module WPScan
|
|||||||
|
|
||||||
return [] unless details
|
return [] unless details
|
||||||
|
|
||||||
[CMSScanner::User.new(details[0],
|
[Model::User.new(details[0],
|
||||||
found_by: format(found_by_msg, details[1]),
|
found_by: format(found_by_msg, details[1]),
|
||||||
confidence: details[2],
|
confidence: details[2],
|
||||||
interesting_entries: [api_url])]
|
interesting_entries: [api_url])]
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ module WPScan
|
|||||||
end
|
end
|
||||||
|
|
||||||
potential_usernames.uniq.each do |potential_username|
|
potential_usernames.uniq.each do |potential_username|
|
||||||
found << CMSScanner::User.new(potential_username, found_by: found_by, confidence: 50)
|
found << Model::User.new(potential_username, found_by: found_by, confidence: 50)
|
||||||
end
|
end
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ module WPScan
|
|||||||
found = []
|
found = []
|
||||||
|
|
||||||
JSON.parse(response.body)&.each do |user|
|
JSON.parse(response.body)&.each do |user|
|
||||||
found << CMSScanner::User.new(user['slug'],
|
found << Model::User.new(user['slug'],
|
||||||
id: user['id'],
|
id: user['id'],
|
||||||
found_by: found_by,
|
found_by: found_by,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
interesting_entries: [response.effective_url])
|
interesting_entries: [response.effective_url])
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ module WPScan
|
|||||||
|
|
||||||
next unless username && !username.strip.empty?
|
next unless username && !username.strip.empty?
|
||||||
|
|
||||||
found << CMSScanner::User.new(username,
|
found << Model::User.new(username,
|
||||||
found_by: found_by,
|
found_by: found_by,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
interesting_entries: [sitemap_url])
|
interesting_entries: [sitemap_url])
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
found
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ module WPScan
|
|||||||
|
|
||||||
number = Regexp.last_match(1)
|
number = Regexp.last_match(1)
|
||||||
|
|
||||||
return unless WPScan::WpVersion.valid?(number)
|
return unless Model::WpVersion.valid?(number)
|
||||||
|
|
||||||
WPScan::WpVersion.new(
|
Model::WpVersion.new(
|
||||||
number,
|
number,
|
||||||
found_by: 'Readme (Aggressive Detection)',
|
found_by: 'Readme (Aggressive Detection)',
|
||||||
# Since WP 4.7, the Readme only contains the major version (ie 4.7, 4.8 etc)
|
# Since WP 4.7, the Readme only contains the major version (ie 4.7, 4.8 etc)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ module WPScan
|
|||||||
hydra.abort
|
hydra.abort
|
||||||
progress_bar.finish
|
progress_bar.finish
|
||||||
|
|
||||||
return WPScan::WpVersion.new(
|
return Model::WpVersion.new(
|
||||||
version_number,
|
version_number,
|
||||||
found_by: 'Unique Fingerprinting (Aggressive Detection)',
|
found_by: 'Unique Fingerprinting (Aggressive Detection)',
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
module WPScan
|
||||||
|
module Model
|
||||||
|
include CMSScanner::Model
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
require_relative 'models/interesting_finding'
|
require_relative 'models/interesting_finding'
|
||||||
require_relative 'models/wp_version'
|
require_relative 'models/wp_version'
|
||||||
require_relative 'models/xml_rpc'
|
require_relative 'models/xml_rpc'
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# Config Backup
|
module Model
|
||||||
class ConfigBackup < InterestingFinding
|
# Config Backup
|
||||||
|
class ConfigBackup < InterestingFinding
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# DB Export
|
module Model
|
||||||
class DbExport < InterestingFinding
|
# DB Export
|
||||||
|
class DbExport < InterestingFinding
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,48 +1,50 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# Custom class to include the WPScan::References module
|
module Model
|
||||||
class InterestingFinding < CMSScanner::InterestingFinding
|
# Custom class to include the WPScan::References module
|
||||||
include References
|
class InterestingFinding < CMSScanner::Model::InterestingFinding
|
||||||
end
|
include References
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Empty classes for the #type to be correctly displayed (as taken from the self.class from the parent)
|
# Empty classes for the #type to be correctly displayed (as taken from the self.class from the parent)
|
||||||
#
|
#
|
||||||
class BackupDB < InterestingFinding
|
class BackupDB < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class DebugLog < InterestingFinding
|
class DebugLog < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class DuplicatorInstallerLog < InterestingFinding
|
class DuplicatorInstallerLog < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class EmergencyPwdResetScript < InterestingFinding
|
class EmergencyPwdResetScript < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class FullPathDisclosure < InterestingFinding
|
class FullPathDisclosure < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class MuPlugins < InterestingFinding
|
class MuPlugins < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class Multisite < InterestingFinding
|
class Multisite < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class Readme < InterestingFinding
|
class Readme < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class Registration < InterestingFinding
|
class Registration < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class TmmDbMigrate < InterestingFinding
|
class TmmDbMigrate < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class UploadDirectoryListing < InterestingFinding
|
class UploadDirectoryListing < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class UploadSQLDump < InterestingFinding
|
class UploadSQLDump < InterestingFinding
|
||||||
end
|
end
|
||||||
|
|
||||||
class WPCron < InterestingFinding
|
class WPCron < InterestingFinding
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# Media
|
module Model
|
||||||
class Media < InterestingFinding
|
# Media
|
||||||
|
class Media < InterestingFinding
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,25 +1,27 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# WordPress Plugin
|
module Model
|
||||||
class Plugin < WpItem
|
# WordPress Plugin
|
||||||
# See WpItem
|
class Plugin < WpItem
|
||||||
def initialize(slug, blog, opts = {})
|
# See WpItem
|
||||||
super(slug, blog, opts)
|
def initialize(slug, blog, opts = {})
|
||||||
|
super(slug, blog, opts)
|
||||||
|
|
||||||
@uri = Addressable::URI.parse(blog.url("wp-content/plugins/#{slug}/"))
|
@uri = Addressable::URI.parse(blog.url("wp-content/plugins/#{slug}/"))
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ JSON ]
|
# @return [ JSON ]
|
||||||
def db_data
|
def db_data
|
||||||
DB::Plugin.db_data(slug)
|
DB::Plugin.db_data(slug)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
#
|
#
|
||||||
# @return [ WPScan::Version, false ]
|
# @return [ Model::Version, false ]
|
||||||
def version(opts = {})
|
def version(opts = {})
|
||||||
@version = Finders::PluginVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
@version = Finders::PluginVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
||||||
|
|
||||||
@version
|
@version
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,99 +1,101 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# WordPress Theme
|
module Model
|
||||||
class Theme < WpItem
|
# WordPress Theme
|
||||||
attr_reader :style_url, :style_name, :style_uri, :author, :author_uri, :template, :description,
|
class Theme < WpItem
|
||||||
:license, :license_uri, :tags, :text_domain
|
attr_reader :style_url, :style_name, :style_uri, :author, :author_uri, :template, :description,
|
||||||
|
:license, :license_uri, :tags, :text_domain
|
||||||
|
|
||||||
# See WpItem
|
# See WpItem
|
||||||
def initialize(slug, blog, opts = {})
|
def initialize(slug, blog, opts = {})
|
||||||
super(slug, blog, opts)
|
super(slug, blog, opts)
|
||||||
|
|
||||||
@uri = Addressable::URI.parse(blog.url("wp-content/themes/#{slug}/"))
|
@uri = Addressable::URI.parse(blog.url("wp-content/themes/#{slug}/"))
|
||||||
@style_url = opts[:style_url] || url('style.css')
|
@style_url = opts[:style_url] || url('style.css')
|
||||||
|
|
||||||
parse_style
|
parse_style
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ JSON ]
|
|
||||||
def db_data
|
|
||||||
DB::Theme.db_data(slug)
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
|
||||||
#
|
|
||||||
# @return [ WPScan::Version, false ]
|
|
||||||
def version(opts = {})
|
|
||||||
@version = Finders::ThemeVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
|
||||||
|
|
||||||
@version
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Theme ]
|
|
||||||
def parent_theme
|
|
||||||
return unless template
|
|
||||||
return unless style_body =~ /^@import\surl\(["']?([^"'\)]+)["']?\);\s*$/i
|
|
||||||
|
|
||||||
opts = detection_opts.merge(
|
|
||||||
style_url: url(Regexp.last_match[1]),
|
|
||||||
found_by: 'Parent Themes (Passive Detection)',
|
|
||||||
confidence: 100
|
|
||||||
).merge(version_detection: version_detection_opts)
|
|
||||||
|
|
||||||
self.class.new(template, blog, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
# @param [ Integer ] depth
|
|
||||||
#
|
|
||||||
# @retun [ Array<Theme> ]
|
|
||||||
def parent_themes(depth = 3)
|
|
||||||
theme = self
|
|
||||||
found = []
|
|
||||||
|
|
||||||
(1..depth).each do |_|
|
|
||||||
parent = theme.parent_theme
|
|
||||||
|
|
||||||
break unless parent
|
|
||||||
|
|
||||||
found << parent
|
|
||||||
theme = parent
|
|
||||||
end
|
end
|
||||||
|
|
||||||
found
|
# @return [ JSON ]
|
||||||
end
|
def db_data
|
||||||
|
DB::Theme.db_data(slug)
|
||||||
def style_body
|
|
||||||
@style_body ||= Browser.get(style_url).body
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_style
|
|
||||||
{
|
|
||||||
style_name: 'Theme Name',
|
|
||||||
style_uri: 'Theme URI',
|
|
||||||
author: 'Author',
|
|
||||||
author_uri: 'Author URI',
|
|
||||||
template: 'Template',
|
|
||||||
description: 'Description',
|
|
||||||
license: 'License',
|
|
||||||
license_uri: 'License URI',
|
|
||||||
tags: 'Tags',
|
|
||||||
text_domain: 'Text Domain'
|
|
||||||
}.each do |attribute, tag|
|
|
||||||
instance_variable_set(:"@#{attribute}", parse_style_tag(style_body, tag))
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# @param [ String ] bofy
|
# @param [ Hash ] opts
|
||||||
# @param [ String ] tag
|
#
|
||||||
#
|
# @return [ Model::Version, false ]
|
||||||
# @return [ String ]
|
def version(opts = {})
|
||||||
def parse_style_tag(body, tag)
|
@version = Finders::ThemeVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
||||||
value = body[/^\s*#{Regexp.escape(tag)}:[\t ]*([^\r\n]+)/i, 1]
|
|
||||||
|
|
||||||
value && !value.strip.empty? ? value.strip : nil
|
@version
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other)
|
# @return [ Theme ]
|
||||||
super(other) && style_url == other.style_url
|
def parent_theme
|
||||||
|
return unless template
|
||||||
|
return unless style_body =~ /^@import\surl\(["']?([^"'\)]+)["']?\);\s*$/i
|
||||||
|
|
||||||
|
opts = detection_opts.merge(
|
||||||
|
style_url: url(Regexp.last_match[1]),
|
||||||
|
found_by: 'Parent Themes (Passive Detection)',
|
||||||
|
confidence: 100
|
||||||
|
).merge(version_detection: version_detection_opts)
|
||||||
|
|
||||||
|
self.class.new(template, blog, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [ Integer ] depth
|
||||||
|
#
|
||||||
|
# @retun [ Array<Theme> ]
|
||||||
|
def parent_themes(depth = 3)
|
||||||
|
theme = self
|
||||||
|
found = []
|
||||||
|
|
||||||
|
(1..depth).each do |_|
|
||||||
|
parent = theme.parent_theme
|
||||||
|
|
||||||
|
break unless parent
|
||||||
|
|
||||||
|
found << parent
|
||||||
|
theme = parent
|
||||||
|
end
|
||||||
|
|
||||||
|
found
|
||||||
|
end
|
||||||
|
|
||||||
|
def style_body
|
||||||
|
@style_body ||= Browser.get(style_url).body
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_style
|
||||||
|
{
|
||||||
|
style_name: 'Theme Name',
|
||||||
|
style_uri: 'Theme URI',
|
||||||
|
author: 'Author',
|
||||||
|
author_uri: 'Author URI',
|
||||||
|
template: 'Template',
|
||||||
|
description: 'Description',
|
||||||
|
license: 'License',
|
||||||
|
license_uri: 'License URI',
|
||||||
|
tags: 'Tags',
|
||||||
|
text_domain: 'Text Domain'
|
||||||
|
}.each do |attribute, tag|
|
||||||
|
instance_variable_set(:"@#{attribute}", parse_style_tag(style_body, tag))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [ String ] bofy
|
||||||
|
# @param [ String ] tag
|
||||||
|
#
|
||||||
|
# @return [ String ]
|
||||||
|
def parse_style_tag(body, tag)
|
||||||
|
value = body[/^\s*#{Regexp.escape(tag)}:[\t ]*([^\r\n]+)/i, 1]
|
||||||
|
|
||||||
|
value && !value.strip.empty? ? value.strip : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def ==(other)
|
||||||
|
super(other) && style_url == other.style_url
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,71 +1,73 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# Timthumb
|
module Model
|
||||||
class Timthumb < InterestingFinding
|
# Timthumb
|
||||||
include Vulnerable
|
class Timthumb < InterestingFinding
|
||||||
|
include Vulnerable
|
||||||
|
|
||||||
attr_reader :version_detection_opts
|
attr_reader :version_detection_opts
|
||||||
|
|
||||||
# @param [ String ] url
|
# @param [ String ] url
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
# @option opts [ Symbol ] :mode The mode to use to detect the version
|
# @option opts [ Symbol ] :mode The mode to use to detect the version
|
||||||
def initialize(url, opts = {})
|
def initialize(url, opts = {})
|
||||||
super(url, opts)
|
super(url, opts)
|
||||||
|
|
||||||
@version_detection_opts = opts[:version_detection] || {}
|
@version_detection_opts = opts[:version_detection] || {}
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
#
|
#
|
||||||
# @return [ WPScan::Version, false ]
|
# @return [ Model::Version, false ]
|
||||||
def version(opts = {})
|
def version(opts = {})
|
||||||
@version = Finders::TimthumbVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
@version = Finders::TimthumbVersion::Base.find(self, version_detection_opts.merge(opts)) if @version.nil?
|
||||||
|
|
||||||
@version
|
@version
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Array<Vulnerability> ]
|
# @return [ Array<Vulnerability> ]
|
||||||
def vulnerabilities
|
def vulnerabilities
|
||||||
vulns = []
|
vulns = []
|
||||||
|
|
||||||
vulns << rce_webshot_vuln if version == false || version > '1.35' && version < '2.8.14' && webshot_enabled?
|
vulns << rce_webshot_vuln if version == false || version > '1.35' && version < '2.8.14' && webshot_enabled?
|
||||||
vulns << rce_132_vuln if version == false || version < '1.33'
|
vulns << rce_132_vuln if version == false || version < '1.33'
|
||||||
|
|
||||||
vulns
|
vulns
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Vulnerability ] The RCE in the <= 1.32
|
# @return [ Vulnerability ] The RCE in the <= 1.32
|
||||||
def rce_132_vuln
|
def rce_132_vuln
|
||||||
Vulnerability.new(
|
Vulnerability.new(
|
||||||
'Timthumb <= 1.32 Remote Code Execution',
|
'Timthumb <= 1.32 Remote Code Execution',
|
||||||
{ exploitdb: ['17602'] },
|
{ exploitdb: ['17602'] },
|
||||||
'RCE',
|
'RCE',
|
||||||
'1.33'
|
'1.33'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Vulnerability ] The RCE due to the WebShot in the > 1.35 (or >= 2.0) and <= 2.8.13
|
# @return [ Vulnerability ] The RCE due to the WebShot in the > 1.35 (or >= 2.0) and <= 2.8.13
|
||||||
def rce_webshot_vuln
|
def rce_webshot_vuln
|
||||||
Vulnerability.new(
|
Vulnerability.new(
|
||||||
'Timthumb <= 2.8.13 WebShot Remote Code Execution',
|
'Timthumb <= 2.8.13 WebShot Remote Code Execution',
|
||||||
{
|
{
|
||||||
url: ['http://seclists.org/fulldisclosure/2014/Jun/117', 'https://github.com/wpscanteam/wpscan/issues/519'],
|
url: ['http://seclists.org/fulldisclosure/2014/Jun/117', 'https://github.com/wpscanteam/wpscan/issues/519'],
|
||||||
cve: '2014-4663'
|
cve: '2014-4663'
|
||||||
},
|
},
|
||||||
'RCE',
|
'RCE',
|
||||||
'2.8.14'
|
'2.8.14'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Boolean ]
|
# @return [ Boolean ]
|
||||||
def webshot_enabled?
|
def webshot_enabled?
|
||||||
res = Browser.get(url, params: { webshot: 1, src: "http://#{default_allowed_domains.sample}" })
|
res = Browser.get(url, params: { webshot: 1, src: "http://#{default_allowed_domains.sample}" })
|
||||||
|
|
||||||
res.body =~ /WEBSHOT_ENABLED == true/ ? false : true
|
res.body =~ /WEBSHOT_ENABLED == true/ ? false : true
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Array<String> ] The default allowed domains (between the 2.0 and 2.8.13)
|
# @return [ Array<String> ] The default allowed domains (between the 2.0 and 2.8.13)
|
||||||
def default_allowed_domains
|
def default_allowed_domains
|
||||||
%w[flickr.com picasa.com img.youtube.com upload.wikimedia.org]
|
%w[flickr.com picasa.com img.youtube.com upload.wikimedia.org]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,158 +1,160 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# WpItem (superclass of Plugin & Theme)
|
module Model
|
||||||
class WpItem
|
# WpItem (superclass of Plugin & Theme)
|
||||||
include Vulnerable
|
class WpItem
|
||||||
include Finders::Finding
|
include Vulnerable
|
||||||
include CMSScanner::Target::Platform::PHP
|
include Finders::Finding
|
||||||
include CMSScanner::Target::Server::Generic
|
include CMSScanner::Target::Platform::PHP
|
||||||
|
include CMSScanner::Target::Server::Generic
|
||||||
|
|
||||||
READMES = %w[readme.txt README.txt README.md readme.md Readme.txt].freeze
|
READMES = %w[readme.txt README.txt README.md readme.md Readme.txt].freeze
|
||||||
CHANGELOGS = %w[changelog.txt CHANGELOG.md changelog.md].freeze
|
CHANGELOGS = %w[changelog.txt CHANGELOG.md changelog.md].freeze
|
||||||
|
|
||||||
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :db_data
|
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :db_data
|
||||||
|
|
||||||
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_urls, to: :blog
|
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_urls, to: :blog
|
||||||
|
|
||||||
# @param [ String ] slug The plugin/theme slug
|
# @param [ String ] slug The plugin/theme slug
|
||||||
# @param [ Target ] blog The targeted blog
|
# @param [ Target ] blog The targeted blog
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
# @option opts [ Symbol ] :mode The detection mode to use
|
# @option opts [ Symbol ] :mode The detection mode to use
|
||||||
# @option opts [ Hash ] :version_detection The options to use when looking for the version
|
# @option opts [ Hash ] :version_detection The options to use when looking for the version
|
||||||
# @option opts [ String ] :url The URL of the item
|
# @option opts [ String ] :url The URL of the item
|
||||||
def initialize(slug, blog, opts = {})
|
def initialize(slug, blog, opts = {})
|
||||||
@slug = URI.decode(slug)
|
@slug = URI.decode(slug)
|
||||||
@blog = blog
|
@blog = blog
|
||||||
@uri = Addressable::URI.parse(opts[:url]) if opts[:url]
|
@uri = Addressable::URI.parse(opts[:url]) if opts[:url]
|
||||||
|
|
||||||
@detection_opts = { mode: opts[:mode] }
|
@detection_opts = { mode: opts[:mode] }
|
||||||
@version_detection_opts = opts[:version_detection] || {}
|
@version_detection_opts = opts[:version_detection] || {}
|
||||||
|
|
||||||
parse_finding_options(opts)
|
parse_finding_options(opts)
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Array<Vulnerabily> ]
|
|
||||||
def vulnerabilities
|
|
||||||
return @vulnerabilities if @vulnerabilities
|
|
||||||
|
|
||||||
@vulnerabilities = []
|
|
||||||
|
|
||||||
[*db_data['vulnerabilities']].each do |json_vuln|
|
|
||||||
vulnerability = Vulnerability.load_from_json(json_vuln)
|
|
||||||
@vulnerabilities << vulnerability if vulnerable_to?(vulnerability)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@vulnerabilities
|
# @return [ Array<Vulnerabily> ]
|
||||||
end
|
def vulnerabilities
|
||||||
|
return @vulnerabilities if @vulnerabilities
|
||||||
|
|
||||||
# Checks if the wp_item is vulnerable to a specific vulnerability
|
@vulnerabilities = []
|
||||||
#
|
|
||||||
# @param [ Vulnerability ] vuln Vulnerability to check the item against
|
|
||||||
#
|
|
||||||
# @return [ Boolean ]
|
|
||||||
def vulnerable_to?(vuln)
|
|
||||||
return true unless version && vuln && vuln.fixed_in && !vuln.fixed_in.empty?
|
|
||||||
|
|
||||||
version < vuln.fixed_in
|
[*db_data['vulnerabilities']].each do |json_vuln|
|
||||||
end
|
vulnerability = Vulnerability.load_from_json(json_vuln)
|
||||||
|
@vulnerabilities << vulnerability if vulnerable_to?(vulnerability)
|
||||||
# @return [ String ]
|
|
||||||
def latest_version
|
|
||||||
@latest_version ||= db_data['latest_version'] ? WPScan::Version.new(db_data['latest_version']) : nil
|
|
||||||
end
|
|
||||||
|
|
||||||
# Not used anywhere ATM
|
|
||||||
# @return [ Boolean ]
|
|
||||||
def popular?
|
|
||||||
@popular ||= db_data['popular']
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ String ]
|
|
||||||
def last_updated
|
|
||||||
@last_updated ||= db_data['last_updated']
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Boolean ]
|
|
||||||
def outdated?
|
|
||||||
@outdated ||= if version && latest_version
|
|
||||||
version < latest_version
|
|
||||||
else
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# URI.encode is preferered over Addressable::URI.encode as it will encode
|
|
||||||
# leading # character:
|
|
||||||
# URI.encode('#t#') => %23t%23
|
|
||||||
# Addressable::URI.encode('#t#') => #t%23
|
|
||||||
#
|
|
||||||
# @param [ String ] path Optional path to merge with the uri
|
|
||||||
#
|
|
||||||
# @return [ String ]
|
|
||||||
def url(path = nil)
|
|
||||||
return unless @uri
|
|
||||||
return @uri.to_s unless path
|
|
||||||
|
|
||||||
@uri.join(URI.encode(path)).to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Boolean ]
|
|
||||||
def ==(other)
|
|
||||||
self.class == other.class && slug == other.slug
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
slug
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Symbol ] The Class symbol associated to the item
|
|
||||||
def classify
|
|
||||||
@classify ||= classify_slug(slug)
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ String ] The readme url if found
|
|
||||||
def readme_url
|
|
||||||
return if detection_opts[:mode] == :passive
|
|
||||||
|
|
||||||
if @readme_url.nil?
|
|
||||||
READMES.each do |path|
|
|
||||||
return @readme_url = url(path) if Browser.get(url(path)).code == 200
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@vulnerabilities
|
||||||
end
|
end
|
||||||
|
|
||||||
@readme_url
|
# Checks if the wp_item is vulnerable to a specific vulnerability
|
||||||
end
|
#
|
||||||
|
# @param [ Vulnerability ] vuln Vulnerability to check the item against
|
||||||
|
#
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def vulnerable_to?(vuln)
|
||||||
|
return true unless version && vuln && vuln.fixed_in && !vuln.fixed_in.empty?
|
||||||
|
|
||||||
# @return [ String, false ] The changelog urr if found
|
version < vuln.fixed_in
|
||||||
def changelog_url
|
end
|
||||||
return if detection_opts[:mode] == :passive
|
|
||||||
|
|
||||||
if @changelog_url.nil?
|
# @return [ String ]
|
||||||
CHANGELOGS.each do |path|
|
def latest_version
|
||||||
return @changelog_url = url(path) if Browser.get(url(path)).code == 200
|
@latest_version ||= db_data['latest_version'] ? Model::Version.new(db_data['latest_version']) : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
# Not used anywhere ATM
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def popular?
|
||||||
|
@popular ||= db_data['popular']
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ]
|
||||||
|
def last_updated
|
||||||
|
@last_updated ||= db_data['last_updated']
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def outdated?
|
||||||
|
@outdated ||= if version && latest_version
|
||||||
|
version < latest_version
|
||||||
|
else
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# URI.encode is preferered over Addressable::URI.encode as it will encode
|
||||||
|
# leading # character:
|
||||||
|
# URI.encode('#t#') => %23t%23
|
||||||
|
# Addressable::URI.encode('#t#') => #t%23
|
||||||
|
#
|
||||||
|
# @param [ String ] path Optional path to merge with the uri
|
||||||
|
#
|
||||||
|
# @return [ String ]
|
||||||
|
def url(path = nil)
|
||||||
|
return unless @uri
|
||||||
|
return @uri.to_s unless path
|
||||||
|
|
||||||
|
@uri.join(URI.encode(path)).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def ==(other)
|
||||||
|
self.class == other.class && slug == other.slug
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
slug
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ Symbol ] The Class symbol associated to the item
|
||||||
|
def classify
|
||||||
|
@classify ||= classify_slug(slug)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ] The readme url if found
|
||||||
|
def readme_url
|
||||||
|
return if detection_opts[:mode] == :passive
|
||||||
|
|
||||||
|
if @readme_url.nil?
|
||||||
|
READMES.each do |path|
|
||||||
|
return @readme_url = url(path) if Browser.get(url(path)).code == 200
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@readme_url
|
||||||
end
|
end
|
||||||
|
|
||||||
@changelog_url
|
# @return [ String, false ] The changelog urr if found
|
||||||
end
|
def changelog_url
|
||||||
|
return if detection_opts[:mode] == :passive
|
||||||
|
|
||||||
# @param [ String ] path
|
if @changelog_url.nil?
|
||||||
# @param [ Hash ] params The request params
|
CHANGELOGS.each do |path|
|
||||||
#
|
return @changelog_url = url(path) if Browser.get(url(path)).code == 200
|
||||||
# @return [ Boolean ]
|
end
|
||||||
def directory_listing?(path = nil, params = {})
|
end
|
||||||
return if detection_opts[:mode] == :passive
|
|
||||||
|
|
||||||
super(path, params)
|
@changelog_url
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ String ] path
|
# @param [ String ] path
|
||||||
# @param [ Hash ] params The request params
|
# @param [ Hash ] params The request params
|
||||||
#
|
#
|
||||||
# @return [ Boolean ]
|
# @return [ Boolean ]
|
||||||
def error_log?(path = 'error_log', params = {})
|
def directory_listing?(path = nil, params = {})
|
||||||
return if detection_opts[:mode] == :passive
|
return if detection_opts[:mode] == :passive
|
||||||
|
|
||||||
super(path, params)
|
super(path, params)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @param [ String ] path
|
||||||
|
# @param [ Hash ] params The request params
|
||||||
|
#
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def error_log?(path = 'error_log', params = {})
|
||||||
|
return if detection_opts[:mode] == :passive
|
||||||
|
|
||||||
|
super(path, params)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,64 +1,66 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# WP Version
|
module Model
|
||||||
class WpVersion < CMSScanner::Version
|
# WP Version
|
||||||
include Vulnerable
|
class WpVersion < CMSScanner::Model::Version
|
||||||
|
include Vulnerable
|
||||||
|
|
||||||
def initialize(number, opts = {})
|
def initialize(number, opts = {})
|
||||||
raise Error::InvalidWordPressVersion unless WpVersion.valid?(number.to_s)
|
raise Error::InvalidWordPressVersion unless WpVersion.valid?(number.to_s)
|
||||||
|
|
||||||
super(number, opts)
|
super(number, opts)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ String ] number
|
# @param [ String ] number
|
||||||
#
|
#
|
||||||
# @return [ Boolean ] true if the number is a valid WP version, false otherwise
|
# @return [ Boolean ] true if the number is a valid WP version, false otherwise
|
||||||
def self.valid?(number)
|
def self.valid?(number)
|
||||||
all.include?(number)
|
all.include?(number)
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [ Array<String> ] All the version numbers
|
# @return [ Array<String> ] All the version numbers
|
||||||
def self.all
|
def self.all
|
||||||
return @all_numbers if @all_numbers
|
return @all_numbers if @all_numbers
|
||||||
|
|
||||||
@all_numbers = []
|
@all_numbers = []
|
||||||
|
|
||||||
DB::Fingerprints.wp_fingerprints.each_value do |fp|
|
DB::Fingerprints.wp_fingerprints.each_value do |fp|
|
||||||
fp.each_value do |versions|
|
fp.each_value do |versions|
|
||||||
versions.each do |version|
|
versions.each do |version|
|
||||||
@all_numbers << version unless @all_numbers.include?(version)
|
@all_numbers << version unless @all_numbers.include?(version)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@all_numbers.sort! { |a, b| Gem::Version.new(b) <=> Gem::Version.new(a) }
|
||||||
end
|
end
|
||||||
|
|
||||||
@all_numbers.sort! { |a, b| Gem::Version.new(b) <=> Gem::Version.new(a) }
|
# @return [ JSON ]
|
||||||
end
|
def db_data
|
||||||
|
DB::Version.db_data(number)
|
||||||
# @return [ JSON ]
|
|
||||||
def db_data
|
|
||||||
DB::Version.db_data(number)
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ Array<Vulnerability> ]
|
|
||||||
def vulnerabilities
|
|
||||||
return @vulnerabilities if @vulnerabilities
|
|
||||||
|
|
||||||
@vulnerabilities = []
|
|
||||||
|
|
||||||
[*db_data['vulnerabilities']].each do |json_vuln|
|
|
||||||
@vulnerabilities << Vulnerability.load_from_json(json_vuln)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@vulnerabilities
|
# @return [ Array<Vulnerability> ]
|
||||||
end
|
def vulnerabilities
|
||||||
|
return @vulnerabilities if @vulnerabilities
|
||||||
|
|
||||||
# @return [ String ]
|
@vulnerabilities = []
|
||||||
def release_date
|
|
||||||
@release_date ||= db_data['release_date'] || 'Unknown'
|
|
||||||
end
|
|
||||||
|
|
||||||
# @return [ String ]
|
[*db_data['vulnerabilities']].each do |json_vuln|
|
||||||
def status
|
@vulnerabilities << Vulnerability.load_from_json(json_vuln)
|
||||||
@status ||= db_data['status'] || 'Unknown'
|
end
|
||||||
|
|
||||||
|
@vulnerabilities
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ]
|
||||||
|
def release_date
|
||||||
|
@release_date ||= db_data['release_date'] || 'Unknown'
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ]
|
||||||
|
def status
|
||||||
|
@status ||= db_data['status'] || 'Unknown'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,19 +1,21 @@
|
|||||||
module WPScan
|
module WPScan
|
||||||
# Override of the CMSScanner::XMLRPC to include the references
|
module Model
|
||||||
class XMLRPC < CMSScanner::XMLRPC
|
# Override of the CMSScanner::XMLRPC to include the references
|
||||||
include References # To be able to use the :wpvulndb reference if needed
|
class XMLRPC < CMSScanner::Model::XMLRPC
|
||||||
|
include References # To be able to use the :wpvulndb reference if needed
|
||||||
|
|
||||||
# @return [ Hash ]
|
# @return [ Hash ]
|
||||||
def references
|
def references
|
||||||
{
|
{
|
||||||
url: ['http://codex.wordpress.org/XML-RPC_Pingback_API'],
|
url: ['http://codex.wordpress.org/XML-RPC_Pingback_API'],
|
||||||
metasploit: [
|
metasploit: [
|
||||||
'auxiliary/scanner/http/wordpress_ghost_scanner',
|
'auxiliary/scanner/http/wordpress_ghost_scanner',
|
||||||
'auxiliary/dos/http/wordpress_xmlrpc_dos',
|
'auxiliary/dos/http/wordpress_xmlrpc_dos',
|
||||||
'auxiliary/scanner/http/wordpress_xmlrpc_login',
|
'auxiliary/scanner/http/wordpress_xmlrpc_login',
|
||||||
'auxiliary/scanner/http/wordpress_pingback_access'
|
'auxiliary/scanner/http/wordpress_pingback_access'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ module WPScan
|
|||||||
|
|
||||||
# @param [ String ] number
|
# @param [ String ] number
|
||||||
# @param [ Hash ] finding_opts
|
# @param [ Hash ] finding_opts
|
||||||
# @return [ WPScan::Version ]
|
# @return [ Model::Version ]
|
||||||
def create_version(number, finding_opts)
|
def create_version(number, finding_opts)
|
||||||
WPScan::Version.new(number, version_finding_opts(finding_opts))
|
Model::Version.new(number, version_finding_opts(finding_opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ module WPScan
|
|||||||
configs.each do |klass, config|
|
configs.each do |klass, config|
|
||||||
item = process_response(opts, target.homepage_res, slug, klass, config)
|
item = process_response(opts, target.homepage_res, slug, klass, config)
|
||||||
|
|
||||||
found << item if item.is_a?(WpItem)
|
found << item if item.is_a?(Model::WpItem)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ module WPScan
|
|||||||
|
|
||||||
item = process_response(opts, response, slug, klass, config)
|
item = process_response(opts, response, slug, klass, config)
|
||||||
|
|
||||||
found << item if item.is_a?(WpItem)
|
found << item if item.is_a?(Model::WpItem)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ module WPScan
|
|||||||
module WpVersion
|
module WpVersion
|
||||||
module Finder
|
module Finder
|
||||||
def create_version(number, finding_opts)
|
def create_version(number, finding_opts)
|
||||||
return unless WPScan::WpVersion.valid?(number)
|
return unless Model::WpVersion.valid?(number)
|
||||||
|
|
||||||
WPScan::WpVersion.new(number, version_finding_opts(finding_opts))
|
Model::WpVersion.new(number, version_finding_opts(finding_opts))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ module WPScan
|
|||||||
include CMSScanner::Finders::Finder::SmartURLChecker
|
include CMSScanner::Finders::Finder::SmartURLChecker
|
||||||
|
|
||||||
def create_version(number, opts = {})
|
def create_version(number, opts = {})
|
||||||
WPScan::WpVersion.new(
|
Model::WpVersion.new(
|
||||||
number,
|
number,
|
||||||
found_by: opts[:found_by] || found_by,
|
found_by: opts[:found_by] || found_by,
|
||||||
confidence: opts[:confidence] || 80,
|
confidence: opts[:confidence] || 80,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ module WPScan
|
|||||||
|
|
||||||
# @return [ XMLRPC, nil ]
|
# @return [ XMLRPC, nil ]
|
||||||
def xmlrpc
|
def xmlrpc
|
||||||
@xmlrpc ||= interesting_findings&.select { |f| f.is_a?(WPScan::XMLRPC) }&.first
|
@xmlrpc ||= interesting_findings&.select { |f| f.is_a?(Model::XMLRPC) }&.first
|
||||||
end
|
end
|
||||||
|
|
||||||
# @param [ Hash ] opts
|
# @param [ Hash ] opts
|
||||||
|
|||||||
@@ -29,13 +29,13 @@ describe WPScan::Controller::Core do
|
|||||||
expect(core.target).to receive(:server).and_return(@stubbed_server)
|
expect(core.target).to receive(:server).and_return(@stubbed_server)
|
||||||
expect(core.load_server_module).to eql @expected
|
expect(core.load_server_module).to eql @expected
|
||||||
|
|
||||||
[core.target, WPScan::WpItem.new(target_url, core.target)].each do |instance|
|
[core.target, WPScan::Model::WpItem.new(target_url, core.target)].each do |instance|
|
||||||
expect(instance).to respond_to(:directory_listing?)
|
expect(instance).to respond_to(:directory_listing?)
|
||||||
expect(instance).to respond_to(:directory_listing_entries)
|
expect(instance).to respond_to(:directory_listing_entries)
|
||||||
|
|
||||||
# The below doesn't work, the module would have to be removed from the class
|
# The below doesn't work, the module would have to be removed from the class
|
||||||
# TODO: find a way to test this
|
# TODO: find a way to test this
|
||||||
# expect(instance.server).to eql @expected if instance.is_a? WPScan::WpItem
|
# expect(instance.server).to eql @expected if instance.is_a? WPScan::Model::WpItem
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
|
|
||||||
it 'returns an array with the users' do
|
it 'returns an array with the users' do
|
||||||
expected = %w[admin editor].reduce([]) do |a, e|
|
expected = %w[admin editor].reduce([]) do |a, e|
|
||||||
a << CMSScanner::User.new(e)
|
a << WPScan::Model::User.new(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
expect(controller.users).to eql expected
|
expect(controller.users).to eql expected
|
||||||
@@ -90,7 +90,9 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
|
|
||||||
context 'when xmlrpc detected on target' do
|
context 'when xmlrpc detected on target' do
|
||||||
before do
|
before do
|
||||||
expect(controller.target).to receive(:xmlrpc).and_return(WPScan::XMLRPC.new("#{target_url}/xmlrpc.php"))
|
expect(controller.target)
|
||||||
|
.to receive(:xmlrpc)
|
||||||
|
.and_return(WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php"))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when single xmlrpc' do
|
context 'when single xmlrpc' do
|
||||||
@@ -98,7 +100,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
|
|
||||||
it 'returns the correct object' do
|
it 'returns the correct object' do
|
||||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
|
|
||||||
it 'returns the correct object' do
|
it 'returns the correct object' do
|
||||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
||||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -127,7 +129,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when xmlrpc not enabled' do
|
context 'when xmlrpc not enabled' do
|
||||||
let(:xmlrpc) { WPScan::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
||||||
|
|
||||||
it 'returns the WpLogin' do
|
it 'returns the WpLogin' do
|
||||||
expect(xmlrpc).to receive(:enabled?).and_return(false)
|
expect(xmlrpc).to receive(:enabled?).and_return(false)
|
||||||
@@ -138,7 +140,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when xmlrpc enabled' do
|
context 'when xmlrpc enabled' do
|
||||||
let(:xmlrpc) { WPScan::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
let(:xmlrpc) { WPScan::Model::XMLRPC.new("#{target_url}/xmlrpc.php") }
|
||||||
|
|
||||||
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
|
before { expect(xmlrpc).to receive(:enabled?).and_return(true) }
|
||||||
|
|
||||||
@@ -159,7 +161,7 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
expect(controller.target).to receive(:wp_version).and_return(false)
|
expect(controller.target).to receive(:wp_version).and_return(false)
|
||||||
|
|
||||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -167,20 +169,20 @@ describe WPScan::Controller::PasswordAttack do
|
|||||||
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
|
before { expect(controller.target).to receive(:wp_version).and_return(wp_version) }
|
||||||
|
|
||||||
context 'when WP < 4.4' do
|
context 'when WP < 4.4' do
|
||||||
let(:wp_version) { WPScan::WpVersion.new('3.8.1') }
|
let(:wp_version) { WPScan::Model::WpVersion.new('3.8.1') }
|
||||||
|
|
||||||
it 'returns the XMLRPCMulticall' do
|
it 'returns the XMLRPCMulticall' do
|
||||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPCMulticall
|
||||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when WP >= 4.4' do
|
context 'when WP >= 4.4' do
|
||||||
let(:wp_version) { WPScan::WpVersion.new('4.4') }
|
let(:wp_version) { WPScan::Model::WpVersion.new('4.4') }
|
||||||
|
|
||||||
it 'returns the XMLRPC' do
|
it 'returns the XMLRPC' do
|
||||||
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
expect(controller.attacker).to be_a WPScan::Finders::Passwords::XMLRPC
|
||||||
expect(controller.attacker.target).to be_a WPScan::XMLRPC
|
expect(controller.attacker.target).to be_a WPScan::Model::XMLRPC
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ describe WPScan::Controller::WpVersion do
|
|||||||
context "when --detection-mode #{mode}" do
|
context "when --detection-mode #{mode}" do
|
||||||
let(:cli_args) { "#{super()} --detection-mode #{mode}" }
|
let(:cli_args) { "#{super()} --detection-mode #{mode}" }
|
||||||
|
|
||||||
[WPScan::WpVersion.new('4.0')].each do |version|
|
[WPScan::Model::WpVersion.new('4.0')].each do |version|
|
||||||
context "when version = #{version}" do
|
context "when version = #{version}" do
|
||||||
let(:stubbed) { version }
|
let(:stubbed) { version }
|
||||||
|
|
||||||
@@ -68,16 +68,16 @@ describe WPScan::Controller::WpVersion do
|
|||||||
|
|
||||||
context 'when --wp-version-all supplied' do
|
context 'when --wp-version-all supplied' do
|
||||||
let(:cli_args) { "#{super()} --wp-version-all" }
|
let(:cli_args) { "#{super()} --wp-version-all" }
|
||||||
let(:stubbed) { WPScan::WpVersion.new('3.9.1') }
|
let(:stubbed) { WPScan::Model::WpVersion.new('3.9.1') }
|
||||||
|
|
||||||
it_calls_the_formatter_with_the_correct_parameter(WPScan::WpVersion.new('3.9.1'))
|
it_calls_the_formatter_with_the_correct_parameter(WPScan::Model::WpVersion.new('3.9.1'))
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when --wp-version-detection mode supplied' do
|
context 'when --wp-version-detection mode supplied' do
|
||||||
let(:cli_args) { "#{super()} --detection-mode mixed --wp-version-detection passive" }
|
let(:cli_args) { "#{super()} --detection-mode mixed --wp-version-detection passive" }
|
||||||
let(:stubbed) { WPScan::WpVersion.new('4.4') }
|
let(:stubbed) { WPScan::Model::WpVersion.new('4.4') }
|
||||||
|
|
||||||
it_calls_the_formatter_with_the_correct_parameter(WPScan::WpVersion.new('4.4'))
|
it_calls_the_formatter_with_the_correct_parameter(WPScan::Model::WpVersion.new('4.4'))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ describe WPScan::Finders::ConfigBackups::KnownFilenames do
|
|||||||
|
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
url = "#{target.url}#{file}"
|
url = "#{target.url}#{file}"
|
||||||
expected << WPScan::ConfigBackup.new(
|
expected << WPScan::Model::ConfigBackup.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ describe WPScan::Finders::DbExports::KnownLocations do
|
|||||||
|
|
||||||
files.each do |file|
|
files.each do |file|
|
||||||
url = "#{target.url}#{file}"
|
url = "#{target.url}#{file}"
|
||||||
expected << WPScan::DbExport.new(
|
expected << WPScan::Model::DbExport.new(
|
||||||
url,
|
url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ describe WPScan::Finders::InterestingFindings::BackupDB do
|
|||||||
after do
|
after do
|
||||||
found = finder.aggressive
|
found = finder.aggressive
|
||||||
|
|
||||||
expect(found).to eql WPScan::BackupDB.new(
|
expect(found).to eql WPScan::Model::BackupDB.new(
|
||||||
dir_url,
|
dir_url,
|
||||||
confidence: 70,
|
confidence: 70,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe WPScan::Finders::InterestingFindings::DebugLog do
|
|||||||
let(:body) { File.read(fixtures.join('debug.log')) }
|
let(:body) { File.read(fixtures.join('debug.log')) }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
expect(finder.aggressive).to eql WPScan::DebugLog.new(
|
expect(finder.aggressive).to eql WPScan::Model::DebugLog.new(
|
||||||
log_url,
|
log_url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe WPScan::Finders::InterestingFindings::DuplicatorInstallerLog do
|
|||||||
let(:body) { File.read(fixtures.join(filename)) }
|
let(:body) { File.read(fixtures.join(filename)) }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
expect(finder.aggressive).to eql WPScan::DuplicatorInstallerLog.new(
|
expect(finder.aggressive).to eql WPScan::Model::DuplicatorInstallerLog.new(
|
||||||
log_url,
|
log_url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe WPScan::Finders::InterestingFindings::FullPathDisclosure do
|
|||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
found = finder.aggressive
|
found = finder.aggressive
|
||||||
|
|
||||||
expect(found).to eql WPScan::FullPathDisclosure.new(
|
expect(found).to eql WPScan::Model::FullPathDisclosure.new(
|
||||||
file_url,
|
file_url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe WPScan::Finders::InterestingFindings::Readme do
|
|||||||
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
before { stub_request(:get, target.url(file)).to_return(body: readme) }
|
||||||
|
|
||||||
it 'returns the expected InterestingFinding' do
|
it 'returns the expected InterestingFinding' do
|
||||||
expected = WPScan::Readme.new(
|
expected = WPScan::Model::Readme.new(
|
||||||
target.url(file),
|
target.url(file),
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ describe WPScan::Finders::InterestingFindings::UploadSQLDump do
|
|||||||
let(:fixture) { 'dump.sql' }
|
let(:fixture) { 'dump.sql' }
|
||||||
|
|
||||||
it 'returns the interesting findings' do
|
it 'returns the interesting findings' do
|
||||||
@expected = WPScan::UploadSQLDump.new(
|
@expected = WPScan::Model::UploadSQLDump.new(
|
||||||
finder.dump_url,
|
finder.dump_url,
|
||||||
confidence: 100,
|
confidence: 100,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ describe WPScan::Finders::InterestingFindings::WPCron do
|
|||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
it 'returns the InterestingFinding' do
|
it 'returns the InterestingFinding' do
|
||||||
expect(finder.aggressive).to eql WPScan::WPCron.new(
|
expect(finder.aggressive).to eql WPScan::Model::WPCron.new(
|
||||||
finder.wp_cron_url,
|
finder.wp_cron_url,
|
||||||
confidence: 60,
|
confidence: 60,
|
||||||
found_by: described_class::DIRECT_ACCESS
|
found_by: described_class::DIRECT_ACCESS
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ describe WPScan::Finders::MainTheme::CssStyle do
|
|||||||
let(:fixture) { 'link_href.html' }
|
let(:fixture) { 'link_href.html' }
|
||||||
|
|
||||||
it 'returns the expected theme' do
|
it 'returns the expected theme' do
|
||||||
@expected = WPScan::Theme.new(
|
@expected = WPScan::Model::Theme.new(
|
||||||
'twentyfifteen',
|
'twentyfifteen',
|
||||||
target,
|
target,
|
||||||
found_by: 'Css Style (Passive Detection)',
|
found_by: 'Css Style (Passive Detection)',
|
||||||
@@ -42,7 +42,7 @@ describe WPScan::Finders::MainTheme::CssStyle do
|
|||||||
let(:fixture) { 'style_code.html' }
|
let(:fixture) { 'style_code.html' }
|
||||||
|
|
||||||
it 'returns the expected theme' do
|
it 'returns the expected theme' do
|
||||||
@expected = WPScan::Theme.new(
|
@expected = WPScan::Model::Theme.new(
|
||||||
'custom',
|
'custom',
|
||||||
target,
|
target,
|
||||||
found_by: 'Css Style (Passive Detection)',
|
found_by: 'Css Style (Passive Detection)',
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe WPScan::Finders::MainTheme::UrlsInHomepage do
|
|||||||
@expected = []
|
@expected = []
|
||||||
|
|
||||||
{ 'twentyfifteen' => 6, 'yolo' => 4, 'test' => 2 }.each do |slug, confidence|
|
{ 'twentyfifteen' => 6, 'yolo' => 4, 'test' => 2 }.each do |slug, confidence|
|
||||||
@expected << WPScan::Theme.new(
|
@expected << WPScan::Model::Theme.new(
|
||||||
slug, target, found_by: 'Urls In Homepage (Passive Detection)', confidence: confidence
|
slug, target, found_by: 'Urls In Homepage (Passive Detection)', confidence: confidence
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ describe WPScan::Finders::MainTheme::WooFrameworkMetaGenerator do
|
|||||||
|
|
||||||
it 'returns the expected theme' do
|
it 'returns the expected theme' do
|
||||||
@file = 'woo_generator.html'
|
@file = 'woo_generator.html'
|
||||||
@expected = WPScan::Theme.new(
|
@expected = WPScan::Model::Theme.new(
|
||||||
'Merchant', target,
|
'Merchant', target,
|
||||||
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
||||||
confidence: 80
|
confidence: 80
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
describe WPScan::Finders::PluginVersion::Readme do
|
describe WPScan::Finders::PluginVersion::Readme do
|
||||||
subject(:finder) { described_class.new(plugin) }
|
subject(:finder) { described_class.new(plugin) }
|
||||||
let(:plugin) { WPScan::Plugin.new('spec', target) }
|
let(:plugin) { WPScan::Model::Plugin.new('spec', target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { FINDERS_FIXTURES.join('plugin_version', 'readme') }
|
let(:fixtures) { FINDERS_FIXTURES.join('plugin_version', 'readme') }
|
||||||
|
|
||||||
def version(number, found_by, confidence)
|
def version(number, found_by, confidence)
|
||||||
WPScan::Version.new(
|
WPScan::Model::Version.new(
|
||||||
number,
|
number,
|
||||||
found_by: format('Readme - %s (Aggressive Detection)', found_by),
|
found_by: format('Readme - %s (Aggressive Detection)', found_by),
|
||||||
confidence: confidence,
|
confidence: confidence,
|
||||||
@@ -31,7 +31,7 @@ describe WPScan::Finders::PluginVersion::Readme do
|
|||||||
expect(finder.aggressive).to eql @expected
|
expect(finder.aggressive).to eql @expected
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:readme_url) { plugin.url(WPScan::WpItem::READMES.sample) }
|
let(:readme_url) { plugin.url(WPScan::Model::WpItem::READMES.sample) }
|
||||||
|
|
||||||
context 'when no version' do
|
context 'when no version' do
|
||||||
it 'returns nil' do
|
it 'returns nil' do
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
describe WPScan::Finders::PluginVersion::Base do
|
describe WPScan::Finders::PluginVersion::Base do
|
||||||
subject(:plugin_version) { described_class.new(plugin) }
|
subject(:plugin_version) { described_class.new(plugin) }
|
||||||
let(:plugin) { WPScan::Plugin.new(slug, target) }
|
let(:plugin) { WPScan::Model::Plugin.new(slug, target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:default_finders) { %w[Readme] }
|
let(:default_finders) { %w[Readme] }
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ describe WPScan::Finders::Plugins::BodyPattern do
|
|||||||
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Model::Plugin }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ describe WPScan::Finders::Plugins::Comment do
|
|||||||
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Model::Plugin }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ describe WPScan::Finders::Plugins::ConfigParser do
|
|||||||
# let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
# let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
#
|
#
|
||||||
# let(:expected_all) { df_expected_all['plugins'] }
|
# let(:expected_all) { df_expected_all['plugins'] }
|
||||||
# let(:item_class) { WPScan::Plugin }
|
# let(:item_class) { WPScan::Model::Plugin }
|
||||||
# end
|
# end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ describe WPScan::Finders::Plugins::HeaderPattern do
|
|||||||
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
def plugin(slug)
|
def plugin(slug)
|
||||||
WPScan::Plugin.new(slug, target)
|
WPScan::Model::Plugin.new(slug, target)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#passive' do
|
describe '#passive' do
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ describe WPScan::Finders::Plugins::JavascriptVar do
|
|||||||
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Model::Plugin }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ describe WPScan::Finders::Plugins::Xpath do
|
|||||||
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
let(:fixtures) { DYNAMIC_FINDERS_FIXTURES.join('plugin_version') }
|
||||||
|
|
||||||
let(:expected_all) { df_expected_all['plugins'] }
|
let(:expected_all) { df_expected_all['plugins'] }
|
||||||
let(:item_class) { WPScan::Plugin }
|
let(:item_class) { WPScan::Model::Plugin }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
describe WPScan::Finders::ThemeVersion::Style do
|
describe WPScan::Finders::ThemeVersion::Style do
|
||||||
subject(:finder) { described_class.new(theme) }
|
subject(:finder) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Theme.new('spec', target) }
|
let(:theme) { WPScan::Model::Theme.new('spec', target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'style') }
|
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'style') }
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ describe WPScan::Finders::ThemeVersion::Style do
|
|||||||
|
|
||||||
it 'returns the expected version' do
|
it 'returns the expected version' do
|
||||||
expected = if expected_version
|
expected = if expected_version
|
||||||
WPScan::Version.new(
|
WPScan::Model::Version.new(
|
||||||
expected_version,
|
expected_version,
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
interesting_entries: ["#{theme.style_url}, Version: #{expected_version}"]
|
interesting_entries: ["#{theme.style_url}, Version: #{expected_version}"]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
||||||
subject(:finder) { described_class.new(theme) }
|
subject(:finder) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Theme.new(slug, target) }
|
let(:theme) { WPScan::Model::Theme.new(slug, target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'woo_framework_meta_generator') }
|
let(:fixtures) { FINDERS_FIXTURES.join('theme_version', 'woo_framework_meta_generator') }
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ describe WPScan::Finders::ThemeVersion::WooFrameworkMetaGenerator do
|
|||||||
let(:slug) { 'Editorial' }
|
let(:slug) { 'Editorial' }
|
||||||
|
|
||||||
it 'return the expected version' do
|
it 'return the expected version' do
|
||||||
@expected = WPScan::Version.new(
|
@expected = WPScan::Model::Version.new(
|
||||||
'1.3.5',
|
'1.3.5',
|
||||||
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
found_by: 'Woo Framework Meta Generator (Passive Detection)',
|
||||||
confidence: 80
|
confidence: 80
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
describe WPScan::Finders::ThemeVersion::Base do
|
describe WPScan::Finders::ThemeVersion::Base do
|
||||||
subject(:theme_version) { described_class.new(theme) }
|
subject(:theme_version) { described_class.new(theme) }
|
||||||
let(:theme) { WPScan::Plugin.new(slug, target) }
|
let(:theme) { WPScan::Model::Plugin.new(slug, target) }
|
||||||
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
let(:target) { WPScan::Target.new('http://wp.lab/') }
|
||||||
let(:slug) { 'spec' }
|
let(:slug) { 'spec' }
|
||||||
let(:default_finders) { %w[Style WooFrameworkMetaGenerator] }
|
let(:default_finders) { %w[Style WooFrameworkMetaGenerator] }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
describe WPScan::Finders::TimthumbVersion::BadRequest do
|
describe WPScan::Finders::TimthumbVersion::BadRequest do
|
||||||
subject(:finder) { described_class.new(target) }
|
subject(:finder) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Timthumb.new(url) }
|
let(:target) { WPScan::Model::Timthumb.new(url) }
|
||||||
let(:url) { 'http://ex.lo/timthumb.php' }
|
let(:url) { 'http://ex.lo/timthumb.php' }
|
||||||
let(:fixtures) { FINDERS_FIXTURES.join('timthumb_version', 'bad_request') }
|
let(:fixtures) { FINDERS_FIXTURES.join('timthumb_version', 'bad_request') }
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ describe WPScan::Finders::TimthumbVersion::BadRequest do
|
|||||||
let(:file) { '2.8.14.php' }
|
let(:file) { '2.8.14.php' }
|
||||||
|
|
||||||
it 'returns the expected version' do
|
it 'returns the expected version' do
|
||||||
@expected = WPScan::Version.new(
|
@expected = WPScan::Model::Version.new(
|
||||||
'2.8.14',
|
'2.8.14',
|
||||||
confidence: 90,
|
confidence: 90,
|
||||||
found_by: 'Bad Request (Aggressive Detection)',
|
found_by: 'Bad Request (Aggressive Detection)',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
describe WPScan::Finders::TimthumbVersion::Base do
|
describe WPScan::Finders::TimthumbVersion::Base do
|
||||||
subject(:timthumb_version) { described_class.new(target) }
|
subject(:timthumb_version) { described_class.new(target) }
|
||||||
let(:target) { WPScan::Timthumb.new(url) }
|
let(:target) { WPScan::Model::Timthumb.new(url) }
|
||||||
let(:url) { 'http://ex.lo/timthumb.php' }
|
let(:url) { 'http://ex.lo/timthumb.php' }
|
||||||
|
|
||||||
describe '#finders' do
|
describe '#finders' do
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ describe WPScan::Finders::Users::RSSGenerator do
|
|||||||
stub_request(:get, target.url('feed/rss2/'))
|
stub_request(:get, target.url('feed/rss2/'))
|
||||||
|
|
||||||
expect(finder.aggressive).to eql [
|
expect(finder.aggressive).to eql [
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'admin',
|
'admin',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
),
|
),
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'Aa Dias-Gildes',
|
'Aa Dias-Gildes',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
@@ -45,12 +45,12 @@ describe WPScan::Finders::Users::RSSGenerator do
|
|||||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||||
|
|
||||||
expect(finder.passive).to eql [
|
expect(finder.passive).to eql [
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'admin',
|
'admin',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Passive Detection)'
|
found_by: 'Rss Generator (Passive Detection)'
|
||||||
),
|
),
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'Aa Dias-Gildes',
|
'Aa Dias-Gildes',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Passive Detection)'
|
found_by: 'Rss Generator (Passive Detection)'
|
||||||
@@ -63,12 +63,12 @@ describe WPScan::Finders::Users::RSSGenerator do
|
|||||||
stub_request(:get, target.url('comments/feed/')).to_return(body: rss_fixture)
|
stub_request(:get, target.url('comments/feed/')).to_return(body: rss_fixture)
|
||||||
|
|
||||||
expect(finder.aggressive(mode: :mixed)).to eql [
|
expect(finder.aggressive(mode: :mixed)).to eql [
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'admin',
|
'admin',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
),
|
),
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'Aa Dias-Gildes',
|
'Aa Dias-Gildes',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
@@ -82,12 +82,12 @@ describe WPScan::Finders::Users::RSSGenerator do
|
|||||||
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
stub_request(:get, target.url('feed/')).to_return(body: rss_fixture)
|
||||||
|
|
||||||
expect(finder.aggressive).to eql [
|
expect(finder.aggressive).to eql [
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'admin',
|
'admin',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
),
|
),
|
||||||
CMSScanner::User.new(
|
WPScan::Model::User.new(
|
||||||
'Aa Dias-Gildes',
|
'Aa Dias-Gildes',
|
||||||
confidence: 50,
|
confidence: 50,
|
||||||
found_by: 'Rss Generator (Aggressive Detection)'
|
found_by: 'Rss Generator (Aggressive Detection)'
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe WPScan::Finders::WpVersion::AtomGenerator do
|
|||||||
stub_request(:get, target.url('?feed=atom'))
|
stub_request(:get, target.url('?feed=atom'))
|
||||||
|
|
||||||
expect(finder.aggressive).to eql [
|
expect(finder.aggressive).to eql [
|
||||||
WPScan::WpVersion.new(
|
WPScan::Model::WpVersion.new(
|
||||||
'4.0',
|
'4.0',
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
found_by: 'Atom Generator (Aggressive Detection)',
|
found_by: 'Atom Generator (Aggressive Detection)',
|
||||||
@@ -42,7 +42,7 @@ describe WPScan::Finders::WpVersion::AtomGenerator do
|
|||||||
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
|
stub_request(:get, target.url('?feed=atom')).to_return(body: atom_fixture)
|
||||||
|
|
||||||
expect(finder.passive).to eql [
|
expect(finder.passive).to eql [
|
||||||
WPScan::WpVersion.new(
|
WPScan::Model::WpVersion.new(
|
||||||
'4.0',
|
'4.0',
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
found_by: 'Atom Generator (Passive Detection)',
|
found_by: 'Atom Generator (Passive Detection)',
|
||||||
@@ -59,7 +59,7 @@ describe WPScan::Finders::WpVersion::AtomGenerator do
|
|||||||
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
|
stub_request(:get, target.url('feed/atom/')).to_return(body: atom_fixture)
|
||||||
|
|
||||||
expect(finder.aggressive(mode: :mixed)).to eql [
|
expect(finder.aggressive(mode: :mixed)).to eql [
|
||||||
WPScan::WpVersion.new(
|
WPScan::Model::WpVersion.new(
|
||||||
'4.0',
|
'4.0',
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
found_by: 'Atom Generator (Aggressive Detection)',
|
found_by: 'Atom Generator (Aggressive Detection)',
|
||||||
@@ -78,7 +78,7 @@ describe WPScan::Finders::WpVersion::AtomGenerator do
|
|||||||
stub_request(:get, target.url('?feed=atom'))
|
stub_request(:get, target.url('?feed=atom'))
|
||||||
|
|
||||||
expect(finder.aggressive).to eql [
|
expect(finder.aggressive).to eql [
|
||||||
WPScan::WpVersion.new(
|
WPScan::Model::WpVersion.new(
|
||||||
'4.0',
|
'4.0',
|
||||||
confidence: 80,
|
confidence: 80,
|
||||||
found_by: 'Atom Generator (Aggressive Detection)',
|
found_by: 'Atom Generator (Aggressive Detection)',
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ describe WPScan::Finders::WpVersion::Readme do
|
|||||||
let(:file) { '4.0.html' }
|
let(:file) { '4.0.html' }
|
||||||
|
|
||||||
it 'returns the expected version' do
|
it 'returns the expected version' do
|
||||||
@expected = WPScan::WpVersion.new(
|
@expected = WPScan::Model::WpVersion.new(
|
||||||
'4.0',
|
'4.0',
|
||||||
confidence: 90,
|
confidence: 90,
|
||||||
found_by: 'Readme (Aggressive Detection)',
|
found_by: 'Readme (Aggressive Detection)',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
describe WPScan::InterestingFinding do
|
describe WPScan::Model::InterestingFinding do
|
||||||
it_behaves_like WPScan::References do
|
it_behaves_like WPScan::References do
|
||||||
subject(:finding) { described_class.new('http://e.org/file.php', opts) }
|
subject(:finding) { described_class.new('http://e.org/file.php', opts) }
|
||||||
let(:opts) { { references: references } }
|
let(:opts) { { references: references } }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
describe WPScan::Media do
|
describe WPScan::Model::Media do
|
||||||
subject(:media) { described_class.new(url) }
|
subject(:media) { described_class.new(url) }
|
||||||
let(:url) { 'http://e.oeg/?attachment_id=2' }
|
let(:url) { 'http://e.oeg/?attachment_id=2' }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
describe WPScan::Plugin do
|
describe WPScan::Model::Plugin do
|
||||||
subject(:plugin) { described_class.new(slug, blog, opts) }
|
subject(:plugin) { described_class.new(slug, blog, opts) }
|
||||||
let(:slug) { 'spec' }
|
let(:slug) { 'spec' }
|
||||||
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
||||||
@@ -70,7 +70,7 @@ describe WPScan::Plugin do
|
|||||||
context 'when values' do
|
context 'when values' do
|
||||||
let(:slug) { 'no-vulns-popular' }
|
let(:slug) { 'no-vulns-popular' }
|
||||||
|
|
||||||
its(:latest_version) { should eql WPScan::Version.new('2.0') }
|
its(:latest_version) { should eql WPScan::Model::Version.new('2.0') }
|
||||||
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z' }
|
its(:last_updated) { should eql '2015-05-16T00:00:00.000Z' }
|
||||||
its(:popular?) { should be true }
|
its(:popular?) { should be true }
|
||||||
end
|
end
|
||||||
@@ -87,7 +87,12 @@ describe WPScan::Plugin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when version' do
|
context 'when version' do
|
||||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new(version_number)) }
|
before do
|
||||||
|
expect(plugin)
|
||||||
|
.to receive(:version)
|
||||||
|
.at_least(1)
|
||||||
|
.and_return(WPScan::Model::Version.new(version_number))
|
||||||
|
end
|
||||||
|
|
||||||
context 'when version < last_version' do
|
context 'when version < last_version' do
|
||||||
let(:version_number) { '1.2' }
|
let(:version_number) { '1.2' }
|
||||||
@@ -113,7 +118,12 @@ describe WPScan::Plugin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when version' do
|
context 'when version' do
|
||||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new('1.0')) }
|
before do
|
||||||
|
expect(plugin)
|
||||||
|
.to receive(:version)
|
||||||
|
.at_least(1)
|
||||||
|
.and_return(WPScan::Model::Version.new('1.0'))
|
||||||
|
end
|
||||||
|
|
||||||
its(:outdated?) { should eql false }
|
its(:outdated?) { should eql false }
|
||||||
end
|
end
|
||||||
@@ -166,7 +176,12 @@ describe WPScan::Plugin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
context 'when plugin version' do
|
context 'when plugin version' do
|
||||||
before { expect(plugin).to receive(:version).at_least(1).and_return(WPScan::Version.new(number)) }
|
before do
|
||||||
|
expect(plugin)
|
||||||
|
.to receive(:version)
|
||||||
|
.at_least(1)
|
||||||
|
.and_return(WPScan::Model::Version.new(number))
|
||||||
|
end
|
||||||
|
|
||||||
context 'when < to a fixed_in' do
|
context 'when < to a fixed_in' do
|
||||||
let(:number) { '5.0' }
|
let(:number) { '5.0' }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
describe WPScan::Theme do
|
describe WPScan::Model::Theme do
|
||||||
subject(:theme) { described_class.new(slug, blog, opts) }
|
subject(:theme) { described_class.new(slug, blog, opts) }
|
||||||
let(:slug) { 'spec' }
|
let(:slug) { 'spec' }
|
||||||
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
let(:blog) { WPScan::Target.new('http://wp.lab/') }
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user