fix some code styling issues
This commit is contained in:
@@ -23,7 +23,7 @@ end
|
||||
html = open(html_path).read
|
||||
examples = html.match(/(\d+) examples/)[0].to_i rescue 0
|
||||
errors = html.match(/(\d+) errors/)[0].to_i rescue 0
|
||||
if errors == 0 then
|
||||
if errors == 0
|
||||
errors = html.match(/(\d+) failure/)[0].to_i rescue 0
|
||||
end
|
||||
pending = html.match(/(\d+) pending/)[0].to_i rescue 0
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_items/detectable'
|
||||
require 'common/collections/wp_items/output'
|
||||
|
||||
class WpItems < Array
|
||||
extend WpItems::Detectable
|
||||
include WpItems::Output
|
||||
|
||||
attr_accessor :wp_target
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
def initialize(wp_target = nil)
|
||||
self.wp_target = wp_target
|
||||
end
|
||||
|
||||
# @param [String] argv
|
||||
#
|
||||
# @return [ void ]
|
||||
def add(*args)
|
||||
index = 0
|
||||
|
||||
until args[index].nil?
|
||||
arg = args[index]
|
||||
|
||||
if arg.is_a?(String)
|
||||
if (next_arg = args[index + 1]).is_a?(Hash)
|
||||
item = create_item(arg, next_arg)
|
||||
index += 1
|
||||
else
|
||||
item = create_item(arg)
|
||||
end
|
||||
elsif arg.is_a?(Item)
|
||||
item = arg
|
||||
else
|
||||
raise 'Invalid arguments'
|
||||
end
|
||||
|
||||
self << item
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
|
||||
# @param [ String ] name
|
||||
# @param [ Hash ] attrs
|
||||
#
|
||||
# @return [ WpItem ]
|
||||
def create_item(name, attrs = {})
|
||||
raise 'wp_target must be set' unless wp_target
|
||||
|
||||
item_class.new(
|
||||
wp_target.uri,
|
||||
attrs.merge(
|
||||
name: name,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir
|
||||
) { |key, oldval, newval| oldval }
|
||||
)
|
||||
end
|
||||
|
||||
# @param [ WpItems ] other
|
||||
#
|
||||
# @return [ self ]
|
||||
def +(other)
|
||||
other.each { |item| self << item }
|
||||
self
|
||||
end
|
||||
|
||||
protected
|
||||
# @return [ Class ]
|
||||
def item_class
|
||||
Object.const_get(self.class.to_s.gsub(/.$/, ''))
|
||||
end
|
||||
end
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_items/detectable'
|
||||
require 'common/collections/wp_items/output'
|
||||
|
||||
class WpItems < Array
|
||||
extend WpItems::Detectable
|
||||
include WpItems::Output
|
||||
|
||||
attr_accessor :wp_target
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
def initialize(wp_target = nil)
|
||||
self.wp_target = wp_target
|
||||
end
|
||||
|
||||
# @param [String] args
|
||||
#
|
||||
# @return [ void ]
|
||||
def add(*args)
|
||||
index = 0
|
||||
|
||||
until args[index].nil?
|
||||
arg = args[index]
|
||||
|
||||
if arg.is_a?(String)
|
||||
if (next_arg = args[index + 1]).is_a?(Hash)
|
||||
item = create_item(arg, next_arg)
|
||||
index += 1
|
||||
else
|
||||
item = create_item(arg)
|
||||
end
|
||||
elsif arg.is_a?(Item)
|
||||
item = arg
|
||||
else
|
||||
raise 'Invalid arguments'
|
||||
end
|
||||
|
||||
self << item
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
|
||||
# @param [ String ] name
|
||||
# @param [ Hash ] attrs
|
||||
#
|
||||
# @return [ WpItem ]
|
||||
def create_item(name, attrs = {})
|
||||
raise 'wp_target must be set' unless wp_target
|
||||
|
||||
item_class.new(
|
||||
wp_target.uri,
|
||||
attrs.merge(
|
||||
name: name,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir
|
||||
) { |key, oldval, newval| oldval }
|
||||
)
|
||||
end
|
||||
|
||||
# @param [ WpItems ] other
|
||||
#
|
||||
# @return [ self ]
|
||||
def +(other)
|
||||
other.each { |item| self << item }
|
||||
self
|
||||
end
|
||||
|
||||
protected
|
||||
# @return [ Class ]
|
||||
def item_class
|
||||
Object.const_get(self.class.to_s.gsub(/.$/, ''))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,238 +1,238 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpItems < Array
|
||||
module Detectable
|
||||
|
||||
attr_reader :vulns_file, :item_xpath
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Hash ] options
|
||||
# @option options [ Boolean ] :show_progression Whether or not output the progress bar
|
||||
# @option options [ Boolean ] :only_vulnerable Only check for vulnerable items
|
||||
# @option options [ String ] :exclude_content
|
||||
#
|
||||
# @return [ WpItems ]
|
||||
def aggressive_detection(wp_target, options = {})
|
||||
browser = Browser.instance
|
||||
hydra = browser.hydra
|
||||
targets = targets_items(wp_target, options)
|
||||
progress_bar = progress_bar(targets.size, options)
|
||||
queue_count = 0
|
||||
exist_options = {
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
exclude_content: options[:exclude_content] ? %r{#{options[:exclude_content]}} : nil
|
||||
}
|
||||
results = passive_detection(wp_target, options)
|
||||
|
||||
targets.each do |target_item|
|
||||
request = browser.forge_request(target_item.url, request_params)
|
||||
|
||||
request.on_complete do |response|
|
||||
progress_bar.progress += 1 if options[:show_progression]
|
||||
|
||||
if target_item.exists?(exist_options, response)
|
||||
if !results.include?(target_item)
|
||||
if !options[:only_vulnerable] || options[:only_vulnerable] && target_item.vulnerable?
|
||||
results << target_item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hydra.queue(request)
|
||||
queue_count += 1
|
||||
|
||||
if queue_count >= browser.max_threads
|
||||
hydra.run
|
||||
queue_count = 0
|
||||
puts "Sent #{browser.max_threads} requests ..." if options[:verbose]
|
||||
end
|
||||
end
|
||||
|
||||
# run the remaining requests
|
||||
hydra.run
|
||||
|
||||
results.select!(&:vulnerable?) if options[:only_vulnerable]
|
||||
results.sort!
|
||||
|
||||
results # can't just return results.sort as it would return an array, and we want a WpItems
|
||||
end
|
||||
|
||||
# @param [ Integer ] targets_size
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ ProgressBar ]
|
||||
# :nocov:
|
||||
def progress_bar(targets_size, options)
|
||||
if options[:show_progression]
|
||||
ProgressBar.create(
|
||||
format: '%t %a <%B> (%c / %C) %P%% %e',
|
||||
title: ' ', # Used to craete a left margin
|
||||
total: targets_size
|
||||
)
|
||||
end
|
||||
end
|
||||
# :nocov:
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ WpItems ]
|
||||
def passive_detection(wp_target, options = {})
|
||||
results = new(wp_target)
|
||||
# improves speed
|
||||
body = remove_base64_images_from_html(Browser.get(wp_target.url).body)
|
||||
page = Nokogiri::HTML(body)
|
||||
names = []
|
||||
|
||||
page.css('link,script,style').each do |tag|
|
||||
%w(href src).each do |attribute|
|
||||
attr_value = tag.attribute(attribute).to_s
|
||||
next unless attr_value
|
||||
|
||||
names << Regexp.last_match[1] if attr_value.match(attribute_pattern(wp_target))
|
||||
end
|
||||
|
||||
next unless tag.name == 'script' || tag.name == 'style'
|
||||
|
||||
code = tag.text.to_s
|
||||
next if code.empty?
|
||||
|
||||
code.scan(code_pattern(wp_target)).flatten.uniq.each do |item_name|
|
||||
names << item_name
|
||||
end
|
||||
end
|
||||
|
||||
names.uniq.each { |name| results.add(name) }
|
||||
|
||||
results.sort!
|
||||
results
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def item_pattern(wp_target)
|
||||
type = to_s.gsub(/Wp/, '').downcase
|
||||
wp_content_dir = wp_target.wp_content_dir
|
||||
wp_content_url = wp_target.uri.merge(wp_content_dir).to_s
|
||||
|
||||
url = /#{wp_content_url.gsub(%r{\A(?:http|https)}, 'https?').gsub('/', '\\\\\?\/')}/i
|
||||
content_dir = %r{(?:#{url}|\\?\/\\?\/?#{wp_content_dir})}i
|
||||
|
||||
%r{#{content_dir}\\?/#{type}\\?/}
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def attribute_pattern(wp_target)
|
||||
/\A#{item_pattern(wp_target)}([^\/]+)/i
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def code_pattern(wp_target)
|
||||
/["'\(]#{item_pattern(wp_target)}([^\\\/\)"']+)/i
|
||||
end
|
||||
|
||||
# The default request parameters
|
||||
#
|
||||
# @return [ Hash ]
|
||||
def request_params; { cache_ttl: 0, followlocation: true } end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ options ] options
|
||||
# @option options [ Boolean ] :only_vulnerable
|
||||
# @option options [ String ] :file The path to the file containing the targets
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def targets_items(wp_target, options = {})
|
||||
item_class = self.item_class
|
||||
vulns_file = self.vulns_file
|
||||
|
||||
targets = vulnerable_targets_items(wp_target, item_class, vulns_file)
|
||||
|
||||
unless options[:only_vulnerable]
|
||||
unless options[:file]
|
||||
raise 'A file must be supplied'
|
||||
end
|
||||
|
||||
targets += targets_items_from_file(options[:file], wp_target, item_class, vulns_file)
|
||||
end
|
||||
|
||||
targets.uniq! { |t| t.name }
|
||||
targets.sort_by { rand }
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Class ] item_class
|
||||
# @param [ String ] vulns_file
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def vulnerable_targets_items(wp_target, item_class, vulns_file)
|
||||
targets = []
|
||||
json = json(vulns_file)
|
||||
|
||||
[*json].each do |item|
|
||||
targets << create_item(
|
||||
item_class,
|
||||
item.keys.inject,
|
||||
wp_target,
|
||||
vulns_file
|
||||
)
|
||||
end
|
||||
|
||||
targets
|
||||
end
|
||||
|
||||
# @param [ Class ] klass
|
||||
# @param [ String ] name
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @option [ String ] vulns_file
|
||||
#
|
||||
# @return [ WpItem ]
|
||||
def create_item(klass, name, wp_target, vulns_file = nil)
|
||||
klass.new(
|
||||
wp_target.uri,
|
||||
name: name,
|
||||
vulns_file: vulns_file,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir
|
||||
)
|
||||
end
|
||||
|
||||
# @param [ String ] file
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Class ] item_class
|
||||
# @param [ String ] vulns_file
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def targets_items_from_file(file, wp_target, item_class, vulns_file)
|
||||
targets = []
|
||||
|
||||
File.open(file, 'r') do |f|
|
||||
f.readlines.collect do |item_name|
|
||||
targets << create_item(
|
||||
item_class,
|
||||
item_name.strip,
|
||||
wp_target,
|
||||
vulns_file
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
targets
|
||||
end
|
||||
|
||||
# @return [ Class ]
|
||||
def item_class
|
||||
Object.const_get(self.to_s.gsub(/.$/, ''))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpItems < Array
|
||||
module Detectable
|
||||
|
||||
attr_reader :vulns_file, :item_xpath
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Hash ] options
|
||||
# @option options [ Boolean ] :show_progression Whether or not output the progress bar
|
||||
# @option options [ Boolean ] :only_vulnerable Only check for vulnerable items
|
||||
# @option options [ String ] :exclude_content
|
||||
#
|
||||
# @return [ WpItems ]
|
||||
def aggressive_detection(wp_target, options = {})
|
||||
browser = Browser.instance
|
||||
hydra = browser.hydra
|
||||
targets = targets_items(wp_target, options)
|
||||
progress_bar = progress_bar(targets.size, options)
|
||||
queue_count = 0
|
||||
exist_options = {
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
exclude_content: options[:exclude_content] ? %r{#{options[:exclude_content]}} : nil
|
||||
}
|
||||
results = passive_detection(wp_target, options)
|
||||
|
||||
targets.each do |target_item|
|
||||
request = browser.forge_request(target_item.url, request_params)
|
||||
|
||||
request.on_complete do |response|
|
||||
progress_bar.progress += 1 if options[:show_progression]
|
||||
|
||||
if target_item.exists?(exist_options, response)
|
||||
unless results.include?(target_item)
|
||||
if !options[:only_vulnerable] || options[:only_vulnerable] && target_item.vulnerable?
|
||||
results << target_item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hydra.queue(request)
|
||||
queue_count += 1
|
||||
|
||||
if queue_count >= browser.max_threads
|
||||
hydra.run
|
||||
queue_count = 0
|
||||
puts "Sent #{browser.max_threads} requests ..." if options[:verbose]
|
||||
end
|
||||
end
|
||||
|
||||
# run the remaining requests
|
||||
hydra.run
|
||||
|
||||
results.select!(&:vulnerable?) if options[:only_vulnerable]
|
||||
results.sort!
|
||||
|
||||
results # can't just return results.sort as it would return an array, and we want a WpItems
|
||||
end
|
||||
|
||||
# @param [ Integer ] targets_size
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ ProgressBar ]
|
||||
# :nocov:
|
||||
def progress_bar(targets_size, options)
|
||||
if options[:show_progression]
|
||||
ProgressBar.create(
|
||||
format: '%t %a <%B> (%c / %C) %P%% %e',
|
||||
title: ' ', # Used to craete a left margin
|
||||
total: targets_size
|
||||
)
|
||||
end
|
||||
end
|
||||
# :nocov:
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ WpItems ]
|
||||
def passive_detection(wp_target, options = {})
|
||||
results = new(wp_target)
|
||||
# improves speed
|
||||
body = remove_base64_images_from_html(Browser.get(wp_target.url).body)
|
||||
page = Nokogiri::HTML(body)
|
||||
names = []
|
||||
|
||||
page.css('link,script,style').each do |tag|
|
||||
%w(href src).each do |attribute|
|
||||
attr_value = tag.attribute(attribute).to_s
|
||||
next unless attr_value
|
||||
|
||||
names << Regexp.last_match[1] if attr_value.match(attribute_pattern(wp_target))
|
||||
end
|
||||
|
||||
next unless tag.name == 'script' || tag.name == 'style'
|
||||
|
||||
code = tag.text.to_s
|
||||
next if code.empty?
|
||||
|
||||
code.scan(code_pattern(wp_target)).flatten.uniq.each do |item_name|
|
||||
names << item_name
|
||||
end
|
||||
end
|
||||
|
||||
names.uniq.each { |name| results.add(name) }
|
||||
|
||||
results.sort!
|
||||
results
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def item_pattern(wp_target)
|
||||
type = to_s.gsub(/Wp/, '').downcase
|
||||
wp_content_dir = wp_target.wp_content_dir
|
||||
wp_content_url = wp_target.uri.merge(wp_content_dir).to_s
|
||||
|
||||
url = /#{wp_content_url.gsub(%r{\A(?:http|https)}, 'https?').gsub('/', '\\\\\?\/')}/i
|
||||
content_dir = %r{(?:#{url}|\\?\/\\?\/?#{wp_content_dir})}i
|
||||
|
||||
%r{#{content_dir}\\?/#{type}\\?/}
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def attribute_pattern(wp_target)
|
||||
/\A#{item_pattern(wp_target)}([^\/]+)/i
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
#
|
||||
# @return [ Regex ]
|
||||
def code_pattern(wp_target)
|
||||
/["'\(]#{item_pattern(wp_target)}([^\\\/\)"']+)/i
|
||||
end
|
||||
|
||||
# The default request parameters
|
||||
#
|
||||
# @return [ Hash ]
|
||||
def request_params; { cache_ttl: 0, followlocation: true } end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ options ] options
|
||||
# @option options [ Boolean ] :only_vulnerable
|
||||
# @option options [ String ] :file The path to the file containing the targets
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def targets_items(wp_target, options = {})
|
||||
item_class = self.item_class
|
||||
vulns_file = self.vulns_file
|
||||
|
||||
targets = vulnerable_targets_items(wp_target, item_class, vulns_file)
|
||||
|
||||
unless options[:only_vulnerable]
|
||||
unless options[:file]
|
||||
raise 'A file must be supplied'
|
||||
end
|
||||
|
||||
targets += targets_items_from_file(options[:file], wp_target, item_class, vulns_file)
|
||||
end
|
||||
|
||||
targets.uniq! { |t| t.name }
|
||||
targets.sort_by { rand }
|
||||
end
|
||||
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Class ] item_class
|
||||
# @param [ String ] vulns_file
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def vulnerable_targets_items(wp_target, item_class, vulns_file)
|
||||
targets = []
|
||||
json = json(vulns_file)
|
||||
|
||||
[*json].each do |item|
|
||||
targets << create_item(
|
||||
item_class,
|
||||
item.keys.inject,
|
||||
wp_target,
|
||||
vulns_file
|
||||
)
|
||||
end
|
||||
|
||||
targets
|
||||
end
|
||||
|
||||
# @param [ Class ] klass
|
||||
# @param [ String ] name
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @option [ String ] vulns_file
|
||||
#
|
||||
# @return [ WpItem ]
|
||||
def create_item(klass, name, wp_target, vulns_file = nil)
|
||||
klass.new(
|
||||
wp_target.uri,
|
||||
name: name,
|
||||
vulns_file: vulns_file,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir
|
||||
)
|
||||
end
|
||||
|
||||
# @param [ String ] file
|
||||
# @param [ WpTarget ] wp_target
|
||||
# @param [ Class ] item_class
|
||||
# @param [ String ] vulns_file
|
||||
#
|
||||
# @return [ Array<WpItem> ]
|
||||
def targets_items_from_file(file, wp_target, item_class, vulns_file)
|
||||
targets = []
|
||||
|
||||
File.open(file, 'r') do |f|
|
||||
f.readlines.collect do |item_name|
|
||||
targets << create_item(
|
||||
item_class,
|
||||
item_name.strip,
|
||||
wp_target,
|
||||
vulns_file
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
targets
|
||||
end
|
||||
|
||||
# @return [ Class ]
|
||||
def item_class
|
||||
Object.const_get(self.to_s.gsub(/.$/, ''))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,7 +41,7 @@ $LOAD_PATH.unshift(MODELS_LIB_DIR)
|
||||
|
||||
def kali_linux?
|
||||
begin
|
||||
File.readlines("/etc/debian_version").grep(/^kali/i).any?
|
||||
File.readlines('/etc/debian_version').grep(/^kali/i).any?
|
||||
rescue
|
||||
false
|
||||
end
|
||||
@@ -54,7 +54,7 @@ def require_files_from_directory(absolute_dir_path, files_pattern = '*.rb')
|
||||
files = Dir[File.join(absolute_dir_path, files_pattern)]
|
||||
|
||||
# Files in the root dir are loaded first, then those in the subdirectories
|
||||
files.sort_by { |file| [file.count("/"), file] }.each do |f|
|
||||
files.sort_by { |file| [file.count('/'), file] }.each do |f|
|
||||
f = File.expand_path(f)
|
||||
#puts "require #{f}" # Used for debug
|
||||
require f
|
||||
@@ -82,7 +82,7 @@ end
|
||||
def update_required?
|
||||
return true unless File.exist?(LAST_UPDATE_FILE)
|
||||
content = File.read(LAST_UPDATE_FILE)
|
||||
date = Time.parse(content) rescue Time.parse("2000-01-01")
|
||||
date = Time.parse(content) rescue Time.parse('2000-01-01')
|
||||
return date < 5.days.ago
|
||||
end
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class HttpError < StandardError
|
||||
attr_reader :response
|
||||
|
||||
# @param [ Typhoeus::Response ] res
|
||||
# @param [ Typhoeus::Response ] response
|
||||
def initialize(response)
|
||||
@response = response
|
||||
end
|
||||
|
||||
@@ -78,7 +78,7 @@ module Terminal
|
||||
|
||||
class Style
|
||||
@@defaults = {
|
||||
:border_x => "-", :border_y => "|", :border_i => "+",
|
||||
:border_x => '-', :border_y => '|', :border_i => '+',
|
||||
:padding_left => 1, :padding_right => 1,
|
||||
:margin_left => '',
|
||||
:width => nil, :alignment => nil
|
||||
@@ -102,7 +102,7 @@ class Numeric
|
||||
def bytes_to_human
|
||||
units = %w{B KB MB GB TB}
|
||||
e = (Math.log(self)/Math.log(1024)).floor
|
||||
s = "%.3f" % (to_f / 1024**e)
|
||||
s = '%.3f' % (to_f / 1024**e)
|
||||
s.sub(/\.?0*$/, ' ' + units[e])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,8 +15,8 @@ class Vulnerability
|
||||
puts " Reference: #{url}" if url
|
||||
end
|
||||
end
|
||||
if !fixed_in.nil?
|
||||
puts notice("Fixed in: #{fixed_in}")
|
||||
unless fixed_in.nil?
|
||||
puts notice("Fixed in: #{fixed_in}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ class WpItem
|
||||
# @return [ String ]
|
||||
def to_s
|
||||
item_version = self.version
|
||||
"#@name#{' - v' + item_version.strip if item_version}"
|
||||
"#{@name}#{' - v' + item_version.strip if item_version}"
|
||||
end
|
||||
|
||||
# Extracts the version number from a given string/body
|
||||
|
||||
@@ -14,7 +14,7 @@ class WpTheme < WpItem
|
||||
|
||||
def get_parent_theme_style_url
|
||||
if is_child_theme?
|
||||
return style_url.sub("/#{name}/style.css", "/#@theme_template/style.css")
|
||||
return style_url.sub("/#{name}/style.css", "/#{@theme_template}/style.css")
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
@@ -10,16 +10,16 @@ class WpTheme
|
||||
theme_desc = verbose ? @theme_description : truncate(@theme_description, 100)
|
||||
puts " | Style URL: #{style_url}"
|
||||
puts " | Referenced style.css: #{referenced_url}" if referenced_url && referenced_url != style_url
|
||||
puts " | Theme Name: #@theme_name" if @theme_name
|
||||
puts " | Theme URI: #@theme_uri" if @theme_uri
|
||||
puts " | Theme Name: #{@theme_name}" if @theme_name
|
||||
puts " | Theme URI: #{@theme_uri}" if @theme_uri
|
||||
puts " | Description: #{theme_desc}"
|
||||
puts " | Author: #@theme_author" if @theme_author
|
||||
puts " | Author URI: #@theme_author_uri" if @theme_author_uri
|
||||
puts " | Template: #@theme_template" if @theme_template and verbose
|
||||
puts " | License: #@theme_license" if @theme_license and verbose
|
||||
puts " | License URI: #@theme_license_uri" if @theme_license_uri and verbose
|
||||
puts " | Tags: #@theme_tags" if @theme_tags and verbose
|
||||
puts " | Text Domain: #@theme_text_domain" if @theme_text_domain and verbose
|
||||
puts " | Author: #{@theme_author}" if @theme_author
|
||||
puts " | Author URI: #{@theme_author_uri}" if @theme_author_uri
|
||||
puts " | Template: #{@theme_template}" if @theme_template and verbose
|
||||
puts " | License: #{@theme_license}" if @theme_license and verbose
|
||||
puts " | License URI: #{@theme_license_uri}" if @theme_license_uri and verbose
|
||||
puts " | Tags: #{@theme_tags}" if @theme_tags and verbose
|
||||
puts " | Text Domain: #{@theme_text_domain}" if @theme_text_domain and verbose
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,7 +15,7 @@ class WpTimthumb < WpItem
|
||||
end
|
||||
|
||||
def check_rce_132
|
||||
return rce_132_vuln unless VersionCompare.lesser_or_equal?('1.33', version)
|
||||
rce_132_vuln unless VersionCompare.lesser_or_equal?('1.33', version)
|
||||
end
|
||||
|
||||
# Vulnerable versions : > 1.35 (or >= 2.0) and < 2.8.14
|
||||
@@ -24,7 +24,7 @@ class WpTimthumb < WpItem
|
||||
|
||||
response = Browser.get(uri.merge('?webshot=1&src=http://' + default_allowed_domains.sample))
|
||||
|
||||
return rce_webshot_vuln unless response.body =~ /WEBSHOT_ENABLED == true/
|
||||
rce_webshot_vuln unless response.body =~ /WEBSHOT_ENABLED == true/
|
||||
end
|
||||
|
||||
# @return [ Array<String> ] The default allowed domains (between the 2.0 and 2.8.13)
|
||||
|
||||
@@ -1,81 +1,81 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'wp_user/existable'
|
||||
require 'wp_user/brute_forcable'
|
||||
|
||||
class WpUser < WpItem
|
||||
include WpUser::Existable
|
||||
include WpUser::BruteForcable
|
||||
|
||||
attr_accessor :id, :login, :display_name, :password
|
||||
|
||||
# @return [ Array<Symbol> ]
|
||||
def allowed_options; [:id, :login, :display_name, :password] end
|
||||
|
||||
# @return [ URI ] The uri to the author page
|
||||
def uri
|
||||
if id
|
||||
return @uri.merge("?author=#{id}")
|
||||
else
|
||||
raise 'The id is nil'
|
||||
end
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
def login_url
|
||||
unless @login_url
|
||||
@login_url = @uri.merge('wp-login.php').to_s
|
||||
|
||||
# Let's check if the login url is redirected (to https url for example)
|
||||
if redirection = redirection(@login_url)
|
||||
@login_url = redirection
|
||||
end
|
||||
end
|
||||
|
||||
@login_url
|
||||
end
|
||||
|
||||
def redirection(url)
|
||||
redirection = nil
|
||||
response = Browser.get(url)
|
||||
|
||||
if response.code == 301 || response.code == 302
|
||||
redirection = response.headers_hash['location']
|
||||
|
||||
# Let's check if there is a redirection in the redirection
|
||||
if other_redirection = redirection(redirection)
|
||||
redirection = other_redirection
|
||||
end
|
||||
end
|
||||
|
||||
redirection
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
def to_s
|
||||
s = "#{id}"
|
||||
s << " | #{login}" if login
|
||||
s << " | #{display_name}" if display_name
|
||||
s
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
def <=>(other)
|
||||
id <=> other.id
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def ==(other)
|
||||
self === other
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def ===(other)
|
||||
id === other.id && login === other.login
|
||||
end
|
||||
|
||||
end
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'wp_user/existable'
|
||||
require 'wp_user/brute_forcable'
|
||||
|
||||
class WpUser < WpItem
|
||||
include WpUser::Existable
|
||||
include WpUser::BruteForcable
|
||||
|
||||
attr_accessor :id, :login, :display_name, :password
|
||||
|
||||
# @return [ Array<Symbol> ]
|
||||
def allowed_options; [:id, :login, :display_name, :password] end
|
||||
|
||||
# @return [ URI ] The uri to the author page
|
||||
def uri
|
||||
if id
|
||||
@uri.merge("?author=#{id}")
|
||||
else
|
||||
raise 'The id is nil'
|
||||
end
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
def login_url
|
||||
unless @login_url
|
||||
@login_url = @uri.merge('wp-login.php').to_s
|
||||
|
||||
# Let's check if the login url is redirected (to https url for example)
|
||||
if redirection = redirection(@login_url)
|
||||
@login_url = redirection
|
||||
end
|
||||
end
|
||||
|
||||
@login_url
|
||||
end
|
||||
|
||||
def redirection(url)
|
||||
redirection = nil
|
||||
response = Browser.get(url)
|
||||
|
||||
if response.code == 301 || response.code == 302
|
||||
redirection = response.headers_hash['location']
|
||||
|
||||
# Let's check if there is a redirection in the redirection
|
||||
if other_redirection = redirection(redirection)
|
||||
redirection = other_redirection
|
||||
end
|
||||
end
|
||||
|
||||
redirection
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
def to_s
|
||||
s = "#{id}"
|
||||
s << " | #{login}" if login
|
||||
s << " | #{display_name}" if display_name
|
||||
s
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
def <=>(other)
|
||||
id <=> other.id
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def ==(other)
|
||||
self === other
|
||||
end
|
||||
|
||||
# @param [ WpUser ] other
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def ===(other)
|
||||
id === other.id && login === other.login
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ class WpUser < WpItem
|
||||
# Generate a random one on each request
|
||||
unless redirect_url
|
||||
random = (0...8).map { 65.+(rand(26)).chr }.join
|
||||
redirect_url = "#@uri#{random}/"
|
||||
redirect_url = "#{@uri}#{random}/"
|
||||
end
|
||||
|
||||
request = login_request(password, redirect_url)
|
||||
@@ -66,7 +66,7 @@ class WpUser < WpItem
|
||||
puts if options[:show_progression] # mandatory to avoid the output of the progressbar to be overriden
|
||||
end
|
||||
|
||||
# @param [ Integer ] targets_size
|
||||
# @param [ Integer ] passwords_size
|
||||
# @param [ Hash ] options
|
||||
#
|
||||
# @return [ ProgressBar ]
|
||||
|
||||
@@ -7,13 +7,13 @@ class WpTarget < WebSite
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def has_full_path_disclosure?
|
||||
response = Browser.get(full_path_disclosure_url())
|
||||
response = Browser.get(full_path_disclosure_url)
|
||||
response.body[%r{Fatal error}i] ? true : false
|
||||
end
|
||||
|
||||
def full_path_disclosure_data
|
||||
return nil unless has_full_path_disclosure?
|
||||
Browser.get(full_path_disclosure_url()).body[%r{<b>([^<]+\.php)</b>}, 1]
|
||||
Browser.get(full_path_disclosure_url).body[%r{<b>([^<]+\.php)</b>}, 1]
|
||||
end
|
||||
|
||||
# @return [ String ]
|
||||
|
||||
@@ -8,7 +8,7 @@ class WpTarget < WebSite
|
||||
@login_protection_plugin = nil
|
||||
|
||||
def has_login_protection?
|
||||
!login_protection_plugin().nil?
|
||||
!login_protection_plugin.nil?
|
||||
end
|
||||
|
||||
# Checks if a login protection plugin is enabled
|
||||
@@ -74,7 +74,7 @@ class WpTarget < WebSite
|
||||
|
||||
# http://wordpress.org/extend/plugins/login-security-solution/
|
||||
def has_login_security_solution_protection?
|
||||
Browser.get(login_security_solution_url()).code != 404
|
||||
Browser.get(login_security_solution_url).code != 404
|
||||
end
|
||||
|
||||
def login_security_solution_url
|
||||
|
||||
@@ -10,7 +10,7 @@ class WpTarget < WebSite
|
||||
#
|
||||
# @return [ Boolean ]
|
||||
def has_readme?
|
||||
response = Browser.get(readme_url())
|
||||
response = Browser.get(readme_url)
|
||||
|
||||
unless response.code == 404
|
||||
return response.body =~ %r{wordpress}i ? true : false
|
||||
|
||||
@@ -64,7 +64,7 @@ describe Browser do
|
||||
|
||||
it 'raises an error' do
|
||||
File.symlink('./testfile', config_file)
|
||||
expect { browser.load_config(config_file) }.to raise_error("[ERROR] Config file is a symlink.")
|
||||
expect { browser.load_config(config_file) }.to raise_error('[ERROR] Config file is a symlink.')
|
||||
File.unlink(config_file)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -92,7 +92,7 @@ describe CacheFileStore do
|
||||
it 'should create a unique storage dir' do
|
||||
storage_dirs = []
|
||||
|
||||
(1..5).each do |i|
|
||||
(1..5).each do |_|
|
||||
storage_dirs << CacheFileStore.new(cache_dir).storage_path
|
||||
end
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ describe 'WpTheme::Findable' do
|
||||
end
|
||||
end
|
||||
|
||||
stub_all_to_nil()
|
||||
stub_all_to_nil
|
||||
|
||||
expect { WpTheme.find(uri) }.to_not raise_error
|
||||
end
|
||||
@@ -129,7 +129,7 @@ describe 'WpTheme::Findable' do
|
||||
|
||||
context 'when the theme is not found' do
|
||||
it 'returns nil' do
|
||||
stub_all_to_nil()
|
||||
stub_all_to_nil
|
||||
|
||||
expect(WpTheme.find(uri)).to be_nil
|
||||
end
|
||||
@@ -137,7 +137,7 @@ describe 'WpTheme::Findable' do
|
||||
|
||||
context 'when the theme is found' do
|
||||
it 'returns it, with the :found_from set' do
|
||||
stub_all_to_nil()
|
||||
stub_all_to_nil
|
||||
stub_request(:get, /.+\/the-oracle\/style.css$/).to_return(status: 200)
|
||||
expected = WpTheme.new(uri, name: 'the-oracle')
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ describe 'WpVersion::Findable' do
|
||||
|
||||
context 'when no version found' do
|
||||
it 'returns nil' do
|
||||
stub_all_to_nil()
|
||||
stub_all_to_nil
|
||||
@expected = nil
|
||||
end
|
||||
end
|
||||
@@ -188,8 +188,8 @@ describe 'WpVersion::Findable' do
|
||||
found_from = method[/^find_from_(.*)/, 1].sub('_', ' ')
|
||||
|
||||
context "when found from #{found_from}" do
|
||||
it "returns the correct WpVersion" do
|
||||
stub_all_to_nil()
|
||||
it 'returns the correct WpVersion' do
|
||||
stub_all_to_nil
|
||||
|
||||
allow(WpVersion).to receive(method).and_return(number)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ describe 'WebSite' do
|
||||
)
|
||||
end
|
||||
|
||||
describe "#new" do
|
||||
describe '#new' do
|
||||
its(:url) { is_expected.to be === 'http://example.localhost/' }
|
||||
end
|
||||
|
||||
@@ -68,14 +68,14 @@ describe 'WebSite' do
|
||||
|
||||
describe '#xml_rpc_url' do
|
||||
it 'returns the xmlrpc url' do
|
||||
expect(web_site.xml_rpc_url).to be === "http://example.localhost/xmlrpc.php"
|
||||
expect(web_site.xml_rpc_url).to be === 'http://example.localhost/xmlrpc.php'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#has_xml_rpc?' do
|
||||
it 'returns true' do
|
||||
stub_request(:get, web_site.xml_rpc_url).
|
||||
to_return(status: 200, body: "XML-RPC server accepts POST requests only")
|
||||
to_return(status: 200, body: 'XML-RPC server accepts POST requests only')
|
||||
|
||||
expect(web_site).to have_xml_rpc
|
||||
end
|
||||
|
||||
@@ -149,7 +149,7 @@ describe WpTarget do
|
||||
|
||||
after :each do
|
||||
allow(wp_target).to receive_messages(wp_content_dir: 'wp-content')
|
||||
stub_request_to_fixture(url: wp_target.debug_log_url(), fixture: @fixture)
|
||||
stub_request_to_fixture(url: wp_target.debug_log_url, fixture: @fixture)
|
||||
expect(wp_target.has_debug_log?).to be === @expected
|
||||
end
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ shared_examples 'WpTarget::WpRegistrable' do
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200, body: %{<form id="setupform" method="post" action="wp-signup.php">} }
|
||||
@stub = { status: 200, body: '<form id="setupform" method="post" action="wp-signup.php">'}
|
||||
@expected = true
|
||||
end
|
||||
end
|
||||
@@ -54,7 +54,7 @@ shared_examples 'WpTarget::WpRegistrable' do
|
||||
end
|
||||
|
||||
it 'returns true' do
|
||||
@stub = { status: 200, body: %{<form name="registerform" id="registerform" action="wp-login.php"} }
|
||||
@stub = { status: 200, body: '<form name="registerform" id="registerform" action="wp-login.php"'}
|
||||
@expected = true
|
||||
end
|
||||
|
||||
|
||||
@@ -10,11 +10,11 @@ describe 'wpscan main checks' do
|
||||
end
|
||||
|
||||
it 'should check for valid syntax' do
|
||||
result = ""
|
||||
Dir.glob("**/*.rb") do |file|
|
||||
result = ''
|
||||
Dir.glob('**/*.rb') do |file|
|
||||
res = %x{#{RbConfig.ruby} -c #{ROOT_DIR}/#{file} 2>&1}.split("\n")
|
||||
ok = res.select {|msg| msg =~ /Syntax OK/}
|
||||
result << ("####################\nSyntax error in #{file}:\n#{res.join("\n").strip()}\n") if ok.size != 1
|
||||
result << ("####################\nSyntax error in #{file}:\n#{res.join("\n").strip}\n") if ok.size != 1
|
||||
end
|
||||
fail(result) unless result.empty?
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user