diff --git a/lib/common/collections/wp_items.rb b/lib/common/collections/wp_items.rb index be09bbf4..78a5dceb 100755 --- a/lib/common/collections/wp_items.rb +++ b/lib/common/collections/wp_items.rb @@ -6,4 +6,69 @@ 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 diff --git a/lib/common/collections/wp_items/detectable.rb b/lib/common/collections/wp_items/detectable.rb index 832c27fa..ccd82bd5 100755 --- a/lib/common/collections/wp_items/detectable.rb +++ b/lib/common/collections/wp_items/detectable.rb @@ -73,11 +73,7 @@ class WpItems < Array item_class = self.item_class type = self.to_s.gsub(/Wp/, '').downcase response = Browser.get(wp_target.url) - item_options = { - wp_content_dir: wp_target.wp_content_dir, - wp_plugins_dir: wp_target.wp_plugins_dir, - vulns_file: self.vulns_file - } + item_options = self.item_options(wp_target) regex1 = %r{(?:[^=:]+)\s?(?:=|:)\s?(?:"|')[^"']+\\?/} regex2 = %r{\\?/} @@ -95,6 +91,17 @@ class WpItems < Array protected + # @param [ WpTarget ] wp_target + # + # @return [ Hash ] + def item_options(wp_target) + { + wp_content_dir: wp_target.wp_content_dir, + wp_plugins_dir: wp_target.wp_plugins_dir, + vulns_file: self.vulns_file + } + end + # The default request parameters # # @return [ Hash ] @@ -165,7 +172,7 @@ class WpItems < Array # @param [ Class ] item_class # @param [ String ] vulns_file # - # @return [ WpItem ] + # @return [ Array ] def targets_items_from_file(file, wp_target, item_class, vulns_file) targets = [] diff --git a/lib/common/collections/wp_plugins/detectable.rb b/lib/common/collections/wp_plugins/detectable.rb index 0573cea5..5c3db5ca 100644 --- a/lib/common/collections/wp_plugins/detectable.rb +++ b/lib/common/collections/wp_plugins/detectable.rb @@ -13,5 +13,59 @@ class WpPlugins < WpItems '//plugin' end + # @param [ WpTarget ] wp_target + # @param [ Hash ] options + # + # @return [ WpPlugins ] + def passive_detection(wp_target, options = {}) + detected = super(wp_target, options) + + detected += from_header(wp_target) + detected += from_content(wp_target) + + detected.uniq! { |i| i.name } + detected + end + + protected + + # X-Powered-By: W3 Total Cache/0.9.2.5 + # WP-Super-Cache: Served supercache file from PHP + # @param [ WpTarget ] wp_target + # + # @return [ WpPlugins ] + def from_header(wp_target) + headers = Browser.get(wp_target.url).headers + wp_plugins = WpPlugins.new(wp_target) + + if headers + powered_by = headers['X-Powered-By'] + wp_super_cache = headers['wp-super-cache'] + + if matches = /W3 Total Cache\/([0-9.]+)/i.match(powered_by) + wp_plugins.add('w3-total-cache', version: matches[1]) + end + + wp_plugins.add('wp-super-cache') if wp_super_cache =~ /supercache/i + end + + wp_plugins + end + + # + #