-) custom plugins directory (outside of wp-content)
-) feedback from ewanlr -) Regex fix for version detection from readme.txt due to false positives (tag-cloud-widget plugin)
This commit is contained in:
@@ -38,7 +38,7 @@ module WpLoginProtection
|
||||
|
||||
return @login_protection_plugin = WpPlugin.new(
|
||||
:name => plugin_name,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/#{plugin_name}/",
|
||||
:wp_content_dir => @wp_content_dir
|
||||
)
|
||||
@@ -68,7 +68,7 @@ module WpLoginProtection
|
||||
|
||||
def better_wp_security_url
|
||||
WpPlugin.new(:wp_content_dir => @wp_content_dir,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/better-wp-security/",
|
||||
:name => "better-wp-security"
|
||||
).get_url_without_filename
|
||||
@@ -81,7 +81,7 @@ module WpLoginProtection
|
||||
|
||||
def simple_login_lockdown_url
|
||||
WpPlugin.new(:wp_content_dir => @wp_content_dir,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/simple-login-lockdown/",
|
||||
:name => "simple-login-lockdown"
|
||||
).get_url_without_filename
|
||||
@@ -94,7 +94,7 @@ module WpLoginProtection
|
||||
|
||||
def login_security_solution_url
|
||||
WpPlugin.new(:wp_content_dir => @wp_content_dir,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/login-security-solution/",
|
||||
:name => "login-security-solution"
|
||||
).get_url_without_filename
|
||||
@@ -107,7 +107,7 @@ module WpLoginProtection
|
||||
|
||||
def limit_login_attempts_url
|
||||
WpPlugin.new(:wp_content_dir => @wp_content_dir,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/limit-login-attempts/",
|
||||
:name => "limit-login-attempts"
|
||||
).get_url_without_filename
|
||||
@@ -120,7 +120,7 @@ module WpLoginProtection
|
||||
|
||||
def bluetrait_event_viewer_url
|
||||
WpPlugin.new(:wp_content_dir => @wp_content_dir,
|
||||
:url => @uri,
|
||||
:base_url => @uri,
|
||||
:path => "/plugins/bluetrait-event-viewer/",
|
||||
:name => "bluetrait-event-viewer"
|
||||
).get_url_without_filename
|
||||
|
||||
@@ -31,12 +31,12 @@ module WpPlugins
|
||||
plugins = []
|
||||
result.each do |r|
|
||||
plugins << WpPlugin.new(
|
||||
:url => r.url,
|
||||
:base_url => r.base_url,
|
||||
:path => r.path,
|
||||
:wp_content_dir => r.wp_content_dir,
|
||||
:name => r.name,
|
||||
:type => "plugins",
|
||||
:wp_plugins_dir => r.wp_plugin_dir
|
||||
:wp_plugins_dir => r.wp_plugins_dir
|
||||
)
|
||||
end
|
||||
plugins.sort_by { |p| p.name }
|
||||
@@ -50,16 +50,16 @@ module WpPlugins
|
||||
# return array of WpPlugin
|
||||
def plugins_from_passive_detection(options)
|
||||
plugins = []
|
||||
temp = WpDetector.passive_detection(options[:url], "plugins", options[:wp_content_dir])
|
||||
temp = WpDetector.passive_detection(options[:base_url], "plugins", options[:wp_content_dir])
|
||||
|
||||
temp.each do |item|
|
||||
plugins << WpPlugin.new(
|
||||
:url => item.url,
|
||||
:base_url => item.base_url,
|
||||
:name => item.name,
|
||||
:path => item.path,
|
||||
:wp_content_dir => options[:wp_content_dir],
|
||||
:type => "plugins",
|
||||
:wp_plugins_dir => options[:wp_plugin_dir]
|
||||
:wp_plugins_dir => options[:wp_plugins_dir]
|
||||
)
|
||||
end
|
||||
plugins.sort_by { |p| p.name }
|
||||
|
||||
@@ -29,7 +29,7 @@ module WpThemes
|
||||
themes = []
|
||||
result.each do |r|
|
||||
themes << WpTheme.new(
|
||||
:url => r.url,
|
||||
:base_url => r.base_url,
|
||||
:path => r.path,
|
||||
:wp_content_dir => r.wp_content_dir,
|
||||
:name => r.name
|
||||
@@ -40,11 +40,11 @@ module WpThemes
|
||||
|
||||
def themes_from_passive_detection(options)
|
||||
themes = []
|
||||
temp = WpDetector.passive_detection(options[:url], "themes", options[:wp_content_dir])
|
||||
temp = WpDetector.passive_detection(options[:base_url], "themes", options[:wp_content_dir])
|
||||
|
||||
temp.each do |item|
|
||||
themes << WpTheme.new(
|
||||
:url => item.url,
|
||||
:base_url => item.base_url,
|
||||
:name => item.name,
|
||||
:path => item.path,
|
||||
:wp_content_dir => options[:wp_content_dir]
|
||||
|
||||
@@ -55,7 +55,7 @@ module WpTimthumbs
|
||||
scripts/timthumb.php tools/timthumb.php functions/timthumb.php
|
||||
}.each do |file|
|
||||
targets << WpItem.new(
|
||||
:url => options[:url],
|
||||
:base_url => options[:base_url],
|
||||
:path => "themes/#{theme_name}/#{file}",
|
||||
:wp_content_dir => options[:wp_content_dir],
|
||||
:name => theme_name,
|
||||
|
||||
@@ -23,7 +23,7 @@ class WpDetector
|
||||
|
||||
result = items
|
||||
if items == nil or items.length == 0
|
||||
result = passive_detection(options[:url], options[:type], options[:wp_content_dir])
|
||||
result = passive_detection(options[:base_url], options[:type], options[:wp_content_dir])
|
||||
end
|
||||
|
||||
enum_results = WpEnumerator.enumerate(options)
|
||||
@@ -61,7 +61,7 @@ class WpDetector
|
||||
|
||||
names.each do |item|
|
||||
items << WpItem.new(
|
||||
:url => url,
|
||||
:base_url => url,
|
||||
:name => item,
|
||||
:type => type,
|
||||
:path => "#{item}/",
|
||||
|
||||
@@ -24,7 +24,7 @@ class WpEnumerator
|
||||
# ==== Attributes
|
||||
#
|
||||
# * +targets+ - targets to enumerate
|
||||
# * * +:url+ - Base URL
|
||||
# * * +:base_url+ - Base URL
|
||||
# * * +:wp_content+ - wp-content directory
|
||||
# * * +:path+ - Path to plugin
|
||||
# * +type+ - "plugins" or "themes", item to enumerate
|
||||
@@ -50,7 +50,7 @@ class WpEnumerator
|
||||
enumerate_size = targets.size
|
||||
|
||||
targets.each do |target|
|
||||
url = target.get_url
|
||||
url = target.get_full_url
|
||||
|
||||
request = enum_browser.forge_request(url, { :cache_timeout => 0, :follow_location => true })
|
||||
request_count += 1
|
||||
@@ -86,7 +86,7 @@ class WpEnumerator
|
||||
file = options[:file]
|
||||
vulns_file = options[:vulns_file]
|
||||
wp_content_dir = options[:wp_content_dir]
|
||||
url = options[:url]
|
||||
url = options[:base_url]
|
||||
type = options[:type]
|
||||
plugins_dir = options[:wp_plugins_dir]
|
||||
targets_url = []
|
||||
@@ -96,7 +96,7 @@ class WpEnumerator
|
||||
File.open(file, "r") do |f|
|
||||
f.readlines.collect do |line|
|
||||
targets_url << WpItem.new(
|
||||
:url => url,
|
||||
:base_url => url,
|
||||
:path => line.strip,
|
||||
:wp_content_dir => wp_content_dir,
|
||||
:name => File.dirname(line.strip),
|
||||
@@ -118,7 +118,7 @@ class WpEnumerator
|
||||
xml.xpath(options[:vulns_xpath_2]).each do |node|
|
||||
name = node.attribute("name").text
|
||||
targets_url << WpItem.new(
|
||||
:url => url,
|
||||
:base_url => url,
|
||||
:path => name,
|
||||
:wp_content_dir => wp_content_dir,
|
||||
:name => name,
|
||||
|
||||
@@ -19,20 +19,20 @@
|
||||
require "#{WPSCAN_LIB_DIR}/vulnerable"
|
||||
|
||||
class WpItem < Vulnerable
|
||||
attr_accessor :path, :url, :wp_content_dir, :name, :vulns_file, :vulns_xpath, :wp_plugin_dir, :type
|
||||
attr_reader :base_url, :path, :wp_content_dir, :name, :vulns_file, :vulns_xpath, :wp_plugins_dir, :type
|
||||
@version = nil
|
||||
|
||||
def initialize(options)
|
||||
@type = options[:type]
|
||||
@wp_content_dir = options[:wp_content_dir] || "wp-content"
|
||||
@wp_plugin_dir = options[:wp_plugins_dir] || "plugins"
|
||||
@url = options[:url]
|
||||
@wp_content_dir = options[:wp_content_dir] ? options[:wp_content_dir].sub(/^\//, "").sub(/\/$/, "") : "wp-content"
|
||||
@wp_plugins_dir = options[:wp_plugins_dir] || "#@wp_content_dir/plugins"
|
||||
@base_url = options[:base_url]
|
||||
@path = options[:path]
|
||||
@name = options[:name] || extract_name_from_url
|
||||
@vulns_file = options[:vulns_file]
|
||||
@vulns_xpath = options[:vulns_xpath].sub(/\$name\$/, @name) unless options[:vulns_xpath] == nil
|
||||
|
||||
raise("url not set") unless @url
|
||||
raise("base_url not set") unless @base_url
|
||||
raise("path not set") unless @path
|
||||
raise("wp_content_dir not set") unless @wp_content_dir
|
||||
raise("name not set") unless @name
|
||||
@@ -42,8 +42,6 @@ class WpItem < Vulnerable
|
||||
|
||||
def get_sub_folder
|
||||
case @type
|
||||
when "plugins"
|
||||
folder = @wp_plugin_dir
|
||||
when "themes"
|
||||
folder = "themes"
|
||||
when "timthumbs"
|
||||
@@ -56,13 +54,16 @@ class WpItem < Vulnerable
|
||||
end
|
||||
|
||||
# Get the full url for this item
|
||||
def get_url
|
||||
url = @url.to_s.end_with?("/") ? @url.to_s : "#@url/"
|
||||
def get_full_url
|
||||
url = @base_url.to_s.end_with?("/") ? @base_url.to_s : "#@base_url/"
|
||||
# remove first and last /
|
||||
wp_content_dir = @wp_content_dir.sub(/^\//, "").sub(/\/$/, "")
|
||||
# remove first /
|
||||
path = @path.sub(/^\//, "")
|
||||
if type == "timthumbs"
|
||||
if type =="plugins"
|
||||
# plugins can be outside of wp-content. wp_content_dir included in wp_plugins_dir
|
||||
ret = URI.parse("#{url}#@wp_plugins_dir/#{path}")
|
||||
elsif type == "timthumbs"
|
||||
# timthumbs have folder in path variable
|
||||
ret = URI.parse("#{url}#{wp_content_dir}/#{path}")
|
||||
else
|
||||
@@ -73,7 +74,7 @@ class WpItem < Vulnerable
|
||||
|
||||
# Gets the full url for this item without filenames
|
||||
def get_url_without_filename
|
||||
location_url = get_url.to_s
|
||||
location_url = get_full_url.to_s
|
||||
valid_location_url = location_url[%r{^(https?://.*/)[^.]+\.[^/]+$}, 1]
|
||||
unless valid_location_url
|
||||
valid_location_url = add_trailing_slash(location_url)
|
||||
@@ -84,7 +85,7 @@ class WpItem < Vulnerable
|
||||
# Returns version number from readme.txt if it exists
|
||||
def version
|
||||
unless @version
|
||||
response = Browser.instance.get(get_url.merge("readme.txt").to_s)
|
||||
response = Browser.instance.get(get_full_url.merge("readme.txt").to_s)
|
||||
@version = response.body[%r{stable tag: #{WpVersion.version_pattern}}i, 1]
|
||||
end
|
||||
@version
|
||||
@@ -98,7 +99,7 @@ class WpItem < Vulnerable
|
||||
|
||||
# Extract item name from a url
|
||||
def extract_name_from_url
|
||||
get_url.to_s[%r{^(https?://.*/([^/]+)/)}i, 2]
|
||||
get_full_url.to_s[%r{^(https?://.*/([^/]+)/)}i, 2]
|
||||
end
|
||||
|
||||
# To string. Adds a version number if detected
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
# * +type+ - Type: plugins, themes
|
||||
class WpOptions
|
||||
def self.check_options(options)
|
||||
raise("url must be set") unless options[:url] != nil and options[:url].to_s.length > 0
|
||||
raise("base_url must be set") unless options[:base_url] != nil and options[:base_url].to_s.length > 0
|
||||
raise("only_vulnerable_ones must be set") unless options[:only_vulnerable_ones] != nil
|
||||
raise("file must be set") unless options[:file] != nil and options[:file].length > 0
|
||||
raise("vulns_file must be set") unless options[:vulns_file] != nil and options[:vulns_file].length > 0
|
||||
|
||||
@@ -37,6 +37,6 @@ class WpPlugin < WpItem
|
||||
end
|
||||
|
||||
def error_log_url
|
||||
get_url.merge("error_log").to_s
|
||||
get_full_url.merge("error_log").to_s
|
||||
end
|
||||
end
|
||||
|
||||
@@ -104,7 +104,7 @@ class WpTarget
|
||||
|
||||
def wp_plugins_dir
|
||||
unless @wp_plugins_dir
|
||||
@wp_plugins_dir = "plugins"
|
||||
@wp_plugins_dir = "#{wp_content_dir}/plugins"
|
||||
end
|
||||
@wp_plugins_dir
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ require "#{WPSCAN_LIB_DIR}/vulnerable"
|
||||
|
||||
class WpTheme < WpItem
|
||||
|
||||
attr_reader :name, :style_url, :version
|
||||
attr_reader :style_url, :version
|
||||
|
||||
def initialize(options = {})
|
||||
options[:vulns_file] = (options[:vulns_file] != nil and options[:vulns_file] != "") ?
|
||||
@@ -67,7 +67,7 @@ class WpTheme < WpItem
|
||||
|
||||
return new(:name => theme_name,
|
||||
:style_url => style_url,
|
||||
:url => style_url,
|
||||
:base_url => style_url,
|
||||
:path => "",
|
||||
:wp_content_dir => ""
|
||||
)
|
||||
@@ -87,7 +87,7 @@ class WpTheme < WpItem
|
||||
|
||||
return new(:name => woo_theme_name,
|
||||
:version => woo_theme_version,
|
||||
:url => matches[0],
|
||||
:base_url => matches[0],
|
||||
:path => "",
|
||||
:wp_content_dir => ""
|
||||
)
|
||||
|
||||
@@ -38,7 +38,7 @@ class WpVersion < Vulnerable
|
||||
# (find_from_meta_generator, find_from_rss_generator etc)
|
||||
def self.find(target_uri, wp_content_dir)
|
||||
options = {
|
||||
:url => target_uri,
|
||||
:base_url => target_uri,
|
||||
:wp_content_dir => wp_content_dir
|
||||
}
|
||||
self.methods.grep(/find_from_/).each do |method_to_call|
|
||||
@@ -59,14 +59,14 @@ class WpVersion < Vulnerable
|
||||
# The meta tag can be removed however it seems,
|
||||
# that it is reinstated on upgrade.
|
||||
def self.find_from_meta_generator(options)
|
||||
target_uri = options[:url]
|
||||
target_uri = options[:base_url]
|
||||
response = Browser.instance.get(target_uri.to_s, {:follow_location => true, :max_redirects => 2})
|
||||
|
||||
response.body[%r{name="generator" content="wordpress ([^"]+)"}i, 1]
|
||||
end
|
||||
|
||||
def self.find_from_rss_generator(options)
|
||||
target_uri = options[:url]
|
||||
target_uri = options[:base_url]
|
||||
response = Browser.instance.get(target_uri.merge("feed/").to_s, {:follow_location => true, :max_redirects => 2})
|
||||
|
||||
response.body[%r{<generator>http://wordpress.org/\?v=([^<]+)</generator>}i, 1]
|
||||
@@ -92,7 +92,7 @@ class WpVersion < Vulnerable
|
||||
# /!\ Warning : this method might return false positive if the file used for fingerprinting is part of a theme (they can be updated)
|
||||
#
|
||||
def self.find_from_advanced_fingerprinting(options)
|
||||
target_uri = options[:url]
|
||||
target_uri = options[:base_url]
|
||||
# needed for rpsec tests
|
||||
version_xml = options[:version_xml] || DATA_DIR + "/wp_versions.xml"
|
||||
xml = Nokogiri::XML(File.open(version_xml)) do |config|
|
||||
@@ -117,18 +117,18 @@ class WpVersion < Vulnerable
|
||||
end
|
||||
|
||||
def self.find_from_readme(options)
|
||||
target_uri = options[:url]
|
||||
target_uri = options[:base_url]
|
||||
Browser.instance.get(target_uri.merge("readme.html").to_s).body[%r{<br />\sversion #{WpVersion.version_pattern}}i, 1]
|
||||
end
|
||||
|
||||
# http://code.google.com/p/wpscan/issues/detail?id=109
|
||||
def self.find_from_sitemap_generator(options)
|
||||
target_uri = options[:url]
|
||||
target_uri = options[:base_url]
|
||||
Browser.instance.get(target_uri.merge("sitemap.xml").to_s).body[%r{generator="wordpress/#{WpVersion.version_pattern}"}, 1]
|
||||
end
|
||||
|
||||
# Used to check if the version is correct : should be numeric with at least one '.'
|
||||
# Used to check if the version is correct : must contain at least one .
|
||||
def self.version_pattern
|
||||
'(.*(?=.)(?=.*\d)(?=.*[.]).*)'
|
||||
'([^\r\n]+[\.][^\r\n]+)'
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user