WPSTools updated to respect ruby standards according to rubocop
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -45,7 +46,11 @@ class Browser
|
||||
override_config_with_options(options)
|
||||
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
|
||||
@cache = CacheFileStore.new(CACHE_DIR + '/browser')
|
||||
|
||||
@@ -69,12 +74,13 @@ class Browser
|
||||
end
|
||||
|
||||
def user_agent_mode=(ua_mode)
|
||||
ua_mode ||= "static"
|
||||
ua_mode ||= 'static'
|
||||
|
||||
if USER_AGENT_MODES.include?(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)
|
||||
@user_agent = nil if ua_mode === "semi-static"
|
||||
# For semi-static user agent mode, the user agent has to
|
||||
# be nil the first time (it will be set with the getter)
|
||||
@user_agent = nil if ua_mode === 'semi-static'
|
||||
else
|
||||
raise "Unknow user agent mode : '#{ua_mode}'"
|
||||
end
|
||||
@@ -83,12 +89,12 @@ class Browser
|
||||
# return the user agent, according to the user_agent_mode
|
||||
def user_agent
|
||||
case @user_agent_mode
|
||||
when "semi-static"
|
||||
unless @user_agent
|
||||
@user_agent = @available_user_agents.sample
|
||||
end
|
||||
when "random"
|
||||
when 'semi-static'
|
||||
unless @user_agent
|
||||
@user_agent = @available_user_agents.sample
|
||||
end
|
||||
when 'random'
|
||||
@user_agent = @available_user_agents.sample
|
||||
end
|
||||
@user_agent
|
||||
end
|
||||
@@ -109,21 +115,25 @@ class Browser
|
||||
@proxy_auth = auth
|
||||
elsif auth.is_a?(String)
|
||||
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
|
||||
raise_invalid_proxy_format()
|
||||
raise_invalid_proxy_auth_format()
|
||||
end
|
||||
else
|
||||
raise_invalid_proxy_format()
|
||||
raise_invalid_proxy_auth_format()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def raise_invalid_proxy_format
|
||||
raise "Invalid proxy auth format, expected username:password or {:proxy_username => username, :proxy_password => password}"
|
||||
def raise_invalid_proxy_auth_format
|
||||
raise 'Invalid proxy auth format, expected username:password or {proxy_username: username, proxy_password: password}'
|
||||
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)
|
||||
@config_file = config_file || @config_file
|
||||
|
||||
@@ -146,7 +156,9 @@ class Browser
|
||||
end
|
||||
|
||||
@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
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -18,7 +19,8 @@
|
||||
|
||||
#
|
||||
# => @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 ?
|
||||
# -> 2 dirs : 1 for storage, the other for cache_timeout ?
|
||||
#
|
||||
@@ -28,14 +30,16 @@ require 'yaml'
|
||||
class CacheFileStore
|
||||
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
|
||||
# Marshal does not need any "require"
|
||||
def initialize(storage_path, serializer = Marshal)
|
||||
@storage_path = File.expand_path(storage_path)
|
||||
@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)
|
||||
Dir.mkdir(@storage_path)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
#
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
#
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
#
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -18,39 +19,39 @@
|
||||
|
||||
LIB_DIR = File.dirname(__FILE__)
|
||||
ROOT_DIR = File.expand_path(LIB_DIR + '/..') # expand_path is used to get "wpscan/" instead of "wpscan/lib/../"
|
||||
DATA_DIR = ROOT_DIR + "/data"
|
||||
CONF_DIR = ROOT_DIR + "/conf"
|
||||
CACHE_DIR = ROOT_DIR + "/cache"
|
||||
WPSCAN_LIB_DIR = LIB_DIR + "/wpscan"
|
||||
WPSTOOLS_LIB_DIR = LIB_DIR + "/wpstools"
|
||||
UPDATER_LIB_DIR = LIB_DIR + "/updater"
|
||||
COMMON_LIB_DIR = LIB_DIR + "/common"
|
||||
LOG_FILE = ROOT_DIR + "/log.txt"
|
||||
DATA_DIR = ROOT_DIR + '/data'
|
||||
CONF_DIR = ROOT_DIR + '/conf'
|
||||
CACHE_DIR = ROOT_DIR + '/cache'
|
||||
WPSCAN_LIB_DIR = LIB_DIR + '/wpscan'
|
||||
WPSTOOLS_LIB_DIR = LIB_DIR + '/wpstools'
|
||||
UPDATER_LIB_DIR = LIB_DIR + '/updater'
|
||||
COMMON_LIB_DIR = LIB_DIR + '/common'
|
||||
LOG_FILE = ROOT_DIR + '/log.txt'
|
||||
# Plugins directories
|
||||
COMON_PLUGINS_DIR = COMMON_LIB_DIR + "/plugins"
|
||||
WPSCAN_PLUGINS_DIR = WPSCAN_LIB_DIR + "/plugins"
|
||||
WPSTOOLS_PLUGINS_DIR = WPSTOOLS_LIB_DIR + "/plugins"
|
||||
COMON_PLUGINS_DIR = COMMON_LIB_DIR + '/plugins'
|
||||
WPSCAN_PLUGINS_DIR = WPSCAN_LIB_DIR + '/plugins'
|
||||
WPSTOOLS_PLUGINS_DIR = WPSTOOLS_LIB_DIR + '/plugins'
|
||||
|
||||
# Data files
|
||||
PLUGINS_FILE = DATA_DIR + "/plugins.txt"
|
||||
PLUGINS_FULL_FILE = DATA_DIR + "/plugins_full.txt"
|
||||
PLUGINS_VULNS_FILE = DATA_DIR + "/plugin_vulns.xml"
|
||||
THEMES_FILE = DATA_DIR + "/themes.txt"
|
||||
THEMES_FULL_FILE = DATA_DIR + "/themes_full.txt"
|
||||
THEMES_VULNS_FILE = DATA_DIR + "/theme_vulns.xml"
|
||||
WP_VULNS_FILE = DATA_DIR + "/wp_vulns.xml"
|
||||
WP_VERSIONS_FILE = DATA_DIR + "/wp_versions.xml"
|
||||
LOCAL_FILES_FILE = DATA_DIR + "/local_vulnerable_files.xml"
|
||||
VULNS_XSD = DATA_DIR + "/vuln.xsd"
|
||||
WP_VERSIONS_XSD = DATA_DIR + "/wp_versions.xsd"
|
||||
LOCAL_FILES_XSD = DATA_DIR + "/local_vulnerable_files.xsd"
|
||||
PLUGINS_FILE = DATA_DIR + '/plugins.txt'
|
||||
PLUGINS_FULL_FILE = DATA_DIR + '/plugins_full.txt'
|
||||
PLUGINS_VULNS_FILE = DATA_DIR + '/plugin_vulns.xml'
|
||||
THEMES_FILE = DATA_DIR + '/themes.txt'
|
||||
THEMES_FULL_FILE = DATA_DIR + '/themes_full.txt'
|
||||
THEMES_VULNS_FILE = DATA_DIR + '/theme_vulns.xml'
|
||||
WP_VULNS_FILE = DATA_DIR + '/wp_vulns.xml'
|
||||
WP_VERSIONS_FILE = DATA_DIR + '/wp_versions.xml'
|
||||
LOCAL_FILES_FILE = DATA_DIR + '/local_vulnerable_files.xml'
|
||||
VULNS_XSD = DATA_DIR + '/vuln.xsd'
|
||||
WP_VERSIONS_XSD = DATA_DIR + '/wp_versions.xsd'
|
||||
LOCAL_FILES_XSD = DATA_DIR + '/local_vulnerable_files.xsd'
|
||||
|
||||
WPSCAN_VERSION = "2.0"
|
||||
WPSCAN_VERSION = '2.0'
|
||||
|
||||
require "#{LIB_DIR}/environment"
|
||||
|
||||
# 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|
|
||||
f = File.expand_path(f)
|
||||
require f
|
||||
@@ -59,7 +60,7 @@ def require_files_from_directory(absolute_dir_path, files_pattern = "*.rb")
|
||||
end
|
||||
|
||||
#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
|
||||
def add_http_protocol(url)
|
||||
@@ -71,8 +72,8 @@ def add_trailing_slash(url)
|
||||
end
|
||||
|
||||
# Gets the string all elements in stringarray ends with
|
||||
def get_equal_string_end(stringarray = [""])
|
||||
already_found = ""
|
||||
def get_equal_string_end(stringarray = [''])
|
||||
already_found = ''
|
||||
looping = true
|
||||
counter = -1
|
||||
if stringarray.kind_of? Array and stringarray.length > 1
|
||||
@@ -97,15 +98,15 @@ end
|
||||
|
||||
# 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
|
||||
if RUBY_VERSION >= "1.9.2"
|
||||
if RUBY_VERSION >= '1.9.2'
|
||||
module URI
|
||||
def self.escape(str)
|
||||
URI.encode_www_form_component(str).gsub("+", "%20")
|
||||
URI.encode_www_form_component(str).gsub('+', '%20')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION < "1.9"
|
||||
if RUBY_VERSION < '1.9'
|
||||
class Array
|
||||
# Fix for grep with symbols in ruby <= 1.8.7
|
||||
def _grep_(regexp)
|
||||
@@ -128,25 +129,25 @@ require_files_from_directory(UPDATER_LIB_DIR)
|
||||
if @updater
|
||||
REVISION = @updater.local_revision_number()
|
||||
else
|
||||
REVISION = "NA"
|
||||
REVISION = 'NA'
|
||||
end
|
||||
|
||||
# our 1337 banner
|
||||
def banner()
|
||||
def banner
|
||||
puts '____________________________________________________'
|
||||
puts " __ _______ _____ "
|
||||
puts " \\ \\ / / __ \\ / ____| "
|
||||
puts " \\ \\ /\\ / /| |__) | (___ ___ __ _ _ __ "
|
||||
puts " \\ \\/ \\/ / | ___/ \\___ \\ / __|/ _` | '_ \\ "
|
||||
puts " \\ /\\ / | | ____) | (__| (_| | | | |"
|
||||
puts ' __ _______ _____ '
|
||||
puts ' \\ \\ / / __ \\ / ____| '
|
||||
puts ' \\ \\ /\\ / /| |__) | (___ ___ __ _ _ __ '
|
||||
puts ' \\ \\/ \\/ / | ___/ \\___ \\ / __|/ _` | \'_ \\ '
|
||||
puts ' \\ /\\ / | | ____) | (__| (_| | | | |'
|
||||
puts " \\/ \\/ |_| |_____/ \\___|\\__,_|_| |_| v#{WPSCAN_VERSION}r#{REVISION}"
|
||||
puts
|
||||
puts " WordPress Security Scanner by the WPScan Team"
|
||||
puts " Sponsored by the RandomStorm Open Source Initiative"
|
||||
puts ' WordPress Security Scanner by the WPScan Team'
|
||||
puts ' Sponsored by the RandomStorm Open Source Initiative'
|
||||
puts '_____________________________________________________'
|
||||
puts
|
||||
if RUBY_VERSION < "1.9"
|
||||
puts "[WARNING] Ruby < 1.9 not officially supported, please upgrade."
|
||||
if RUBY_VERSION < '1.9'
|
||||
puts '[WARNING] Ruby < 1.9 not officially supported, please upgrade.'
|
||||
puts
|
||||
end
|
||||
end
|
||||
@@ -165,16 +166,16 @@ end
|
||||
|
||||
def get_metasploit_url(module_path)
|
||||
# remove leading slash
|
||||
module_path = module_path.sub(/^\//, "")
|
||||
module_path = module_path.sub(/^\//, '')
|
||||
"http://www.metasploit.com/modules/#{module_path}"
|
||||
end
|
||||
|
||||
# Override for puts to enable logging
|
||||
def puts(o = "")
|
||||
def puts(o = '')
|
||||
# remove color for logging
|
||||
if o.respond_to?("gsub")
|
||||
if o.respond_to?('gsub')
|
||||
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
|
||||
super(o)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -47,7 +48,7 @@ rescue LoadError => e
|
||||
if missing_gem
|
||||
if missing_gem =~ /nokogiri/i
|
||||
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
|
||||
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"
|
||||
@@ -55,7 +56,7 @@ rescue LoadError => e
|
||||
exit(1)
|
||||
end
|
||||
|
||||
if Typhoeus::VERSION == "0.4.0"
|
||||
puts "Typhoeus 0.4.0 detected, please update the gem otherwise wpscan will not work correctly"
|
||||
if Typhoeus::VERSION == '0.4.0'
|
||||
puts 'Typhoeus 0.4.0 detected, please update the gem otherwise wpscan will not work correctly'
|
||||
exit(1)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -24,7 +25,8 @@ class GitUpdater < Updater
|
||||
%x[git #{repo_directory_arguments()} status 2>&1] =~ /On branch/ ? true : false
|
||||
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
|
||||
git_log = %x[git #{repo_directory_arguments()} log -1 2>&1]
|
||||
git_log[/commit ([0-9a-z]{7})/i, 1].to_s
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -21,7 +22,7 @@ require File.expand_path(File.dirname(__FILE__) + '/updater')
|
||||
class SvnUpdater < Updater
|
||||
|
||||
REVISION_PATTERN = /revision="(\d+)"/i
|
||||
TRUNK_URL = "https://github.com/wpscanteam/wpscan"
|
||||
TRUNK_URL = 'https://github.com/wpscanteam/wpscan'
|
||||
|
||||
def is_installed?
|
||||
%x[svn info "#@repo_directory" --xml 2>&1] =~ /revision=/ ? true : false
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
#
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
@@ -18,13 +20,11 @@
|
||||
class CheckerPlugin < Plugin
|
||||
|
||||
def initialize
|
||||
super(
|
||||
:author => "@wpscanteam - @erwanlr"
|
||||
)
|
||||
super(author: 'WPScanTeam - @erwanlr')
|
||||
|
||||
register_options(
|
||||
["--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-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']
|
||||
)
|
||||
end
|
||||
|
||||
@@ -39,11 +39,11 @@ class CheckerPlugin < Plugin
|
||||
end
|
||||
|
||||
def check_vuln_ref_urls
|
||||
vuln_ref_files = [ PLUGINS_VULNS_FILE , THEMES_VULNS_FILE, WP_VULNS_FILE ]
|
||||
vuln_ref_files = [PLUGINS_VULNS_FILE, THEMES_VULNS_FILE, WP_VULNS_FILE]
|
||||
error_codes = [404, 500, 403]
|
||||
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|
|
||||
xml = Nokogiri::XML(File.open(vuln_ref_file)) do |config|
|
||||
@@ -51,7 +51,7 @@ class CheckerPlugin < Plugin
|
||||
end
|
||||
|
||||
urls = []
|
||||
xml.xpath("//reference").each { |node| urls << node.text }
|
||||
xml.xpath('//reference').each { |node| urls << node.text }
|
||||
|
||||
urls.uniq!
|
||||
|
||||
@@ -63,7 +63,7 @@ class CheckerPlugin < Plugin
|
||||
number_of_urls = urls.size
|
||||
|
||||
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.on_complete do |response|
|
||||
@@ -95,11 +95,11 @@ class CheckerPlugin < Plugin
|
||||
if Dir::exist?(dir_to_scan)
|
||||
xml_file = LOCAL_FILES_FILE
|
||||
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
|
||||
|
||||
if local_hashes.has_key?(sha1sum)
|
||||
@@ -109,36 +109,36 @@ class CheckerPlugin < Plugin
|
||||
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|
|
||||
config.noblanks
|
||||
end
|
||||
|
||||
xml.xpath("//hash").each do |node|
|
||||
sha1sum = node.attribute("sha1").text
|
||||
xml.xpath('//hash').each do |node|
|
||||
sha1sum = node.attribute('sha1').text
|
||||
|
||||
if local_hashes.has_key?(sha1sum)
|
||||
local_filenames = local_hashes[sha1sum]
|
||||
vuln_title = node.search("title").text
|
||||
vuln_filename = node.search("file").text
|
||||
vuln_refrence = node.search("reference").text
|
||||
vuln_title = node.search('title').text
|
||||
vuln_filename = node.search('file').text
|
||||
vuln_refrence = node.search('reference').text
|
||||
|
||||
puts " #{vuln_filename} found :"
|
||||
puts " | Location(s):"
|
||||
puts ' | Location(s):'
|
||||
local_filenames.each do |file|
|
||||
puts " | - #{file}"
|
||||
end
|
||||
puts " |"
|
||||
puts ' |'
|
||||
puts " | Title: #{vuln_title}"
|
||||
puts " | Refrence: #{vuln_refrence}" if !vuln_refrence.empty?
|
||||
puts
|
||||
end
|
||||
end
|
||||
|
||||
puts "done."
|
||||
puts 'done.'
|
||||
|
||||
else
|
||||
puts "The supplied directory '#{dir_to_scan}' does not exist"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -26,14 +25,14 @@ class GenerateList
|
||||
# type = themes | plugins
|
||||
def initialize(type, verbose)
|
||||
if type =~ /plugins/i
|
||||
@type = "plugin"
|
||||
@svn_url = "http://plugins.svn.wordpress.org/"
|
||||
@popular_url = "http://wordpress.org/extend/plugins/browse/popular/"
|
||||
@type = 'plugin'
|
||||
@svn_url = 'http://plugins.svn.wordpress.org/'
|
||||
@popular_url = 'http://wordpress.org/extend/plugins/browse/popular/'
|
||||
@popular_regex = %r{<h3><a href="http://wordpress.org/extend/plugins/(.+)/">.+</a></h3>}i
|
||||
elsif type =~ /themes/i
|
||||
@type = "theme"
|
||||
@svn_url = "http://themes.svn.wordpress.org/"
|
||||
@popular_url = "http://wordpress.org/extend/themes/browse/popular/"
|
||||
@type = 'theme'
|
||||
@svn_url = 'http://themes.svn.wordpress.org/'
|
||||
@popular_url = 'http://wordpress.org/extend/themes/browse/popular/'
|
||||
@popular_regex = %r{<h3><a href="http://wordpress.org/extend/themes/(.+)">.+</a></h3>}i
|
||||
else
|
||||
raise "Type #{type} not defined"
|
||||
@@ -45,24 +44,24 @@ class GenerateList
|
||||
|
||||
def set_file_name(type)
|
||||
case @type
|
||||
when "plugin"
|
||||
case type
|
||||
when :full
|
||||
@file_name = PLUGINS_FULL_FILE
|
||||
when :popular
|
||||
@file_name = PLUGINS_FILE
|
||||
else
|
||||
raise "Unknown type"
|
||||
end
|
||||
when "theme"
|
||||
case type
|
||||
when :full
|
||||
@file_name = THEMES_FULL_FILE
|
||||
when :popular
|
||||
@file_name = THEMES_FILE
|
||||
else
|
||||
raise "Unknown type"
|
||||
end
|
||||
when 'plugin'
|
||||
case type
|
||||
when :full
|
||||
@file_name = PLUGINS_FULL_FILE
|
||||
when :popular
|
||||
@file_name = PLUGINS_FILE
|
||||
else
|
||||
raise 'Unknown type'
|
||||
end
|
||||
when 'theme'
|
||||
case type
|
||||
when :full
|
||||
@file_name = THEMES_FULL_FILE
|
||||
when :popular
|
||||
@file_name = THEMES_FILE
|
||||
else
|
||||
raise 'Unknown type'
|
||||
end
|
||||
else
|
||||
raise "Unknown type #@type"
|
||||
end
|
||||
@@ -87,7 +86,7 @@ class GenerateList
|
||||
page_count = 1
|
||||
queue_count = 0
|
||||
|
||||
(1...(pages.to_i+1)).each do |page|
|
||||
(1...(pages.to_i + 1)).each do |page|
|
||||
# First page has another URL
|
||||
url = (page == 1) ? @popular_url : @popular_url + 'page/' + page.to_s + '/'
|
||||
request = @browser.forge_request(url)
|
||||
@@ -95,7 +94,7 @@ class GenerateList
|
||||
queue_count += 1
|
||||
|
||||
request.on_complete do |response|
|
||||
puts "[+] Parsing page " + page_count.to_s if @verbose
|
||||
puts "[+] Parsing page #{page_count}" if @verbose
|
||||
page_count += 1
|
||||
response.body.scan(@popular_regex).each do |item|
|
||||
puts "[+] Found popular #@type: #{item}" if @verbose
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
#
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
#
|
||||
@@ -18,18 +20,16 @@
|
||||
class ListGeneratorPlugin < Plugin
|
||||
|
||||
def initialize
|
||||
super(
|
||||
:author => "WPScanTeam - @FireFart"
|
||||
)
|
||||
super(author: 'WPScanTeam - @FireFart')
|
||||
|
||||
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-full-plugin-list", "--gfpl", "Generate a new full data/plugins.txt file"],
|
||||
['--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-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-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-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
|
||||
|
||||
@@ -40,13 +40,13 @@ class ListGeneratorPlugin < Plugin
|
||||
if options.has_key?(:generate_plugin_list) || generate_all
|
||||
number_of_pages = options[:generate_plugin_list] || 150
|
||||
|
||||
puts "[+] Generating new most popular plugin list"
|
||||
puts '[+] Generating new most popular plugin list'
|
||||
puts
|
||||
GenerateList.new('plugins', verbose).generate_popular_list(number_of_pages)
|
||||
end
|
||||
|
||||
if options[:generate_full_plugin_list] || generate_all
|
||||
puts "[+] Generating new full plugin list"
|
||||
puts '[+] Generating new full plugin list'
|
||||
puts
|
||||
GenerateList.new('plugins', verbose).generate_full_list
|
||||
end
|
||||
@@ -54,13 +54,13 @@ class ListGeneratorPlugin < Plugin
|
||||
if options.has_key?(:generate_theme_list) || generate_all
|
||||
number_of_pages = options[:generate_theme_list] || 150
|
||||
|
||||
puts "[+] Generating new most popular theme list"
|
||||
puts '[+] Generating new most popular theme list'
|
||||
puts
|
||||
GenerateList.new('themes', verbose).generate_popular_list(number_of_pages)
|
||||
end
|
||||
|
||||
if options[:generate_full_theme_list] || generate_all
|
||||
puts "[+] Generating new full theme list"
|
||||
puts '[+] Generating new full theme list'
|
||||
puts
|
||||
GenerateList.new('themes', verbose).generate_full_list
|
||||
end
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -24,12 +23,12 @@ class SvnParser
|
||||
attr_accessor :verbose, :svn_root, :keep_empty_dirs
|
||||
|
||||
def initialize(svn_root)
|
||||
@svn_root = svn_root
|
||||
@svn_browser = Browser.instance
|
||||
@svn_hydra = @svn_browser.hydra
|
||||
@svn_root = svn_root
|
||||
@svn_browser = Browser.instance
|
||||
@svn_hydra = @svn_browser.hydra
|
||||
end
|
||||
|
||||
def parse()
|
||||
def parse
|
||||
get_root_directories
|
||||
end
|
||||
|
||||
@@ -38,11 +37,13 @@ class SvnParser
|
||||
|
||||
# Gets all directories in the SVN root
|
||||
def get_root_directories
|
||||
dirs = []
|
||||
dirs = []
|
||||
rootindex = @svn_browser.get(@svn_root).body
|
||||
|
||||
rootindex.scan(%r{<li><a href=".+">(.+)/</a></li>}i).each do |dir|
|
||||
dirs << dir[0]
|
||||
end
|
||||
|
||||
dirs.sort!
|
||||
dirs.uniq
|
||||
end
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# encoding: UTF-8
|
||||
#--
|
||||
# WPScan - WordPress Security Scanner
|
||||
# Copyright (C) 2012-2013
|
||||
@@ -19,33 +20,33 @@
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../common_helper')
|
||||
|
||||
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
|
||||
puts
|
||||
puts "-h for further help."
|
||||
puts '-h for further help.'
|
||||
puts
|
||||
puts "Examples:"
|
||||
puts 'Examples:'
|
||||
puts
|
||||
puts "- Generate a new 'most popular' plugin list, up to 150 pages ..."
|
||||
puts "ruby #{script_name} --generate-plugin-list 150"
|
||||
puts
|
||||
puts "- Generate a new full plugin list"
|
||||
puts '- Generate a new full plugin list'
|
||||
puts "ruby #{script_name} --generate-full-plugin-list"
|
||||
puts
|
||||
puts "- Generate a new 'most popular' theme list, up to 150 pages ..."
|
||||
puts "ruby #{script_name} --generate-theme-list 150"
|
||||
puts
|
||||
puts "- Generate a new full theme list"
|
||||
puts '- Generate a new full theme list'
|
||||
puts "ruby #{script_name} --generate-full-theme-list"
|
||||
puts
|
||||
puts "- Generate all list"
|
||||
puts '- Generate all list'
|
||||
puts "ruby #{script_name} --generate-all"
|
||||
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
|
||||
puts "See README for further information."
|
||||
puts 'See README for further information.'
|
||||
puts
|
||||
end
|
||||
|
||||
156
wpscan.rb
156
wpscan.rb
@@ -19,17 +19,17 @@
|
||||
#++
|
||||
|
||||
$: << '.'
|
||||
require File.dirname(__FILE__) +'/lib/wpscan/wpscan_helper'
|
||||
require File.dirname(__FILE__) + '/lib/wpscan/wpscan_helper'
|
||||
|
||||
def output_vulnerabilities(vulns)
|
||||
vulns.each do |vulnerability|
|
||||
puts
|
||||
puts " | " + red("* Title: #{vulnerability.title}")
|
||||
puts ' | ' + red("* Title: #{vulnerability.title}")
|
||||
vulnerability.references.each do |r|
|
||||
puts " | " + red("* Reference: #{r}")
|
||||
puts ' | ' + red("* Reference: #{r}")
|
||||
end
|
||||
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
|
||||
@@ -61,8 +61,8 @@ begin
|
||||
end
|
||||
puts @updater.update()
|
||||
else
|
||||
puts "Svn / Git not installed, or wpscan has not been installed with one of them."
|
||||
puts "Update aborted"
|
||||
puts 'Svn / Git not installed, or wpscan has not been installed with one of them.'
|
||||
puts 'Update aborted'
|
||||
end
|
||||
exit(1)
|
||||
end
|
||||
@@ -89,37 +89,37 @@ begin
|
||||
puts
|
||||
else
|
||||
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
|
||||
|
||||
if wpscan_options.follow_redirection or Readline.readline =~ /^y/i
|
||||
wpscan_options.url = redirection
|
||||
wp_target = WpTarget.new(redirection, wpscan_options.to_h)
|
||||
else
|
||||
puts "Scan aborted"
|
||||
puts 'Scan aborted'
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
# Remote website is wordpress?
|
||||
unless wpscan_options.force
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
unless wp_target.wp_plugins_dir_exists?
|
||||
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 "Continue? [y/n]"
|
||||
puts 'You can specify one per command line option (don\'t forget to include the wp-content directory if needed)'
|
||||
puts 'Continue? [y/n]'
|
||||
unless Readline.readline =~ /^y/i
|
||||
exit
|
||||
end
|
||||
@@ -134,33 +134,33 @@ begin
|
||||
wp_theme = wp_target.theme
|
||||
if wp_theme
|
||||
# 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 " | Name: #{wp_theme}" #this will also output the version number if detected
|
||||
puts " | Location: #{wp_theme.get_url_without_filename}"
|
||||
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 " | Changelog: #{wp_theme.changelog_url}" if wp_theme.has_changelog?
|
||||
|
||||
theme_vulnerabilities = wp_theme.vulnerabilities
|
||||
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)
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
wp_target.config_backup.each do |file_url|
|
||||
@@ -172,46 +172,46 @@ begin
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if wp_target.registration_enabled?
|
||||
puts green("[+]") + " User registration is enabled"
|
||||
puts green('[+]') + ' User registration is enabled'
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if wp_target.has_malwares?
|
||||
malwares = wp_target.malwares
|
||||
puts red("[!]") + " #{malwares.size} malware(s) found :"
|
||||
puts red('[!]') + " #{malwares.size} malware(s) found :"
|
||||
|
||||
malwares.each do |malware_url|
|
||||
puts
|
||||
puts " | " + red("#{malware_url}")
|
||||
puts ' | ' + red("#{malware_url}")
|
||||
end
|
||||
puts
|
||||
end
|
||||
|
||||
wp_version = wp_target.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
|
||||
|
||||
unless version_vulnerabilities.empty?
|
||||
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)
|
||||
end
|
||||
end
|
||||
|
||||
if wpscan_options.enumerate_plugins == nil and wpscan_options.enumerate_only_vulnerable_plugins == nil
|
||||
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?
|
||||
puts "#{plugins.size} found :"
|
||||
|
||||
@@ -224,84 +224,84 @@ begin
|
||||
output_vulnerabilities(plugin.vulnerabilities)
|
||||
end
|
||||
else
|
||||
puts "No plugins found :("
|
||||
puts 'No plugins found :('
|
||||
end
|
||||
end
|
||||
|
||||
# Enumerate the installed plugins
|
||||
if wpscan_options.enumerate_plugins or wpscan_options.enumerate_only_vulnerable_plugins or wpscan_options.enumerate_all_plugins
|
||||
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
|
||||
|
||||
options = {
|
||||
:base_url => wp_target.uri,
|
||||
:only_vulnerable_ones => wpscan_options.enumerate_only_vulnerable_plugins || false,
|
||||
:show_progression => true,
|
||||
:wp_content_dir => wp_target.wp_content_dir,
|
||||
:error_404_hash => wp_target.error_404_hash,
|
||||
:homepage_hash => wp_target.homepage_hash,
|
||||
:wp_plugins_dir => wp_target.wp_plugins_dir,
|
||||
:full => wpscan_options.enumerate_all_plugins,
|
||||
:exclude_content_based => wpscan_options.exclude_content_based
|
||||
base_url: wp_target.uri,
|
||||
only_vulnerable_ones: wpscan_options.enumerate_only_vulnerable_plugins || false,
|
||||
show_progression: true,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
wp_plugins_dir: wp_target.wp_plugins_dir,
|
||||
full: wpscan_options.enumerate_all_plugins,
|
||||
exclude_content_based: wpscan_options.exclude_content_based
|
||||
}
|
||||
|
||||
plugins = wp_target.plugins_from_aggressive_detection(options)
|
||||
unless plugins.empty?
|
||||
puts
|
||||
puts
|
||||
puts green("[+]") + " We found #{plugins.size.to_s} plugins:"
|
||||
puts green('[+]') + " We found #{plugins.size.to_s} plugins:"
|
||||
|
||||
plugins.each do |plugin|
|
||||
puts
|
||||
puts " | Name: #{plugin}" #this will also output the version number if detected
|
||||
puts " | Location: #{plugin.get_url_without_filename}"
|
||||
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 " | Changelog: #{plugin.changelog_url}" if plugin.has_changelog?
|
||||
|
||||
output_vulnerabilities(plugin.vulnerabilities)
|
||||
|
||||
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
|
||||
else
|
||||
puts
|
||||
puts "No plugins found :("
|
||||
puts 'No plugins found :('
|
||||
end
|
||||
end
|
||||
|
||||
# Enumerate installed themes
|
||||
if wpscan_options.enumerate_themes or wpscan_options.enumerate_only_vulnerable_themes or wpscan_options.enumerate_all_themes
|
||||
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
|
||||
|
||||
options = {
|
||||
:base_url => wp_target.uri,
|
||||
:only_vulnerable_ones => wpscan_options.enumerate_only_vulnerable_themes || false,
|
||||
:show_progression => true,
|
||||
:wp_content_dir => wp_target.wp_content_dir,
|
||||
:error_404_hash => wp_target.error_404_hash,
|
||||
:homepage_hash => wp_target.homepage_hash,
|
||||
:full => wpscan_options.enumerate_all_themes,
|
||||
:exclude_content_based => wpscan_options.exclude_content_based
|
||||
base_url: wp_target.uri,
|
||||
only_vulnerable_ones: wpscan_options.enumerate_only_vulnerable_themes || false,
|
||||
show_progression: true,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
full: wpscan_options.enumerate_all_themes,
|
||||
exclude_content_based: wpscan_options.exclude_content_based
|
||||
}
|
||||
|
||||
themes = wp_target.themes_from_aggressive_detection(options)
|
||||
unless themes.empty?
|
||||
puts
|
||||
puts
|
||||
puts green("[+]") + " We found #{themes.size.to_s} themes:"
|
||||
puts green('[+]') + " We found #{themes.size.to_s} themes:"
|
||||
|
||||
themes.each do |theme|
|
||||
puts
|
||||
puts " | Name: #{theme}" #this will also output the version number if detected
|
||||
puts " | Location: #{theme.get_url_without_filename}"
|
||||
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 " | Changelog: #{theme.changelog_url}" if theme.has_changelog?
|
||||
|
||||
@@ -309,22 +309,22 @@ begin
|
||||
end
|
||||
else
|
||||
puts
|
||||
puts "No themes found :("
|
||||
puts 'No themes found :('
|
||||
end
|
||||
end
|
||||
|
||||
if wpscan_options.enumerate_timthumbs
|
||||
puts
|
||||
puts green("[+]") + " Enumerating timthumb files ..."
|
||||
puts green('[+]') + ' Enumerating timthumb files ...'
|
||||
puts
|
||||
|
||||
options = {
|
||||
:base_url => wp_target.uri,
|
||||
:show_progression => true,
|
||||
:wp_content_dir => wp_target.wp_content_dir,
|
||||
:error_404_hash => wp_target.error_404_hash,
|
||||
:homepage_hash => wp_target.homepage_hash,
|
||||
:exclude_content_based => wpscan_options.exclude_content_based
|
||||
base_url: wp_target.uri,
|
||||
show_progression: true,
|
||||
wp_content_dir: wp_target.wp_content_dir,
|
||||
error_404_hash: wp_target.error_404_hash,
|
||||
homepage_hash: wp_target.homepage_hash,
|
||||
exclude_content_based: wpscan_options.exclude_content_based
|
||||
}
|
||||
|
||||
theme_name = wp_theme ? wp_theme.name : nil
|
||||
@@ -332,36 +332,36 @@ begin
|
||||
timthumbs = wp_target.timthumbs
|
||||
|
||||
puts
|
||||
puts green("[+]") + " We found #{timthumbs.size.to_s} timthumb file/s :"
|
||||
puts green('[+]') + " We found #{timthumbs.size.to_s} timthumb file/s :"
|
||||
puts
|
||||
|
||||
timthumbs.each do |t|
|
||||
puts " | " + red("[!]") + " #{t.get_full_url.to_s}"
|
||||
puts ' | ' + red('[!]') + " #{t.get_full_url.to_s}"
|
||||
end
|
||||
puts
|
||||
puts red(" * Reference: http://www.exploit-db.com/exploits/17602/")
|
||||
puts red(' * Reference: http://www.exploit-db.com/exploits/17602/')
|
||||
else
|
||||
puts
|
||||
puts "No timthumb files found :("
|
||||
puts 'No timthumb files found :('
|
||||
end
|
||||
end
|
||||
|
||||
# If we haven't been supplied a username, enumerate them...
|
||||
if !wpscan_options.username and wpscan_options.wordlist or wpscan_options.enumerate_usernames
|
||||
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?
|
||||
puts
|
||||
puts "We did not enumerate any usernames :("
|
||||
puts "Try supplying your own username with the --username option"
|
||||
puts 'We did not enumerate any usernames :('
|
||||
puts 'Try supplying your own username with the --username option'
|
||||
puts
|
||||
exit(1)
|
||||
else
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
else
|
||||
usernames = [WpUser.new(wpscan_options.username, -1, "empty")]
|
||||
usernames = [WpUser.new(wpscan_options.username, -1, 'empty')]
|
||||
end
|
||||
|
||||
# Start the brute forcer
|
||||
@@ -390,19 +390,19 @@ begin
|
||||
|
||||
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 "[?] 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
|
||||
end
|
||||
|
||||
if bruteforce
|
||||
puts
|
||||
puts green("[+]") + " Starting the password brute forcer"
|
||||
puts green('[+]') + ' Starting the password brute forcer'
|
||||
puts
|
||||
wp_target.brute_force(usernames, wpscan_options.wordlist, {:show_progression => true})
|
||||
wp_target.brute_force(usernames, wpscan_options.wordlist, {show_progression: true})
|
||||
else
|
||||
puts
|
||||
puts "Brute forcing aborted"
|
||||
puts 'Brute forcing aborted'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -410,10 +410,10 @@ begin
|
||||
puts
|
||||
puts green("[+] Finished at #{stop_time.asctime}")
|
||||
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!
|
||||
rescue => e
|
||||
puts red("[ERROR] #{e.message}")
|
||||
puts red("Trace :")
|
||||
puts red('Trace :')
|
||||
puts red(e.backtrace.join("\n"))
|
||||
end
|
||||
|
||||
10
wpstools.rb
10
wpstools.rb
@@ -19,15 +19,15 @@
|
||||
#++
|
||||
|
||||
$: << '.'
|
||||
require File.dirname(__FILE__) + "/lib/wpstools/wpstools_helper"
|
||||
require File.dirname(__FILE__) + '/lib/wpstools/wpstools_helper'
|
||||
|
||||
begin
|
||||
|
||||
banner()
|
||||
|
||||
option_parser = CustomOptionParser.new("Usage: ./wpstools.rb [options]", 60)
|
||||
option_parser.separator ""
|
||||
option_parser.add(["-v", "--verbose", "Verbose output"])
|
||||
option_parser = CustomOptionParser.new('Usage: ./wpstools.rb [options]', 60)
|
||||
option_parser.separator ''
|
||||
option_parser.add(['-v', '--verbose', 'Verbose output'])
|
||||
|
||||
plugins = Plugins.new(option_parser)
|
||||
plugins.register(
|
||||
@@ -47,6 +47,6 @@ begin
|
||||
|
||||
rescue => e
|
||||
puts "[ERROR] #{e.message}"
|
||||
puts "Trace :"
|
||||
puts 'Trace :'
|
||||
puts e.backtrace.join("\n")
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user