This commit is contained in:
Christian Mehlmauer
2012-09-22 16:19:21 +02:00
parent b9d8e5a3e2
commit ef72568688
17 changed files with 144 additions and 142 deletions

View File

@@ -16,14 +16,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
#++ #++
LIB_DIR = File.dirname(__FILE__) LIB_DIR = File.dirname(__FILE__)
ROOT_DIR = File.expand_path(LIB_DIR + '/..') # expand_path is used to get "wpscan/" instead of "wpscan/lib/../" ROOT_DIR = File.expand_path(LIB_DIR + '/..') # expand_path is used to get "wpscan/" instead of "wpscan/lib/../"
DATA_DIR = ROOT_DIR + "/data" DATA_DIR = ROOT_DIR + "/data"
CONF_DIR = ROOT_DIR + "/conf" CONF_DIR = ROOT_DIR + "/conf"
CACHE_DIR = ROOT_DIR + "/cache" CACHE_DIR = ROOT_DIR + "/cache"
WPSCAN_LIB_DIR = LIB_DIR + "/wpscan" WPSCAN_LIB_DIR = LIB_DIR + "/wpscan"
WPSTOOLS_LIB_DIR = LIB_DIR + "/wpstools" WPSTOOLS_LIB_DIR = LIB_DIR + "/wpstools"
UPDATER_LIB_DIR = LIB_DIR + "/updater" UPDATER_LIB_DIR = LIB_DIR + "/updater"
WPSCAN_VERSION = "2.0" WPSCAN_VERSION = "2.0"
@@ -127,9 +127,9 @@ def colorize(text, color_code)
end end
def red(text) def red(text)
; colorize(text, 31) colorize(text, 31)
end end
def green(text) def green(text)
; colorize(text, 32) colorize(text, 32)
end end

View File

@@ -23,15 +23,17 @@ module WebSite
def is_wordpress? def is_wordpress?
wordpress = false wordpress = false
response = Browser.instance.get(login_url(), response = Browser.instance.get(
{:follow_location => true, :max_redirects => 2} login_url(),
{:follow_location => true, :max_redirects => 2}
) )
if response.body =~ %r{WordPress}i if response.body =~ %r{WordPress}i
wordpress = true wordpress = true
else else
response = Browser.instance.get(xmlrpc_url(), response = Browser.instance.get(
{:follow_location => true, :max_redirects => 2} xmlrpc_url(),
{:follow_location => true, :max_redirects => 2}
) )
if response.body =~ %r{XML-RPC server accepts POST requests only}i if response.body =~ %r{XML-RPC server accepts POST requests only}i

View File

@@ -37,9 +37,9 @@ module WpLoginProtection
plugin_name = symbol_to_call[LOGIN_PROTECTION_METHOD_PATTERN, 1].gsub('_', '-') plugin_name = symbol_to_call[LOGIN_PROTECTION_METHOD_PATTERN, 1].gsub('_', '-')
return @login_protection_plugin = WpPlugin.new( return @login_protection_plugin = WpPlugin.new(
:name => plugin_name, :name => plugin_name,
:url => @uri, :url => @uri,
:path => "/plugins/#{plugin_name}/", :path => "/plugins/#{plugin_name}/",
:wp_content_dir => @wp_content_dir :wp_content_dir => @wp_content_dir
) )
end end
@@ -67,10 +67,10 @@ module WpLoginProtection
end end
def better_wp_security_url def better_wp_security_url
WpPlugin.new(:wp_content_dir => @wp_content_dir, WpPlugin.new(:wp_content_dir => @wp_content_dir,
:url => @uri, :url => @uri,
:path => "/plugins/better-wp-security/", :path => "/plugins/better-wp-security/",
:name => "better-wp-security" :name => "better-wp-security"
).get_url_without_filename ).get_url_without_filename
end end
@@ -80,10 +80,10 @@ module WpLoginProtection
end end
def simple_login_lockdown_url def simple_login_lockdown_url
WpPlugin.new(:wp_content_dir => @wp_content_dir, WpPlugin.new(:wp_content_dir => @wp_content_dir,
:url => @uri, :url => @uri,
:path => "/plugins/simple-login-lockdown/", :path => "/plugins/simple-login-lockdown/",
:name => "simple-login-lockdown" :name => "simple-login-lockdown"
).get_url_without_filename ).get_url_without_filename
end end
@@ -93,10 +93,10 @@ module WpLoginProtection
end end
def login_security_solution_url def login_security_solution_url
WpPlugin.new(:wp_content_dir => @wp_content_dir, WpPlugin.new(:wp_content_dir => @wp_content_dir,
:url => @uri, :url => @uri,
:path => "/plugins/login-security-solution/", :path => "/plugins/login-security-solution/",
:name => "login-security-solution" :name => "login-security-solution"
).get_url_without_filename ).get_url_without_filename
end end
@@ -106,10 +106,10 @@ module WpLoginProtection
end end
def limit_login_attempts_url def limit_login_attempts_url
WpPlugin.new(:wp_content_dir => @wp_content_dir, WpPlugin.new(:wp_content_dir => @wp_content_dir,
:url => @uri, :url => @uri,
:path => "/plugins/limit-login-attempts/", :path => "/plugins/limit-login-attempts/",
:name => "limit-login-attempts" :name => "limit-login-attempts"
).get_url_without_filename ).get_url_without_filename
end end
@@ -119,10 +119,10 @@ module WpLoginProtection
end end
def bluetrait_event_viewer_url def bluetrait_event_viewer_url
WpPlugin.new(:wp_content_dir => @wp_content_dir, WpPlugin.new(:wp_content_dir => @wp_content_dir,
:url => @uri, :url => @uri,
:path => "/plugins/bluetrait-event-viewer/", :path => "/plugins/bluetrait-event-viewer/",
:name => "bluetrait-event-viewer" :name => "bluetrait-event-viewer"
).get_url_without_filename ).get_url_without_filename
end end
end end

View File

@@ -22,19 +22,19 @@ module WpPlugins
# #
# return array of WpPlugin # return array of WpPlugin
def plugins_from_aggressive_detection(options) def plugins_from_aggressive_detection(options)
options[:file] = options[:file] || "#{DATA_DIR}/plugins.txt" options[:file] = options[:file] || "#{DATA_DIR}/plugins.txt"
options[:vulns_file] = options[:vulns_file] || "#{DATA_DIR}/plugin_vulns.xml" options[:vulns_file] = options[:vulns_file] || "#{DATA_DIR}/plugin_vulns.xml"
options[:vulns_xpath] = "//plugin[@name='#{@name}']/vulnerability" options[:vulns_xpath] = "//plugin[@name='#{@name}']/vulnerability"
options[:vulns_xpath_2] = "//plugin" options[:vulns_xpath_2] = "//plugin"
options[:type] = "plugins" options[:type] = "plugins"
result = WpDetector.aggressive_detection(options) result = WpDetector.aggressive_detection(options)
plugins = [] plugins = []
result.each do |r| result.each do |r|
plugins << WpPlugin.new( plugins << WpPlugin.new(
:url => r[:url], :url => r[:url],
:path => r[:path], :path => r[:path],
:wp_content_dir => r[:wp_content_dir], :wp_content_dir => r[:wp_content_dir],
:name => r[:name] :name => r[:name]
) )
end end
plugins.sort_by { |p| p.name } plugins.sort_by { |p| p.name }
@@ -52,9 +52,9 @@ module WpPlugins
temp.each do |item| temp.each do |item|
plugins << WpPlugin.new( plugins << WpPlugin.new(
:url => item[:url], :url => item[:url],
:name => item[:name], :name => item[:name],
:path => item[:path], :path => item[:path],
:wp_content_dir => options[:wp_content_dir] :wp_content_dir => options[:wp_content_dir]
) )
end end

View File

@@ -19,19 +19,19 @@
module WpThemes module WpThemes
def themes_from_aggressive_detection(options) def themes_from_aggressive_detection(options)
options[:file] = options[:file] || "#{DATA_DIR}/themes.txt" options[:file] = options[:file] || "#{DATA_DIR}/themes.txt"
options[:vulns_file] = options[:vulns_file] || "#{DATA_DIR}/wp_theme_vulns.xml" options[:vulns_file] = options[:vulns_file] || "#{DATA_DIR}/wp_theme_vulns.xml"
options[:vulns_xpath] = "//theme[@name='#{@name}']/vulnerability" options[:vulns_xpath] = "//theme[@name='#{@name}']/vulnerability"
options[:vulns_xpath_2] = "//theme" options[:vulns_xpath_2] = "//theme"
options[:type] = "themes" options[:type] = "themes"
result = WpDetector.aggressive_detection(options) result = WpDetector.aggressive_detection(options)
themes = [] themes = []
result.each do |r| result.each do |r|
themes << WpTheme.new( themes << WpTheme.new(
:url => r[:url], :url => r[:url],
:path => r[:path], :path => r[:path],
:wp_content_dir => r[:wp_content_dir], :wp_content_dir => r[:wp_content_dir],
:name => r[:name] :name => r[:name]
) )
end end
themes.sort_by { |t| t.name } themes.sort_by { |t| t.name }
@@ -43,9 +43,9 @@ module WpThemes
temp.each do |item| temp.each do |item|
themes << WpTheme.new( themes << WpTheme.new(
:url => item[:url], :url => item[:url],
:name => item[:name], :name => item[:name],
:path => item[:path], :path => item[:path],
:wp_content_dir => options[:wp_content_dir] :wp_content_dir => options[:wp_content_dir]
) )
end end

View File

@@ -27,12 +27,12 @@ module WpTimthumbs
def timthumbs(theme_name = nil, options = {}) def timthumbs(theme_name = nil, options = {})
if @wp_timthumbs.nil? if @wp_timthumbs.nil?
options[:type] = "timthumbs" options[:type] = "timthumbs"
options[:only_vulnerable_ones] = false options[:only_vulnerable_ones] = false
options[:file] = options[:file] || DATA_DIR + "/timthumbs.txt" options[:file] = options[:file] || DATA_DIR + "/timthumbs.txt"
options[:vulns_file] = "xxx" options[:vulns_file] = "xxx"
options[:vulns_xpath] = "xxx" options[:vulns_xpath] = "xxx"
options[:vulns_xpath_2] = "xxx" options[:vulns_xpath_2] = "xxx"
WpOptions.check_options(options) WpOptions.check_options(options)
if theme_name == nil if theme_name == nil
@@ -55,10 +55,10 @@ module WpTimthumbs
scripts/timthumb.php tools/timthumb.php functions/timthumb.php scripts/timthumb.php tools/timthumb.php functions/timthumb.php
}.each do |file| }.each do |file|
targets << { targets << {
:url => options[:url], :url => options[:url],
:path => "themes/#{theme_name}/#{file}", :path => "themes/#{theme_name}/#{file}",
:wp_content_dir => options[:wp_content_dir], :wp_content_dir => options[:wp_content_dir],
:name => options[:name] :name => options[:name]
} }
end end
targets targets

View File

@@ -24,17 +24,17 @@ class WpItem < Vulnerable
def initialize(options = {}) def initialize(options = {})
@wp_content_dir = options[:wp_content_dir] || "wp-content" @wp_content_dir = options[:wp_content_dir] || "wp-content"
@url = options[:url] @url = options[:url]
@path = options[:path] @path = options[:path]
@name = options[:name] || extract_name_from_url @name = options[:name] || extract_name_from_url
@vulns_xml = options[:vulns_xml] @vulns_xml = options[:vulns_xml]
@vulns_xpath = options[:vulns_xpath].sub(/\$name\$/, @name) @vulns_xpath = options[:vulns_xpath].sub(/\$name\$/, @name)
raise("url not set") unless @url raise("url not set") unless @url
raise("path not set") unless @path raise("path not set") unless @path
raise("wp_content_dir not set") unless @wp_content_dir raise("wp_content_dir not set") unless @wp_content_dir
raise("name not set") unless @name raise("name not set") unless @name
raise("vulns_xml not set") unless @vulns_xml raise("vulns_xml not set") unless @vulns_xml
end end
# Get the full url for this item # Get the full url for this item

View File

@@ -32,16 +32,16 @@
# * +type+ - Type: plugins, themes # * +type+ - Type: plugins, themes
class WpOptions class WpOptions
def self.check_options(options) def self.check_options(options)
raise("url must be set") unless options[:url] != nil and options[:url].to_s.length > 0 raise("url must be set") unless options[:url] != nil and options[:url].to_s.length > 0
raise("only_vulnerable_ones must be set") unless options[:only_vulnerable_ones] != nil 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("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 raise("vulns_file must be set") unless options[:vulns_file] != nil and options[:vulns_file].length > 0
raise("vulns_xpath must be set") unless options[:vulns_xpath] != nil and options[:vulns_xpath].length > 0 raise("vulns_xpath must be set") unless options[:vulns_xpath] != nil and options[:vulns_xpath].length > 0
raise("vulns_xpath_2 must be set") unless options[:vulns_xpath_2] != nil and options[:vulns_xpath_2].length > 0 raise("vulns_xpath_2 must be set") unless options[:vulns_xpath_2] != nil and options[:vulns_xpath_2].length > 0
raise("wp_content_dir must be set") unless options[:wp_content_dir] != nil and options[:wp_content_dir].length > 0 raise("wp_content_dir must be set") unless options[:wp_content_dir] != nil and options[:wp_content_dir].length > 0
raise("show_progress_bar must be set") unless options[:show_progress_bar] != nil raise("show_progress_bar must be set") unless options[:show_progress_bar] != nil
raise("error_404_hash must be set") unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0 raise("error_404_hash must be set") unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0
raise("type must be set") unless options[:type] != nil and options[:type].length > 0 raise("type must be set") unless options[:type] != nil and options[:type].length > 0
unless options[:type] =~ /plugins/i or options[:type] =~ /themes/i or options[:type] =~ /timthumbs/i unless options[:type] =~ /plugins/i or options[:type] =~ /themes/i or options[:type] =~ /timthumbs/i
raise("Unknown type #{options[:type]}") raise("Unknown type #{options[:type]}")

View File

@@ -18,10 +18,10 @@
class WpPlugin < WpItem class WpPlugin < WpItem
def initialize(options = {}) def initialize(options = {})
options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/plugin_vulns.xml' options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/plugin_vulns.xml'
options[:vulns_xpath] = "//plugin[@name='$name$']/vulnerability" options[:vulns_xpath] = "//plugin[@name='$name$']/vulnerability"
options[:vulns_xpath_2] = "//plugin" options[:vulns_xpath_2] = "//plugin"
options[:type] = "plugins" options[:type] = "plugins"
super(options) super(options)
end end

View File

@@ -34,8 +34,8 @@ class WpTarget
attr_reader :uri, :verbose attr_reader :uri, :verbose
def initialize(target_url, options = {}) def initialize(target_url, options = {})
@uri = URI.parse(add_trailing_slash(add_http_protocol(target_url))) @uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
@verbose = options[:verbose] @verbose = options[:verbose]
@wp_content_dir = options[:wp_content_dir] @wp_content_dir = options[:wp_content_dir]
@wp_plugins_dir = options[:wp_plugins_dir] @wp_plugins_dir = options[:wp_plugins_dir]

View File

@@ -23,10 +23,10 @@ class WpTheme < WpItem
attr_reader :name, :style_url, :version attr_reader :name, :style_url, :version
def initialize(options = {}) def initialize(options = {})
options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/wp_theme_vulns.xml' options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/wp_theme_vulns.xml'
options[:vulns_xpath] = "//theme[@name='$name$']/vulnerability" options[:vulns_xpath] = "//theme[@name='$name$']/vulnerability"
@version = options[:version] @version = options[:version]
@style_url = options[:style_url] @style_url = options[:style_url]
super(options) super(options)
end end
@@ -63,11 +63,11 @@ class WpTheme < WpItem
style_url = matches[0] style_url = matches[0]
theme_name = matches[1] theme_name = matches[1]
return new(:name => theme_name, return new(:name => theme_name,
:style_url => style_url, :style_url => style_url,
:url => style_url, :url => style_url,
:path => "", :path => "",
:wp_content_dir => "" :wp_content_dir => ""
) )
end end
end end
@@ -83,11 +83,11 @@ class WpTheme < WpItem
woo_theme_version = matches[2] woo_theme_version = matches[2]
woo_framework_version = matches[3] # Not used at this time woo_framework_version = matches[3] # Not used at this time
return new(:name => woo_theme_name, return new(:name => woo_theme_name,
:version => woo_theme_version, :version => woo_theme_version,
:url => matches[0], :url => matches[0],
:path => "", :path => "",
:wp_content_dir => "" :wp_content_dir => ""
) )
end end
end end

View File

@@ -20,8 +20,8 @@ class WpUser
attr_accessor :name, :id, :nickname attr_accessor :name, :id, :nickname
def initialize(name, id, nickname) def initialize(name, id, nickname)
@name = name ? name : "empty" @name = name ? name : "empty"
@id = id ? id : "empty" @id = id ? id : "empty"
@nickname = nickname ? nickname : "empty" @nickname = nickname ? nickname : "empty"
end end

View File

@@ -23,10 +23,10 @@ class WpVersion < Vulnerable
attr_reader :number, :discovery_method attr_reader :number, :discovery_method
def initialize(number, options = {}) def initialize(number, options = {})
@number = number @number = number
@discovery_method = options[:discovery_method] @discovery_method = options[:discovery_method]
@vulns_xml = options[:vulns_xml] || DATA_DIR + '/wp_vulns.xml' @vulns_xml = options[:vulns_xml] || DATA_DIR + '/wp_vulns.xml'
@vulns_xpath = "//wordpress[@version='#{@number}']/vulnerability" @vulns_xpath = "//wordpress[@version='#{@number}']/vulnerability"
end end
# Will use all method self.find_from_* to try to detect the version # Will use all method self.find_from_* to try to detect the version
@@ -38,7 +38,7 @@ class WpVersion < Vulnerable
# (find_from_meta_generator, find_from_rss_generator etc) # (find_from_meta_generator, find_from_rss_generator etc)
def self.find(target_uri, wp_content_dir) def self.find(target_uri, wp_content_dir)
options = { options = {
:url => target_uri, :url => target_uri,
:wp_content_dir => wp_content_dir :wp_content_dir => wp_content_dir
} }
self.methods.grep(/find_from_/).each do |method_to_call| self.methods.grep(/find_from_/).each do |method_to_call|

View File

@@ -20,8 +20,8 @@ class WpVulnerability
attr_accessor :title, :reference, :type attr_accessor :title, :reference, :type
def initialize(title, reference, type) def initialize(title, reference, type)
@title = title @title = title
@reference = reference @reference = reference
@type = type @type = type
end end
end end

View File

@@ -26,23 +26,23 @@ class Generate_List
# type = themes | plugins # type = themes | plugins
def initialize(type, verbose) def initialize(type, verbose)
if type =~ /plugins/i if type =~ /plugins/i
@type = "plugin" @type = "plugin"
@svn_url = 'http://plugins.svn.wordpress.org/' @svn_url = 'http://plugins.svn.wordpress.org/'
@file_name = DATA_DIR + '/plugins.txt' @file_name = DATA_DIR + '/plugins.txt'
@popular_url = 'http://wordpress.org/extend/plugins/browse/popular/' @popular_url = 'http://wordpress.org/extend/plugins/browse/popular/'
@popular_regex = %r{<h3><a href="http://wordpress.org/extend/plugins/(.+)/">.+</a></h3>}i @popular_regex = %r{<h3><a href="http://wordpress.org/extend/plugins/(.+)/">.+</a></h3>}i
elsif type =~ /themes/i elsif type =~ /themes/i
@type = "theme" @type = "theme"
@svn_url = 'http://themes.svn.wordpress.org/' @svn_url = 'http://themes.svn.wordpress.org/'
@file_name = DATA_DIR + '/themes.txt' @file_name = DATA_DIR + '/themes.txt'
@popular_url = 'http://wordpress.org/extend/themes/browse/popular/' @popular_url = 'http://wordpress.org/extend/themes/browse/popular/'
@popular_regex = %r{<h3><a href="http://wordpress.org/extend/themes/(.+)">.+</a></h3>}i @popular_regex = %r{<h3><a href="http://wordpress.org/extend/themes/(.+)">.+</a></h3>}i
else else
raise "Type #{type} not defined" raise "Type #{type} not defined"
end end
@verbose = verbose @verbose = verbose
@browser = Browser.instance @browser = Browser.instance
@hydra = @browser.hydra @hydra = @browser.hydra
end end
def generate_full_list def generate_full_list

View File

@@ -24,11 +24,11 @@ class Svn_Parser
attr_accessor :verbose, :svn_root, :keep_empty_dirs attr_accessor :verbose, :svn_root, :keep_empty_dirs
def initialize(svn_root, verbose, keep_empty_dirs = false) def initialize(svn_root, verbose, keep_empty_dirs = false)
@svn_root = svn_root @svn_root = svn_root
@verbose = verbose @verbose = verbose
@keep_empty_dirs = keep_empty_dirs @keep_empty_dirs = keep_empty_dirs
@svn_browser = Browser.instance @svn_browser = Browser.instance
@svn_hydra = @svn_browser.hydra @svn_hydra = @svn_browser.hydra
end end
def parse(dirs=nil) def parse(dirs=nil)

View File

@@ -181,11 +181,11 @@ begin
puts puts
options = {} options = {}
options[:url] = wp_target.uri options[:url] = wp_target.uri
options[:only_vulnerable_ones] = wpscan_options.enumerate_only_vulnerable_plugins || false options[:only_vulnerable_ones] = wpscan_options.enumerate_only_vulnerable_plugins || false
options[:show_progress_bar] = true options[:show_progress_bar] = true
options[:wp_content_dir] = wp_target.wp_content_dir options[:wp_content_dir] = wp_target.wp_content_dir
options[:error_404_hash] = wp_target.error_404_hash options[:error_404_hash] = wp_target.error_404_hash
plugins = wp_target.plugins_from_aggressive_detection(options) plugins = wp_target.plugins_from_aggressive_detection(options)
unless plugins.empty? unless plugins.empty?
@@ -235,11 +235,11 @@ begin
puts puts
options = {} options = {}
options[:url] = wp_target.uri options[:url] = wp_target.uri
options[:only_vulnerable_ones] = wpscan_options.enumerate_only_vulnerable_themes || false options[:only_vulnerable_ones] = wpscan_options.enumerate_only_vulnerable_themes || false
options[:show_progress_bar] = true options[:show_progress_bar] = true
options[:wp_content_dir] = wp_target.wp_content_dir options[:wp_content_dir] = wp_target.wp_content_dir
options[:error_404_hash] = wp_target.error_404_hash options[:error_404_hash] = wp_target.error_404_hash
themes = wp_target.themes_from_aggressive_detection(options) themes = wp_target.themes_from_aggressive_detection(options)
unless themes.empty? unless themes.empty?
@@ -281,10 +281,10 @@ begin
puts puts
options = {} options = {}
options[:url] = wp_target.uri options[:url] = wp_target.uri
options[:show_progress_bar] = true options[:show_progress_bar] = true
options[:wp_content_dir] = wp_target.wp_content_dir options[:wp_content_dir] = wp_target.wp_content_dir
options[:error_404_hash] = wp_target.error_404_hash options[:error_404_hash] = wp_target.error_404_hash
theme_name = wp_theme ? wp_theme.name : nil theme_name = wp_theme ? wp_theme.name : nil
if wp_target.has_timthumbs?(theme_name, options) if wp_target.has_timthumbs?(theme_name, options)