New enumeration system
This commit is contained in:
8
lib/common/collections/vulnerabilities.rb
Normal file
8
lib/common/collections/vulnerabilities.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/vulnerabilities/output'
|
||||
|
||||
class Vulnerabilities < Array
|
||||
include Vulnerabilities::Output
|
||||
|
||||
end
|
||||
13
lib/common/collections/vulnerabilities/output.rb
Normal file
13
lib/common/collections/vulnerabilities/output.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class Vulnerabilities < Array
|
||||
module Output
|
||||
|
||||
def output
|
||||
self.each do |v|
|
||||
v.output
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
10
lib/common/collections/wp_items.rb
Executable file
10
lib/common/collections/wp_items.rb
Executable file
@@ -0,0 +1,10 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_items/detectable'
|
||||
require 'common/collections/wp_items/output'
|
||||
|
||||
class WpItems < Array
|
||||
extend WpItems::Detectable
|
||||
include WpItems::Output
|
||||
|
||||
end
|
||||
154
lib/common/collections/wp_items/detectable.rb
Executable file
154
lib/common/collections/wp_items/detectable.rb
Executable file
@@ -0,0 +1,154 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpItems < Array
|
||||
|
||||
module Detectable
|
||||
|
||||
# The default request parameters
|
||||
def request_params; { cache_ttl: 0, followlocation: true } end
|
||||
|
||||
# options:
|
||||
# option name - default - description
|
||||
# show_progress - false - Output a progress bar
|
||||
# only_vulnerable - nil - Only check for vulnerable items
|
||||
# exclude_content - nil -
|
||||
def aggressive_detection(wp_target, options = {})
|
||||
queue_count = 0
|
||||
request_count = 0
|
||||
browser = Browser.instance
|
||||
hydra = browser.hydra
|
||||
targets = targets_items(wp_target, options)
|
||||
targets_size = targets.size
|
||||
show_progression = options[:show_progression] || false
|
||||
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
|
||||
}
|
||||
|
||||
# If we only want the vulnerable ones, the passive detection is ignored
|
||||
# Otherwise, a passive detection is performed, and results will be merged
|
||||
results = options[:only_vulnerable] ? new : passive_detection(wp_target, options)
|
||||
|
||||
targets.each do |target_item|
|
||||
request = browser.forge_request(target_item.url, request_params)
|
||||
request_count += 1
|
||||
|
||||
request.on_complete do |response|
|
||||
|
||||
print "\rChecking for #{targets_size} total ... #{(request_count * 100) / targets_size}% complete." if show_progression
|
||||
|
||||
if target_item.exists?(exist_options, response)
|
||||
if !results.include?(target_item)
|
||||
results << target_item
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hydra.queue(request)
|
||||
queue_count += 1
|
||||
|
||||
if queue_count == browser.max_threads
|
||||
hydra.run
|
||||
queue_count = 0
|
||||
end
|
||||
end
|
||||
|
||||
hydra.run
|
||||
results.sort!
|
||||
results # can't just return results.sort because the #sort returns an array, and we want a WpItems
|
||||
end
|
||||
|
||||
def passive_detection(wp_target, options = {})
|
||||
results = new
|
||||
item_class = self.item_class
|
||||
type = self.to_s.gsub(/Wp/, '').downcase
|
||||
response = Browser.instance.get(wp_target.url)
|
||||
item_options = {
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir,
|
||||
vulns_file: vulns_file
|
||||
}
|
||||
|
||||
regex1 = %r{(?:[^=:]+)\s?(?:=|:)\s?(?:"|')[^"']+\\?/}
|
||||
regex2 = %r{\\?/}
|
||||
regex3 = %r{\\?/([^/\\"']+)\\?(?:/|"|')}
|
||||
|
||||
names = response.body.scan(/#{regex1}#{Regexp.escape(wp_target.wp_content_dir)}#{regex2}#{Regexp.escape(type)}#{regex3}/i)
|
||||
|
||||
names.flatten.uniq.each do |name|
|
||||
results << item_class.new(wp_target.uri, item_options.merge(name: name))
|
||||
end
|
||||
|
||||
results.sort!
|
||||
results
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
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
|
||||
|
||||
def vulnerable_targets_items(wp_target, item_class, vulns_file)
|
||||
targets = []
|
||||
xml = xml(vulns_file)
|
||||
|
||||
xml.xpath(item_xpath).each do |node|
|
||||
targets << create_item(
|
||||
item_class,
|
||||
node.attribute('name').text,
|
||||
wp_target,
|
||||
vulns_file
|
||||
)
|
||||
end
|
||||
targets
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
11
lib/common/collections/wp_items/output.rb
Normal file
11
lib/common/collections/wp_items/output.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpItems < Array
|
||||
module Output
|
||||
|
||||
def output
|
||||
self.each { |item| item.output }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
8
lib/common/collections/wp_plugins.rb
Executable file
8
lib/common/collections/wp_plugins.rb
Executable file
@@ -0,0 +1,8 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_plugins/detectable'
|
||||
|
||||
class WpPlugins < WpItems
|
||||
extend WpPlugins::Detectable
|
||||
|
||||
end
|
||||
18
lib/common/collections/wp_plugins/detectable.rb
Normal file
18
lib/common/collections/wp_plugins/detectable.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpPlugins < WpItems
|
||||
module Detectable
|
||||
|
||||
def vulns_file
|
||||
unless @vulns_file
|
||||
@vulns_file = PLUGINS_VULNS_FILE
|
||||
end
|
||||
@vulns_file
|
||||
end
|
||||
|
||||
def item_xpath
|
||||
'//plugin'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
8
lib/common/collections/wp_themes.rb
Executable file
8
lib/common/collections/wp_themes.rb
Executable file
@@ -0,0 +1,8 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_themes/detectable'
|
||||
|
||||
class WpThemes < WpItems
|
||||
extend WpThemes::Detectable
|
||||
|
||||
end
|
||||
18
lib/common/collections/wp_themes/detectable.rb
Normal file
18
lib/common/collections/wp_themes/detectable.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpThemes < WpItems
|
||||
module Detectable
|
||||
|
||||
def vulns_file
|
||||
unless @vulns_file
|
||||
@vulns_file = THEMES_VULNS_FILE
|
||||
end
|
||||
@vulns_file
|
||||
end
|
||||
|
||||
def item_xpath
|
||||
'//theme'
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
8
lib/common/collections/wp_timthumbs.rb
Executable file
8
lib/common/collections/wp_timthumbs.rb
Executable file
@@ -0,0 +1,8 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_timthumbs/detectable'
|
||||
|
||||
class WpTimthumbs < WpItems
|
||||
extend WpTimthumbs::Detectable
|
||||
|
||||
end
|
||||
56
lib/common/collections/wp_timthumbs/detectable.rb
Normal file
56
lib/common/collections/wp_timthumbs/detectable.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpTimthumbs < WpItems
|
||||
module Detectable
|
||||
|
||||
# No passive detection
|
||||
# @return [ WpTimthumbs ]
|
||||
def passive_detection(wp_target, topns = {})
|
||||
new
|
||||
end
|
||||
|
||||
def targets_items(wp_target, options = {})
|
||||
unless options[:file]
|
||||
raise 'A file must be supplied'
|
||||
end
|
||||
|
||||
targets = options[:theme_name] ? theme_timthumbs(options[:theme_name], wp_target) : []
|
||||
|
||||
File.open(options[:file], 'r') do |f|
|
||||
f.readlines.collect do |path|
|
||||
targets << create_item(wp_target, path.strip)
|
||||
end
|
||||
end
|
||||
|
||||
targets.uniq { |i| i.url }
|
||||
end
|
||||
|
||||
# @return [ WpTimthumb Array ]
|
||||
def theme_timthumbs(theme_name, wp_target)
|
||||
targets = []
|
||||
wp_timthumb = create_item(wp_target)
|
||||
|
||||
%w{
|
||||
timthumb.php lib/timthumb.php inc/timthumb.php includes/timthumb.php
|
||||
scripts/timthumb.php tools/timthumb.php functions/timthumb.php
|
||||
}.each do |path|
|
||||
wp_timthumb.path = "$wp-content$/themes/#{theme_name}/#{path}"
|
||||
|
||||
targets << wp_timthumb.dup
|
||||
end
|
||||
targets
|
||||
end
|
||||
|
||||
# @return [ WpTimthumb ]
|
||||
def create_item(wp_target, path = nil)
|
||||
options = {
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir
|
||||
}
|
||||
|
||||
options.merge!(path: path) if path
|
||||
|
||||
WpTimthumb.new(wp_target.uri, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
10
lib/common/collections/wp_users.rb
Executable file
10
lib/common/collections/wp_users.rb
Executable file
@@ -0,0 +1,10 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require 'common/collections/wp_users/detectable'
|
||||
require 'common/collections/wp_users/output'
|
||||
|
||||
class WpUsers < WpItems
|
||||
extend WpUsers::Detectable
|
||||
include WpUsers::Output
|
||||
|
||||
end
|
||||
27
lib/common/collections/wp_users/detectable.rb
Executable file
27
lib/common/collections/wp_users/detectable.rb
Executable file
@@ -0,0 +1,27 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpUsers < WpItems
|
||||
module Detectable
|
||||
|
||||
def request_params; {} end
|
||||
|
||||
# options:
|
||||
# :range - default 1..10
|
||||
def targets_items(wp_target, options = {})
|
||||
range = options[:range] || (1..10)
|
||||
targets = []
|
||||
|
||||
range.each do |user_id|
|
||||
targets << WpUser.new(wp_target.uri, id: user_id)
|
||||
end
|
||||
targets
|
||||
end
|
||||
|
||||
# No passive detection
|
||||
# @return [ WpUsers ]
|
||||
def passive_detection(wp_target, options = {})
|
||||
new
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
29
lib/common/collections/wp_users/output.rb
Normal file
29
lib/common/collections/wp_users/output.rb
Normal file
@@ -0,0 +1,29 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
class WpUsers < WpItems
|
||||
module Output
|
||||
|
||||
# TODO : create a generic method to output tabs
|
||||
def output(left_margin = '')
|
||||
max_id_length = self.sort { |a, b| a.id.to_s.length <=> b.id.to_s.length }.last.id.to_s.length
|
||||
max_login_length = self.sort { |a, b| a.login.length <=> b.login.length }.last.login.length
|
||||
max_display_name_length = self.sort { |a, b| a.display_name.length <=> b.display_name.length }.last.display_name.length
|
||||
|
||||
inner_space = 2
|
||||
id_length = (max_id_length + inner_space * 2) /2 *2
|
||||
login_length = max_login_length + inner_space * 2
|
||||
display_name_length = max_display_name_length + inner_space * 2
|
||||
|
||||
puts left_margin + '+' * (id_length + login_length + display_name_length + 4)
|
||||
puts left_margin + '|' + 'id'.center(id_length) + '|' + 'login'.center(login_length) + '|' + 'display name'.center(display_name_length) + '|'
|
||||
puts left_margin + '|' + '+' * (id_length + login_length + display_name_length + 2) + '|'
|
||||
|
||||
self.each do |u|
|
||||
puts left_margin + '|' + u.id.to_s.center(id_length) + '|' + u.login.center(login_length) + '|' + u.display_name.center(display_name_length) + '|'
|
||||
end
|
||||
|
||||
puts left_margin + '+' * (id_length + login_length + display_name_length + 4)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user