WPSTools updated to respect ruby standards according to rubocop

This commit is contained in:
erwanlr
2013-01-24 17:04:45 +01:00
parent ce9f073f26
commit b0dd9ba989
18 changed files with 261 additions and 231 deletions

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -45,7 +46,11 @@ class Browser
override_config_with_options(options) override_config_with_options(options)
end end
@hydra = Typhoeus::Hydra.new(:max_concurrency => @max_threads, :timeout => @request_timeout) @hydra = Typhoeus::Hydra.new(
max_concurrency: @max_threads,
timeout: @request_timeout
)
# TODO : add an option for the cache dir instead of using a constant # TODO : add an option for the cache dir instead of using a constant
@cache = CacheFileStore.new(CACHE_DIR + '/browser') @cache = CacheFileStore.new(CACHE_DIR + '/browser')
@@ -69,12 +74,13 @@ class Browser
end end
def user_agent_mode=(ua_mode) def user_agent_mode=(ua_mode)
ua_mode ||= "static" ua_mode ||= 'static'
if USER_AGENT_MODES.include?(ua_mode) if USER_AGENT_MODES.include?(ua_mode)
@user_agent_mode = ua_mode @user_agent_mode = ua_mode
# For semi-static user agent mode, the user agent has to be nil the first time (it will be set with the getter) # For semi-static user agent mode, the user agent has to
@user_agent = nil if ua_mode === "semi-static" # be nil the first time (it will be set with the getter)
@user_agent = nil if ua_mode === 'semi-static'
else else
raise "Unknow user agent mode : '#{ua_mode}'" raise "Unknow user agent mode : '#{ua_mode}'"
end end
@@ -83,11 +89,11 @@ class Browser
# return the user agent, according to the user_agent_mode # return the user agent, according to the user_agent_mode
def user_agent def user_agent
case @user_agent_mode case @user_agent_mode
when "semi-static" when 'semi-static'
unless @user_agent unless @user_agent
@user_agent = @available_user_agents.sample @user_agent = @available_user_agents.sample
end end
when "random" when 'random'
@user_agent = @available_user_agents.sample @user_agent = @available_user_agents.sample
end end
@user_agent @user_agent
@@ -109,21 +115,25 @@ class Browser
@proxy_auth = auth @proxy_auth = auth
elsif auth.is_a?(String) elsif auth.is_a?(String)
if matches = %r{([^:]+):(.*)}.match(auth) if matches = %r{([^:]+):(.*)}.match(auth)
@proxy_auth = {:proxy_username => matches[1], :proxy_password => matches[2]} @proxy_auth = {
proxy_username: matches[1],
proxy_password: matches[2]
}
else else
raise_invalid_proxy_format() raise_invalid_proxy_auth_format()
end end
else else
raise_invalid_proxy_format() raise_invalid_proxy_auth_format()
end end
end end
end end
def raise_invalid_proxy_format def raise_invalid_proxy_auth_format
raise "Invalid proxy auth format, expected username:password or {:proxy_username => username, :proxy_password => password}" raise 'Invalid proxy auth format, expected username:password or {proxy_username: username, proxy_password: password}'
end end
# TODO reload hydra (if the .load_config is called on a browser object, hydra will not have the new @max_threads and @request_timeout) # TODO reload hydra (if the .load_config is called on a browser object,
# hydra will not have the new @max_threads and @request_timeout)
def load_config(config_file = nil) def load_config(config_file = nil)
@config_file = config_file || @config_file @config_file = config_file || @config_file
@@ -146,7 +156,9 @@ class Browser
end end
@hydra.cache_getter do |request| @hydra.cache_getter do |request|
@cache.read_entry(Browser.generate_cache_key_from_request(request)) rescue nil @cache.read_entry(
Browser.generate_cache_key_from_request(request)
) rescue nil
end end
end end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -18,7 +19,8 @@
# #
# => @todo take consideration of the cache_timeout : # => @todo take consideration of the cache_timeout :
# -> create 2 files per key : one for the data storage (key.store ?) and the other for the cache timeout (key.expiration, key.timeout ?) # -> create 2 files per key : one for the data storage (key.store ?)
# and the other for the cache timeout (key.expiration, key.timeout ?)
# or 1 file for all timeouts ? # or 1 file for all timeouts ?
# -> 2 dirs : 1 for storage, the other for cache_timeout ? # -> 2 dirs : 1 for storage, the other for cache_timeout ?
# #
@@ -28,14 +30,16 @@ require 'yaml'
class CacheFileStore class CacheFileStore
attr_reader :storage_path, :serializer attr_reader :storage_path, :serializer
# The serializer must have the 2 methods .load and .dump (Marshal and YAML have them) # The serializer must have the 2 methods .load and .dump
# (Marshal and YAML have them)
# YAML is Human Readable, contrary to Marshal which store in a binary format # YAML is Human Readable, contrary to Marshal which store in a binary format
# Marshal does not need any "require" # Marshal does not need any "require"
def initialize(storage_path, serializer = Marshal) def initialize(storage_path, serializer = Marshal)
@storage_path = File.expand_path(storage_path) @storage_path = File.expand_path(storage_path)
@serializer = serializer @serializer = serializer
# File.directory? for ruby <= 1.9 otherwise, it makes more sense to do Dir.exist? :/ # File.directory? for ruby <= 1.9 otherwise,
# it makes more sense to do Dir.exist? :/
unless File.directory?(@storage_path) unless File.directory?(@storage_path)
Dir.mkdir(@storage_path) Dir.mkdir(@storage_path)
end end

View File

@@ -1,3 +1,5 @@
# encoding: UTF-8
#
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
# #

View File

@@ -1,3 +1,5 @@
# encoding: UTF-8
#
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
# #

View File

@@ -1,3 +1,5 @@
# encoding: UTF-8
#
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
# #

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -18,39 +19,39 @@
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'
COMMON_LIB_DIR = LIB_DIR + "/common" COMMON_LIB_DIR = LIB_DIR + '/common'
LOG_FILE = ROOT_DIR + "/log.txt" LOG_FILE = ROOT_DIR + '/log.txt'
# Plugins directories # Plugins directories
COMON_PLUGINS_DIR = COMMON_LIB_DIR + "/plugins" COMON_PLUGINS_DIR = COMMON_LIB_DIR + '/plugins'
WPSCAN_PLUGINS_DIR = WPSCAN_LIB_DIR + "/plugins" WPSCAN_PLUGINS_DIR = WPSCAN_LIB_DIR + '/plugins'
WPSTOOLS_PLUGINS_DIR = WPSTOOLS_LIB_DIR + "/plugins" WPSTOOLS_PLUGINS_DIR = WPSTOOLS_LIB_DIR + '/plugins'
# Data files # Data files
PLUGINS_FILE = DATA_DIR + "/plugins.txt" PLUGINS_FILE = DATA_DIR + '/plugins.txt'
PLUGINS_FULL_FILE = DATA_DIR + "/plugins_full.txt" PLUGINS_FULL_FILE = DATA_DIR + '/plugins_full.txt'
PLUGINS_VULNS_FILE = DATA_DIR + "/plugin_vulns.xml" PLUGINS_VULNS_FILE = DATA_DIR + '/plugin_vulns.xml'
THEMES_FILE = DATA_DIR + "/themes.txt" THEMES_FILE = DATA_DIR + '/themes.txt'
THEMES_FULL_FILE = DATA_DIR + "/themes_full.txt" THEMES_FULL_FILE = DATA_DIR + '/themes_full.txt'
THEMES_VULNS_FILE = DATA_DIR + "/theme_vulns.xml" THEMES_VULNS_FILE = DATA_DIR + '/theme_vulns.xml'
WP_VULNS_FILE = DATA_DIR + "/wp_vulns.xml" WP_VULNS_FILE = DATA_DIR + '/wp_vulns.xml'
WP_VERSIONS_FILE = DATA_DIR + "/wp_versions.xml" WP_VERSIONS_FILE = DATA_DIR + '/wp_versions.xml'
LOCAL_FILES_FILE = DATA_DIR + "/local_vulnerable_files.xml" LOCAL_FILES_FILE = DATA_DIR + '/local_vulnerable_files.xml'
VULNS_XSD = DATA_DIR + "/vuln.xsd" VULNS_XSD = DATA_DIR + '/vuln.xsd'
WP_VERSIONS_XSD = DATA_DIR + "/wp_versions.xsd" WP_VERSIONS_XSD = DATA_DIR + '/wp_versions.xsd'
LOCAL_FILES_XSD = DATA_DIR + "/local_vulnerable_files.xsd" LOCAL_FILES_XSD = DATA_DIR + '/local_vulnerable_files.xsd'
WPSCAN_VERSION = "2.0" WPSCAN_VERSION = '2.0'
require "#{LIB_DIR}/environment" require "#{LIB_DIR}/environment"
# TODO : add an exclude pattern ? # TODO : add an exclude pattern ?
def require_files_from_directory(absolute_dir_path, files_pattern = "*.rb") def require_files_from_directory(absolute_dir_path, files_pattern = '*.rb')
Dir[File.join(absolute_dir_path, files_pattern)].sort.each do |f| Dir[File.join(absolute_dir_path, files_pattern)].sort.each do |f|
f = File.expand_path(f) f = File.expand_path(f)
require f require f
@@ -59,7 +60,7 @@ def require_files_from_directory(absolute_dir_path, files_pattern = "*.rb")
end end
#require_files_from_directory(COMMON_LIB_DIR) #require_files_from_directory(COMMON_LIB_DIR)
require_files_from_directory(COMMON_LIB_DIR, "**/*.rb") require_files_from_directory(COMMON_LIB_DIR, '**/*.rb')
# Add protocol # Add protocol
def add_http_protocol(url) def add_http_protocol(url)
@@ -71,8 +72,8 @@ def add_trailing_slash(url)
end end
# Gets the string all elements in stringarray ends with # Gets the string all elements in stringarray ends with
def get_equal_string_end(stringarray = [""]) def get_equal_string_end(stringarray = [''])
already_found = "" already_found = ''
looping = true looping = true
counter = -1 counter = -1
if stringarray.kind_of? Array and stringarray.length > 1 if stringarray.kind_of? Array and stringarray.length > 1
@@ -97,15 +98,15 @@ end
# Since ruby 1.9.2, URI::escape is obsolete # Since ruby 1.9.2, URI::escape is obsolete
# See http://rosettacode.org/wiki/URL_encoding#Ruby and http://www.ruby-forum.com/topic/207489 # See http://rosettacode.org/wiki/URL_encoding#Ruby and http://www.ruby-forum.com/topic/207489
if RUBY_VERSION >= "1.9.2" if RUBY_VERSION >= '1.9.2'
module URI module URI
def self.escape(str) def self.escape(str)
URI.encode_www_form_component(str).gsub("+", "%20") URI.encode_www_form_component(str).gsub('+', '%20')
end end
end end
end end
if RUBY_VERSION < "1.9" if RUBY_VERSION < '1.9'
class Array class Array
# Fix for grep with symbols in ruby <= 1.8.7 # Fix for grep with symbols in ruby <= 1.8.7
def _grep_(regexp) def _grep_(regexp)
@@ -128,25 +129,25 @@ require_files_from_directory(UPDATER_LIB_DIR)
if @updater if @updater
REVISION = @updater.local_revision_number() REVISION = @updater.local_revision_number()
else else
REVISION = "NA" REVISION = 'NA'
end end
# our 1337 banner # our 1337 banner
def banner() def banner
puts '____________________________________________________' puts '____________________________________________________'
puts " __ _______ _____ " puts ' __ _______ _____ '
puts " \\ \\ / / __ \\ / ____| " puts ' \\ \\ / / __ \\ / ____| '
puts " \\ \\ /\\ / /| |__) | (___ ___ __ _ _ __ " puts ' \\ \\ /\\ / /| |__) | (___ ___ __ _ _ __ '
puts " \\ \\/ \\/ / | ___/ \\___ \\ / __|/ _` | '_ \\ " puts ' \\ \\/ \\/ / | ___/ \\___ \\ / __|/ _` | \'_ \\ '
puts " \\ /\\ / | | ____) | (__| (_| | | | |" puts ' \\ /\\ / | | ____) | (__| (_| | | | |'
puts " \\/ \\/ |_| |_____/ \\___|\\__,_|_| |_| v#{WPSCAN_VERSION}r#{REVISION}" puts " \\/ \\/ |_| |_____/ \\___|\\__,_|_| |_| v#{WPSCAN_VERSION}r#{REVISION}"
puts puts
puts " WordPress Security Scanner by the WPScan Team" puts ' WordPress Security Scanner by the WPScan Team'
puts " Sponsored by the RandomStorm Open Source Initiative" puts ' Sponsored by the RandomStorm Open Source Initiative'
puts '_____________________________________________________' puts '_____________________________________________________'
puts puts
if RUBY_VERSION < "1.9" if RUBY_VERSION < '1.9'
puts "[WARNING] Ruby < 1.9 not officially supported, please upgrade." puts '[WARNING] Ruby < 1.9 not officially supported, please upgrade.'
puts puts
end end
end end
@@ -165,16 +166,16 @@ end
def get_metasploit_url(module_path) def get_metasploit_url(module_path)
# remove leading slash # remove leading slash
module_path = module_path.sub(/^\//, "") module_path = module_path.sub(/^\//, '')
"http://www.metasploit.com/modules/#{module_path}" "http://www.metasploit.com/modules/#{module_path}"
end end
# Override for puts to enable logging # Override for puts to enable logging
def puts(o = "") def puts(o = '')
# remove color for logging # remove color for logging
if o.respond_to?("gsub") if o.respond_to?('gsub')
temp = o.gsub(/\e\[\d+m(.*)?\e\[0m/, '\1') temp = o.gsub(/\e\[\d+m(.*)?\e\[0m/, '\1')
File.open(LOG_FILE, "a+") { |f| f.puts(temp) } File.open(LOG_FILE, 'a+') { |f| f.puts(temp) }
end end
super(o) super(o)
end end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -47,7 +48,7 @@ rescue LoadError => e
if missing_gem if missing_gem
if missing_gem =~ /nokogiri/i if missing_gem =~ /nokogiri/i
puts puts
puts "Nokogiri needs some packets, please run 'sudo apt-get install libxml2 libxml2-dev libxslt1-dev' to install them. Then run the command below" puts 'Nokogiri needs some packets, please run \'sudo apt-get install libxml2 libxml2-dev libxslt1-dev\' to install them. Then run the command below'
puts puts
end end
puts "[TIP] Try to run 'gem install #{missing_gem}' or 'gem install --user-install #{missing_gem}'. If you still get an error, Please see README file or https://github.com/wpscanteam/wpscan" puts "[TIP] Try to run 'gem install #{missing_gem}' or 'gem install --user-install #{missing_gem}'. If you still get an error, Please see README file or https://github.com/wpscanteam/wpscan"
@@ -55,7 +56,7 @@ rescue LoadError => e
exit(1) exit(1)
end end
if Typhoeus::VERSION == "0.4.0" if Typhoeus::VERSION == '0.4.0'
puts "Typhoeus 0.4.0 detected, please update the gem otherwise wpscan will not work correctly" puts 'Typhoeus 0.4.0 detected, please update the gem otherwise wpscan will not work correctly'
exit(1) exit(1)
end end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -24,7 +25,8 @@ class GitUpdater < Updater
%x[git #{repo_directory_arguments()} status 2>&1] =~ /On branch/ ? true : false %x[git #{repo_directory_arguments()} status 2>&1] =~ /On branch/ ? true : false
end end
# Git has not a revsion number like SVN, so we will take the 7 first chars of the last commit hash # Git has not a revsion number like SVN,
# so we will take the 7 first chars of the last commit hash
def local_revision_number def local_revision_number
git_log = %x[git #{repo_directory_arguments()} log -1 2>&1] git_log = %x[git #{repo_directory_arguments()} log -1 2>&1]
git_log[/commit ([0-9a-z]{7})/i, 1].to_s git_log[/commit ([0-9a-z]{7})/i, 1].to_s

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -21,7 +22,7 @@ require File.expand_path(File.dirname(__FILE__) + '/updater')
class SvnUpdater < Updater class SvnUpdater < Updater
REVISION_PATTERN = /revision="(\d+)"/i REVISION_PATTERN = /revision="(\d+)"/i
TRUNK_URL = "https://github.com/wpscanteam/wpscan" TRUNK_URL = 'https://github.com/wpscanteam/wpscan'
def is_installed? def is_installed?
%x[svn info "#@repo_directory" --xml 2>&1] =~ /revision=/ ? true : false %x[svn info "#@repo_directory" --xml 2>&1] =~ /revision=/ ? true : false

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013

View File

@@ -1,3 +1,5 @@
# encoding: UTF-8
#
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
# #
@@ -18,13 +20,11 @@
class CheckerPlugin < Plugin class CheckerPlugin < Plugin
def initialize def initialize
super( super(author: 'WPScanTeam - @erwanlr')
:author => "@wpscanteam - @erwanlr"
)
register_options( register_options(
["--check-vuln-ref-urls", "--cvru", "Check all the vulnerabilities reference urls for 404"], ['--check-vuln-ref-urls', '--cvru', 'Check all the vulnerabilities reference urls for 404'],
["--check-local-vulnerable-files LOCAL_DIRECTORY", "--clvf", "Perform a recursive scan in the LOCAL_DIRECTORY to find vulnerable files or shells"] ['--check-local-vulnerable-files LOCAL_DIRECTORY', '--clvf', 'Perform a recursive scan in the LOCAL_DIRECTORY to find vulnerable files or shells']
) )
end end
@@ -43,7 +43,7 @@ class CheckerPlugin < Plugin
error_codes = [404, 500, 403] error_codes = [404, 500, 403]
not_found_regexp = %r{No Results Found|error 404|ID Invalid or Not Found}i not_found_regexp = %r{No Results Found|error 404|ID Invalid or Not Found}i
puts "[+] Checking vulnerabilities reference urls" puts '[+] Checking vulnerabilities reference urls'
vuln_ref_files.each do |vuln_ref_file| vuln_ref_files.each do |vuln_ref_file|
xml = Nokogiri::XML(File.open(vuln_ref_file)) do |config| xml = Nokogiri::XML(File.open(vuln_ref_file)) do |config|
@@ -51,7 +51,7 @@ class CheckerPlugin < Plugin
end end
urls = [] urls = []
xml.xpath("//reference").each { |node| urls << node.text } xml.xpath('//reference').each { |node| urls << node.text }
urls.uniq! urls.uniq!
@@ -63,7 +63,7 @@ class CheckerPlugin < Plugin
number_of_urls = urls.size number_of_urls = urls.size
urls.each do |url| urls.each do |url|
request = browser.forge_request(url, { :cache_timeout => 0, :follow_location => true }) request = browser.forge_request(url, { cache_timeout: 0, follow_location: true })
request_count += 1 request_count += 1
request.on_complete do |response| request.on_complete do |response|
@@ -95,11 +95,11 @@ class CheckerPlugin < Plugin
if Dir::exist?(dir_to_scan) if Dir::exist?(dir_to_scan)
xml_file = LOCAL_FILES_FILE xml_file = LOCAL_FILES_FILE
local_hashes = {} local_hashes = {}
file_extension_to_scan = "*.{js,php,swf,html,htm}" file_extension_to_scan = '*.{js,php,swf,html,htm}'
print "[+] Generating local hashes ... " print '[+] Generating local hashes ... '
Dir[File::join(dir_to_scan, "**", file_extension_to_scan)].each do |filename| Dir[File::join(dir_to_scan, '**', file_extension_to_scan)].each do |filename|
sha1sum = Digest::SHA1.file(filename).hexdigest sha1sum = Digest::SHA1.file(filename).hexdigest
if local_hashes.has_key?(sha1sum) if local_hashes.has_key?(sha1sum)
@@ -109,36 +109,36 @@ class CheckerPlugin < Plugin
end end
end end
puts "done." puts 'done.'
puts "[+] Checking for vulnerable files ..." puts '[+] Checking for vulnerable files ...'
xml = Nokogiri::XML(File.open(xml_file)) do |config| xml = Nokogiri::XML(File.open(xml_file)) do |config|
config.noblanks config.noblanks
end end
xml.xpath("//hash").each do |node| xml.xpath('//hash').each do |node|
sha1sum = node.attribute("sha1").text sha1sum = node.attribute('sha1').text
if local_hashes.has_key?(sha1sum) if local_hashes.has_key?(sha1sum)
local_filenames = local_hashes[sha1sum] local_filenames = local_hashes[sha1sum]
vuln_title = node.search("title").text vuln_title = node.search('title').text
vuln_filename = node.search("file").text vuln_filename = node.search('file').text
vuln_refrence = node.search("reference").text vuln_refrence = node.search('reference').text
puts " #{vuln_filename} found :" puts " #{vuln_filename} found :"
puts " | Location(s):" puts ' | Location(s):'
local_filenames.each do |file| local_filenames.each do |file|
puts " | - #{file}" puts " | - #{file}"
end end
puts " |" puts ' |'
puts " | Title: #{vuln_title}" puts " | Title: #{vuln_title}"
puts " | Refrence: #{vuln_refrence}" if !vuln_refrence.empty? puts " | Refrence: #{vuln_refrence}" if !vuln_refrence.empty?
puts puts
end end
end end
puts "done." puts 'done.'
else else
puts "The supplied directory '#{dir_to_scan}' does not exist" puts "The supplied directory '#{dir_to_scan}' does not exist"

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env ruby # encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -26,14 +25,14 @@ class GenerateList
# 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/'
@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/'
@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"
@@ -45,23 +44,23 @@ class GenerateList
def set_file_name(type) def set_file_name(type)
case @type case @type
when "plugin" when 'plugin'
case type case type
when :full when :full
@file_name = PLUGINS_FULL_FILE @file_name = PLUGINS_FULL_FILE
when :popular when :popular
@file_name = PLUGINS_FILE @file_name = PLUGINS_FILE
else else
raise "Unknown type" raise 'Unknown type'
end end
when "theme" when 'theme'
case type case type
when :full when :full
@file_name = THEMES_FULL_FILE @file_name = THEMES_FULL_FILE
when :popular when :popular
@file_name = THEMES_FILE @file_name = THEMES_FILE
else else
raise "Unknown type" raise 'Unknown type'
end end
else else
raise "Unknown type #@type" raise "Unknown type #@type"
@@ -95,7 +94,7 @@ class GenerateList
queue_count += 1 queue_count += 1
request.on_complete do |response| request.on_complete do |response|
puts "[+] Parsing page " + page_count.to_s if @verbose puts "[+] Parsing page #{page_count}" if @verbose
page_count += 1 page_count += 1
response.body.scan(@popular_regex).each do |item| response.body.scan(@popular_regex).each do |item|
puts "[+] Found popular #@type: #{item}" if @verbose puts "[+] Found popular #@type: #{item}" if @verbose

View File

@@ -1,3 +1,5 @@
# encoding: UTF-8
#
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
# #
@@ -18,18 +20,16 @@
class ListGeneratorPlugin < Plugin class ListGeneratorPlugin < Plugin
def initialize def initialize
super( super(author: 'WPScanTeam - @FireFart')
:author => "WPScanTeam - @FireFart"
)
register_options( register_options(
["--generate-plugin-list [NUMBER_OF_PAGES]", "--gpl", Integer, "Generate a new data/plugins.txt file. (supply number of *pages* to parse, default : 150)"], ['--generate-plugin-list [NUMBER_OF_PAGES]', '--gpl', Integer, 'Generate a new data/plugins.txt file. (supply number of *pages* to parse, default : 150)'],
["--generate-full-plugin-list", "--gfpl", "Generate a new full data/plugins.txt file"], ['--generate-full-plugin-list', '--gfpl', 'Generate a new full data/plugins.txt file'],
["--generate-theme-list [NUMBER_OF_PAGES]", "--gtl", Integer, "Generate a new data/themes.txt file. (supply number of *pages* to parse, default : 150)"], ['--generate-theme-list [NUMBER_OF_PAGES]', '--gtl', Integer, 'Generate a new data/themes.txt file. (supply number of *pages* to parse, default : 150)'],
["--generate-full-theme-list", "--gftl", "Generate a new full data/themes.txt file"], ['--generate-full-theme-list', '--gftl', 'Generate a new full data/themes.txt file'],
["--generate-all", "--ga", "Generate a new full plugins, full themes, popular plugins and popular themes list"], ['--generate-all', '--ga', 'Generate a new full plugins, full themes, popular plugins and popular themes list']
) )
end end
@@ -40,13 +40,13 @@ class ListGeneratorPlugin < Plugin
if options.has_key?(:generate_plugin_list) || generate_all if options.has_key?(:generate_plugin_list) || generate_all
number_of_pages = options[:generate_plugin_list] || 150 number_of_pages = options[:generate_plugin_list] || 150
puts "[+] Generating new most popular plugin list" puts '[+] Generating new most popular plugin list'
puts puts
GenerateList.new('plugins', verbose).generate_popular_list(number_of_pages) GenerateList.new('plugins', verbose).generate_popular_list(number_of_pages)
end end
if options[:generate_full_plugin_list] || generate_all if options[:generate_full_plugin_list] || generate_all
puts "[+] Generating new full plugin list" puts '[+] Generating new full plugin list'
puts puts
GenerateList.new('plugins', verbose).generate_full_list GenerateList.new('plugins', verbose).generate_full_list
end end
@@ -54,13 +54,13 @@ class ListGeneratorPlugin < Plugin
if options.has_key?(:generate_theme_list) || generate_all if options.has_key?(:generate_theme_list) || generate_all
number_of_pages = options[:generate_theme_list] || 150 number_of_pages = options[:generate_theme_list] || 150
puts "[+] Generating new most popular theme list" puts '[+] Generating new most popular theme list'
puts puts
GenerateList.new('themes', verbose).generate_popular_list(number_of_pages) GenerateList.new('themes', verbose).generate_popular_list(number_of_pages)
end end
if options[:generate_full_theme_list] || generate_all if options[:generate_full_theme_list] || generate_all
puts "[+] Generating new full theme list" puts '[+] Generating new full theme list'
puts puts
GenerateList.new('themes', verbose).generate_full_list GenerateList.new('themes', verbose).generate_full_list
end end

View File

@@ -1,5 +1,4 @@
#!/usr/bin/env ruby # encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -29,7 +28,7 @@ class SvnParser
@svn_hydra = @svn_browser.hydra @svn_hydra = @svn_browser.hydra
end end
def parse() def parse
get_root_directories get_root_directories
end end
@@ -40,9 +39,11 @@ class SvnParser
def get_root_directories def get_root_directories
dirs = [] dirs = []
rootindex = @svn_browser.get(@svn_root).body rootindex = @svn_browser.get(@svn_root).body
rootindex.scan(%r{<li><a href=".+">(.+)/</a></li>}i).each do |dir| rootindex.scan(%r{<li><a href=".+">(.+)/</a></li>}i).each do |dir|
dirs << dir[0] dirs << dir[0]
end end
dirs.sort! dirs.sort!
dirs.uniq dirs.uniq
end end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#-- #--
# WPScan - WordPress Security Scanner # WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013 # Copyright (C) 2012-2013
@@ -19,33 +20,33 @@
require File.expand_path(File.dirname(__FILE__) + '/../common_helper') require File.expand_path(File.dirname(__FILE__) + '/../common_helper')
require_files_from_directory(WPSTOOLS_LIB_DIR) require_files_from_directory(WPSTOOLS_LIB_DIR)
require_files_from_directory(WPSTOOLS_PLUGINS_DIR, "**/*.rb") require_files_from_directory(WPSTOOLS_PLUGINS_DIR, '**/*.rb')
def usage() def usage
script_name = $0 script_name = $0
puts puts
puts "-h for further help." puts '-h for further help.'
puts puts
puts "Examples:" puts 'Examples:'
puts puts
puts "- Generate a new 'most popular' plugin list, up to 150 pages ..." puts "- Generate a new 'most popular' plugin list, up to 150 pages ..."
puts "ruby #{script_name} --generate-plugin-list 150" puts "ruby #{script_name} --generate-plugin-list 150"
puts puts
puts "- Generate a new full plugin list" puts '- Generate a new full plugin list'
puts "ruby #{script_name} --generate-full-plugin-list" puts "ruby #{script_name} --generate-full-plugin-list"
puts puts
puts "- Generate a new 'most popular' theme list, up to 150 pages ..." puts "- Generate a new 'most popular' theme list, up to 150 pages ..."
puts "ruby #{script_name} --generate-theme-list 150" puts "ruby #{script_name} --generate-theme-list 150"
puts puts
puts "- Generate a new full theme list" puts '- Generate a new full theme list'
puts "ruby #{script_name} --generate-full-theme-list" puts "ruby #{script_name} --generate-full-theme-list"
puts puts
puts "- Generate all list" puts '- Generate all list'
puts "ruby #{script_name} --generate-all" puts "ruby #{script_name} --generate-all"
puts puts
puts "Locally scan a wordpress installation for vulnerable files or shells" puts 'Locally scan a wordpress installation for vulnerable files or shells'
puts "ruby #{script_name} --check-local-vulnerable-files /var/www/wordpress/" puts "ruby #{script_name} --check-local-vulnerable-files /var/www/wordpress/"
puts puts
puts "See README for further information." puts 'See README for further information.'
puts puts
end end

154
wpscan.rb
View File

@@ -24,12 +24,12 @@ require File.dirname(__FILE__) +'/lib/wpscan/wpscan_helper'
def output_vulnerabilities(vulns) def output_vulnerabilities(vulns)
vulns.each do |vulnerability| vulns.each do |vulnerability|
puts puts
puts " | " + red("* Title: #{vulnerability.title}") puts ' | ' + red("* Title: #{vulnerability.title}")
vulnerability.references.each do |r| vulnerability.references.each do |r|
puts " | " + red("* Reference: #{r}") puts ' | ' + red("* Reference: #{r}")
end end
vulnerability.metasploit_modules.each do |m| vulnerability.metasploit_modules.each do |m|
puts " | " + red("* Metasploit module: #{get_metasploit_url(m)}") puts ' | ' + red("* Metasploit module: #{get_metasploit_url(m)}")
end end
end end
end end
@@ -61,8 +61,8 @@ begin
end end
puts @updater.update() puts @updater.update()
else else
puts "Svn / Git not installed, or wpscan has not been installed with one of them." puts 'Svn / Git not installed, or wpscan has not been installed with one of them.'
puts "Update aborted" puts 'Update aborted'
end end
exit(1) exit(1)
end end
@@ -89,37 +89,37 @@ begin
puts puts
else else
puts "The remote host tried to redirect us to #{redirection}" puts "The remote host tried to redirect us to #{redirection}"
puts "Do you want follow the redirection ? [y/n]" puts 'Do you want follow the redirection ? [y/n]'
end end
if wpscan_options.follow_redirection or Readline.readline =~ /^y/i if wpscan_options.follow_redirection or Readline.readline =~ /^y/i
wpscan_options.url = redirection wpscan_options.url = redirection
wp_target = WpTarget.new(redirection, wpscan_options.to_h) wp_target = WpTarget.new(redirection, wpscan_options.to_h)
else else
puts "Scan aborted" puts 'Scan aborted'
exit exit
end end
end end
if wp_target.has_basic_auth? && wpscan_options.basic_auth.nil? if wp_target.has_basic_auth? && wpscan_options.basic_auth.nil?
raise "A basic authentification is required, please provide it with --basic-auth <login:password>" raise 'A basic authentification is required, please provide it with --basic-auth <login:password>'
end end
# Remote website is wordpress? # Remote website is wordpress?
unless wpscan_options.force unless wpscan_options.force
unless wp_target.wordpress? unless wp_target.wordpress?
raise "The remote website is up, but does not seem to be running WordPress." raise 'The remote website is up, but does not seem to be running WordPress.'
end end
end end
unless wp_target.wp_content_dir unless wp_target.wp_content_dir
raise "The wp_content_dir has not been found, please supply it with --wp-content-dir" raise 'The wp_content_dir has not been found, please supply it with --wp-content-dir'
end end
unless wp_target.wp_plugins_dir_exists? unless wp_target.wp_plugins_dir_exists?
puts "The plugins directory '#{wp_target.wp_plugins_dir}' does not exist." puts "The plugins directory '#{wp_target.wp_plugins_dir}' does not exist."
puts "You can specify one per command line option (don't forget to include the wp-content directory if needed)" puts 'You can specify one per command line option (don\'t forget to include the wp-content directory if needed)'
puts "Continue? [y/n]" puts 'Continue? [y/n]'
unless Readline.readline =~ /^y/i unless Readline.readline =~ /^y/i
exit exit
end end
@@ -134,33 +134,33 @@ begin
wp_theme = wp_target.theme wp_theme = wp_target.theme
if wp_theme if wp_theme
# Theme version is handled in wp_item.to_s # Theme version is handled in wp_item.to_s
puts green("[+]") + " The WordPress theme in use is #{wp_theme}" puts green('[+]') + " The WordPress theme in use is #{wp_theme}"
puts puts
puts " | Name: #{wp_theme}" #this will also output the version number if detected puts " | Name: #{wp_theme}" #this will also output the version number if detected
puts " | Location: #{wp_theme.get_url_without_filename}" puts " | Location: #{wp_theme.get_url_without_filename}"
puts " | WordPress: #{wp_theme.wp_org_url}" if wp_theme.wp_org_item? puts " | WordPress: #{wp_theme.wp_org_url}" if wp_theme.wp_org_item?
puts " | Directory listing enabled: Yes" if wp_theme.directory_listing? puts ' | Directory listing enabled: Yes' if wp_theme.directory_listing?
puts " | Readme: #{wp_theme.readme_url}" if wp_theme.has_readme? puts " | Readme: #{wp_theme.readme_url}" if wp_theme.has_readme?
puts " | Changelog: #{wp_theme.changelog_url}" if wp_theme.has_changelog? puts " | Changelog: #{wp_theme.changelog_url}" if wp_theme.has_changelog?
theme_vulnerabilities = wp_theme.vulnerabilities theme_vulnerabilities = wp_theme.vulnerabilities
unless theme_vulnerabilities.empty? unless theme_vulnerabilities.empty?
puts red("[!]") + " We have identified #{theme_vulnerabilities.size} vulnerabilities for this theme :" puts red('[!]') + " We have identified #{theme_vulnerabilities.size} vulnerabilities for this theme :"
output_vulnerabilities(theme_vulnerabilities) output_vulnerabilities(theme_vulnerabilities)
end end
puts puts
end end
if wp_target.has_readme? if wp_target.has_readme?
puts red("[!]") + " The WordPress '#{wp_target.readme_url}' file exists" puts red('[!]') + " The WordPress '#{wp_target.readme_url}' file exists"
end end
if wp_target.has_full_path_disclosure? if wp_target.has_full_path_disclosure?
puts red("[!]") + " Full Path Disclosure (FPD) in '#{wp_target.full_path_disclosure_url}'" puts red('[!]') + " Full Path Disclosure (FPD) in '#{wp_target.full_path_disclosure_url}'"
end end
if wp_target.has_debug_log? if wp_target.has_debug_log?
puts red("[!]") + " Debug log file found : #{wp_target.debug_log_url}" puts red('[!]') + " Debug log file found : #{wp_target.debug_log_url}"
end end
wp_target.config_backup.each do |file_url| wp_target.config_backup.each do |file_url|
@@ -172,46 +172,46 @@ begin
end end
if wp_target.is_multisite? if wp_target.is_multisite?
puts green("[+]") + " This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)" puts green('[+]') + ' This site seems to be a multisite (http://codex.wordpress.org/Glossary#Multisite)'
end end
if wp_target.registration_enabled? if wp_target.registration_enabled?
puts green("[+]") + " User registration is enabled" puts green('[+]') + ' User registration is enabled'
end end
if wp_target.has_xml_rpc? if wp_target.has_xml_rpc?
puts green("[+]") + " XML-RPC Interface available under #{wp_target.xml_rpc_url}" puts green('[+]') + " XML-RPC Interface available under #{wp_target.xml_rpc_url}"
end end
if wp_target.has_malwares? if wp_target.has_malwares?
malwares = wp_target.malwares malwares = wp_target.malwares
puts red("[!]") + " #{malwares.size} malware(s) found :" puts red('[!]') + " #{malwares.size} malware(s) found :"
malwares.each do |malware_url| malwares.each do |malware_url|
puts puts
puts " | " + red("#{malware_url}") puts ' | ' + red("#{malware_url}")
end end
puts puts
end end
wp_version = wp_target.version wp_version = wp_target.version
if wp_version if wp_version
puts green("[+]") + " WordPress version #{wp_version.number} identified from #{wp_version.discovery_method}" puts green('[+]') + " WordPress version #{wp_version.number} identified from #{wp_version.discovery_method}"
version_vulnerabilities = wp_version.vulnerabilities version_vulnerabilities = wp_version.vulnerabilities
unless version_vulnerabilities.empty? unless version_vulnerabilities.empty?
puts puts
puts red("[!]") + " We have identified #{version_vulnerabilities.size} vulnerabilities from the version number :" puts red('[!]') + " We have identified #{version_vulnerabilities.size} vulnerabilities from the version number :"
output_vulnerabilities(version_vulnerabilities) output_vulnerabilities(version_vulnerabilities)
end end
end end
if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil
puts puts
puts green("[+]") + " Enumerating plugins from passive detection ... " puts green('[+]') + ' Enumerating plugins from passive detection ... '
plugins = wp_target.plugins_from_passive_detection(:base_url => wp_target.uri, :wp_content_dir => wp_target.wp_content_dir) plugins = wp_target.plugins_from_passive_detection(base_url: wp_target.uri, wp_content_dir: wp_target.wp_content_dir)
unless plugins.empty? unless plugins.empty?
puts "#{plugins.size} found :" puts "#{plugins.size} found :"
@@ -224,84 +224,84 @@ begin
output_vulnerabilities(plugin.vulnerabilities) output_vulnerabilities(plugin.vulnerabilities)
end end
else else
puts "No plugins found :(" puts 'No plugins found :('
end end
end end
# Enumerate the installed plugins # Enumerate the installed plugins
if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins
puts puts
puts green("[+]") + " Enumerating installed plugins #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_plugins} ..." puts green('[+]') + " Enumerating installed plugins #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_plugins} ..."
puts puts
options = { options = {
:base_url => wp_target.uri, base_url: wp_target.uri,
:only_vulnerable_ones => wpscan_options.enumerate_only_vulnerable_plugins || false, only_vulnerable_ones: wpscan_options.enumerate_only_vulnerable_plugins || false,
:show_progression => true, show_progression: true,
:wp_content_dir => wp_target.wp_content_dir, wp_content_dir: wp_target.wp_content_dir,
:error_404_hash => wp_target.error_404_hash, error_404_hash: wp_target.error_404_hash,
:homepage_hash => wp_target.homepage_hash, homepage_hash: wp_target.homepage_hash,
:wp_plugins_dir => wp_target.wp_plugins_dir, wp_plugins_dir: wp_target.wp_plugins_dir,
:full => wpscan_options.enumerate_all_plugins, full: wpscan_options.enumerate_all_plugins,
:exclude_content_based => wpscan_options.exclude_content_based exclude_content_based: wpscan_options.exclude_content_based
} }
plugins = wp_target.plugins_from_aggressive_detection(options) plugins = wp_target.plugins_from_aggressive_detection(options)
unless plugins.empty? unless plugins.empty?
puts puts
puts puts
puts green("[+]") + " We found #{plugins.size.to_s} plugins:" puts green('[+]') + " We found #{plugins.size.to_s} plugins:"
plugins.each do |plugin| plugins.each do |plugin|
puts puts
puts " | Name: #{plugin}" #this will also output the version number if detected puts " | Name: #{plugin}" #this will also output the version number if detected
puts " | Location: #{plugin.get_url_without_filename}" puts " | Location: #{plugin.get_url_without_filename}"
puts " | WordPress: #{plugin.wp_org_url}" if plugin.wp_org_item? puts " | WordPress: #{plugin.wp_org_url}" if plugin.wp_org_item?
puts " | Directory listing enabled: Yes" if plugin.directory_listing? puts ' | Directory listing enabled: Yes' if plugin.directory_listing?
puts " | Readme: #{plugin.readme_url}" if plugin.has_readme? puts " | Readme: #{plugin.readme_url}" if plugin.has_readme?
puts " | Changelog: #{plugin.changelog_url}" if plugin.has_changelog? puts " | Changelog: #{plugin.changelog_url}" if plugin.has_changelog?
output_vulnerabilities(plugin.vulnerabilities) output_vulnerabilities(plugin.vulnerabilities)
if plugin.error_log? if plugin.error_log?
puts " | " + red("[!]") + " A WordPress error_log file has been found : #{plugin.error_log_url}" puts ' | ' + red('[!]') + " A WordPress error_log file has been found : #{plugin.error_log_url}"
end end
end end
else else
puts puts
puts "No plugins found :(" puts 'No plugins found :('
end end
end end
# Enumerate installed themes # Enumerate installed themes
if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes
puts puts
puts green("[+]") + " Enumerating installed themes #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_themes} ..." puts green('[+]') + " Enumerating installed themes #{'(only vulnerable ones)' if wpscan_options.enumerate_only_vulnerable_themes} ..."
puts puts
options = { options = {
:base_url => wp_target.uri, base_url: wp_target.uri,
:only_vulnerable_ones => wpscan_options.enumerate_only_vulnerable_themes || false, only_vulnerable_ones: wpscan_options.enumerate_only_vulnerable_themes || false,
:show_progression => true, show_progression: true,
:wp_content_dir => wp_target.wp_content_dir, wp_content_dir: wp_target.wp_content_dir,
:error_404_hash => wp_target.error_404_hash, error_404_hash: wp_target.error_404_hash,
:homepage_hash => wp_target.homepage_hash, homepage_hash: wp_target.homepage_hash,
:full => wpscan_options.enumerate_all_themes, full: wpscan_options.enumerate_all_themes,
:exclude_content_based => wpscan_options.exclude_content_based exclude_content_based: wpscan_options.exclude_content_based
} }
themes = wp_target.themes_from_aggressive_detection(options) themes = wp_target.themes_from_aggressive_detection(options)
unless themes.empty? unless themes.empty?
puts puts
puts puts
puts green("[+]") + " We found #{themes.size.to_s} themes:" puts green('[+]') + " We found #{themes.size.to_s} themes:"
themes.each do |theme| themes.each do |theme|
puts puts
puts " | Name: #{theme}" #this will also output the version number if detected puts " | Name: #{theme}" #this will also output the version number if detected
puts " | Location: #{theme.get_url_without_filename}" puts " | Location: #{theme.get_url_without_filename}"
puts " | WordPress: #{theme.wp_org_url}" if theme.wp_org_item? puts " | WordPress: #{theme.wp_org_url}" if theme.wp_org_item?
puts " | Directory listing enabled: Yes" if theme.directory_listing? puts ' | Directory listing enabled: Yes' if theme.directory_listing?
puts " | Readme: #{theme.readme_url}" if theme.has_readme? puts " | Readme: #{theme.readme_url}" if theme.has_readme?
puts " | Changelog: #{theme.changelog_url}" if theme.has_changelog? puts " | Changelog: #{theme.changelog_url}" if theme.has_changelog?
@@ -309,22 +309,22 @@ begin
end end
else else
puts puts
puts "No themes found :(" puts 'No themes found :('
end end
end end
if wpscan_options.enumerate_timthumbs if wpscan_options.enumerate_timthumbs
puts puts
puts green("[+]") + " Enumerating timthumb files ..." puts green('[+]') + ' Enumerating timthumb files ...'
puts puts
options = { options = {
:base_url => wp_target.uri, base_url: wp_target.uri,
:show_progression => true, show_progression: true,
:wp_content_dir => wp_target.wp_content_dir, wp_content_dir: wp_target.wp_content_dir,
:error_404_hash => wp_target.error_404_hash, error_404_hash: wp_target.error_404_hash,
:homepage_hash => wp_target.homepage_hash, homepage_hash: wp_target.homepage_hash,
:exclude_content_based => wpscan_options.exclude_content_based exclude_content_based: wpscan_options.exclude_content_based
} }
theme_name = wp_theme ? wp_theme.name : nil theme_name = wp_theme ? wp_theme.name : nil
@@ -332,36 +332,36 @@ begin
timthumbs = wp_target.timthumbs timthumbs = wp_target.timthumbs
puts puts
puts green("[+]") + " We found #{timthumbs.size.to_s} timthumb file/s :" puts green('[+]') + " We found #{timthumbs.size.to_s} timthumb file/s :"
puts puts
timthumbs.each do |t| timthumbs.each do |t|
puts " | " + red("[!]") + " #{t.get_full_url.to_s}" puts ' | ' + red('[!]') + " #{t.get_full_url.to_s}"
end end
puts puts
puts red(" * Reference: http://www.exploit-db.com/exploits/17602/") puts red(' * Reference: http://www.exploit-db.com/exploits/17602/')
else else
puts puts
puts "No timthumb files found :(" puts 'No timthumb files found :('
end end
end end
# If we haven't been supplied a username, enumerate them... # If we haven't been supplied a username, enumerate them...
if !wpscan_options.username and wpscan_options.wordlist or wpscan_options.enumerate_usernames if !wpscan_options.username and wpscan_options.wordlist or wpscan_options.enumerate_usernames
puts puts
puts green("[+]") + " Enumerating usernames ..." puts green('[+]') + ' Enumerating usernames ...'
usernames = wp_target.usernames(:range => wpscan_options.enumerate_usernames_range) usernames = wp_target.usernames(range: wpscan_options.enumerate_usernames_range)
if usernames.empty? if usernames.empty?
puts puts
puts "We did not enumerate any usernames :(" puts 'We did not enumerate any usernames :('
puts "Try supplying your own username with the --username option" puts 'Try supplying your own username with the --username option'
puts puts
exit(1) exit(1)
else else
puts puts
puts green("[+]") + " We found the following #{usernames.length.to_s} username/s :" puts green('[+]') + " We found the following #{usernames.length.to_s} username/s :"
puts puts
max_id_length = usernames.sort { |a, b| a.id.to_s.length <=> b.id.to_s.length }.last.id.to_s.length max_id_length = usernames.sort { |a, b| a.id.to_s.length <=> b.id.to_s.length }.last.id.to_s.length
@@ -378,7 +378,7 @@ begin
end end
else else
usernames = [WpUser.new(wpscan_options.username, -1, "empty")] usernames = [WpUser.new(wpscan_options.username, -1, 'empty')]
end end
# Start the brute forcer # Start the brute forcer
@@ -390,19 +390,19 @@ begin
puts puts
puts "The plugin #{protection_plugin.name} has been detected. It might record the IP and timestamp of every failed login. Not a good idea for brute forcing !" puts "The plugin #{protection_plugin.name} has been detected. It might record the IP and timestamp of every failed login. Not a good idea for brute forcing !"
puts "[?] Do you want to start the brute force anyway ? [y/n]" puts '[?] Do you want to start the brute force anyway ? [y/n]'
bruteforce = false if Readline.readline !~ /^y/i bruteforce = false if Readline.readline !~ /^y/i
end end
if bruteforce if bruteforce
puts puts
puts green("[+]") + " Starting the password brute forcer" puts green('[+]') + ' Starting the password brute forcer'
puts puts
wp_target.brute_force(usernames, wpscan_options.wordlist, {:show_progression => true}) wp_target.brute_force(usernames, wpscan_options.wordlist, {show_progression: true})
else else
puts puts
puts "Brute forcing aborted" puts 'Brute forcing aborted'
end end
end end
@@ -410,10 +410,10 @@ begin
puts puts
puts green("[+] Finished at #{stop_time.asctime}") puts green("[+] Finished at #{stop_time.asctime}")
elapsed = stop_time - start_time elapsed = stop_time - start_time
puts green("[+] Elapsed time: #{Time.at(elapsed).utc.strftime("%H:%M:%S")}") puts green("[+] Elapsed time: #{Time.at(elapsed).utc.strftime('%H:%M:%S')}")
exit() # must exit! exit() # must exit!
rescue => e rescue => e
puts red("[ERROR] #{e.message}") puts red("[ERROR] #{e.message}")
puts red("Trace :") puts red('Trace :')
puts red(e.backtrace.join("\n")) puts red(e.backtrace.join("\n"))
end end

View File

@@ -19,15 +19,15 @@
#++ #++
$: << '.' $: << '.'
require File.dirname(__FILE__) + "/lib/wpstools/wpstools_helper" require File.dirname(__FILE__) + '/lib/wpstools/wpstools_helper'
begin begin
banner() banner()
option_parser = CustomOptionParser.new("Usage: ./wpstools.rb [options]", 60) option_parser = CustomOptionParser.new('Usage: ./wpstools.rb [options]', 60)
option_parser.separator "" option_parser.separator ''
option_parser.add(["-v", "--verbose", "Verbose output"]) option_parser.add(['-v', '--verbose', 'Verbose output'])
plugins = Plugins.new(option_parser) plugins = Plugins.new(option_parser)
plugins.register( plugins.register(
@@ -47,6 +47,6 @@ begin
rescue => e rescue => e
puts "[ERROR] #{e.message}" puts "[ERROR] #{e.message}"
puts "Trace :" puts 'Trace :'
puts e.backtrace.join("\n") puts e.backtrace.join("\n")
end end