lib/wpscan rubocopied

This commit is contained in:
erwanlr
2013-01-24 18:23:54 +01:00
parent b0dd9ba989
commit 3094d31633
24 changed files with 338 additions and 296 deletions

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -34,10 +35,10 @@ module BruteForce
request_count = 0
password_found = false
File.open(wordlist_path, "r").each do |password|
File.open(wordlist_path, 'r').each do |password|
# ignore file comments, but will miss passwords if they start with a hash...
next if password[0,1] == "#"
next if password[0, 1] == '#'
# keep a count of the amount of requests to be sent
request_count += 1
@@ -50,9 +51,9 @@ module BruteForce
# the request object
request = Browser.instance.forge_request(login_url,
{
:method => :post,
:params => {:log => username, :pwd => password},
:cache_timeout => 0
method: :post,
params: {log: username, pwd: password},
cache_timeout: 0
}
)
@@ -64,20 +65,20 @@ module BruteForce
if response.body =~ /login_error/i
puts "\nIncorrect username and/or password." if @verbose
elsif response.code == 302
puts "\n " + green("[SUCCESS]") + " Username : #{username} Password : #{password}\n" if show_progression
found << { :name => username, :password => password }
puts "\n " + green('[SUCCESS]') + " Username : #{username} Password : #{password}\n" if show_progression
found << { name: username, password: password }
password_found = true
elsif response.timed_out?
puts red("ERROR:") + " Request timed out." if show_progression
puts red('ERROR:') + ' Request timed out.' if show_progression
elsif response.code == 0
puts red("ERROR:") + " No response from remote server. WAF/IPS?" if show_progression
puts red('ERROR:') + ' No response from remote server. WAF/IPS?' if show_progression
# code is a fixnum, needs a string for regex
elsif response.code.to_s =~ /^50/
puts red("ERROR:") + " Server error, try reducing the number of threads." if show_progression
puts red('ERROR:') + ' Server error, try reducing the number of threads.' if show_progression
else
puts "\n" + red("ERROR:") + " We recieved an unknown response for #{password}..." if show_progression
puts "\n" + red('ERROR:') + " We recieved an unknown response for #{password}..." if show_progression
# ugly method to get the coverage :/ (otherwise some output is present in the rspec)
# HACK to get the coverage :/ (otherwise some output is present in the rspec)
puts red("Code: #{response.code.to_s}") if @verbose
puts red("Body: #{response.body}") if @verbose
puts if @verbose
@@ -116,7 +117,7 @@ module BruteForce
# wordlists, although bareable.
def self.lines_in_file(file_path)
lines = 0
File.open(file_path, 'r').each { || lines += 1 }
File.open(file_path, 'r').each { |_| lines += 1 }
lines
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -17,7 +18,10 @@
#++
module Malwares
# Used as cache : nil => malwares not checked, [] => no malwares, otherwise array of malwares url found
# Used as cache :
# nil => malwares not checked,
# [] => no malwares,
# otherwise array of malwares url found
@malwares = nil
def has_malwares?(malwares_file_path = nil)

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -34,7 +35,7 @@ module WebSite
response = Browser.instance.get(
login_url(),
{:follow_location => true, :max_redirects => 2}
{ follow_location: true, max_redirects: 2 }
)
if response.body =~ %r{WordPress}i
@@ -42,7 +43,7 @@ module WebSite
else
response = Browser.instance.get(
xml_rpc_url,
{:follow_location => true, :max_redirects => 2}
{ follow_location: true, max_redirects: 2 }
)
if response.body =~ %r{XML-RPC server accepts POST requests only}i
@@ -60,7 +61,7 @@ module WebSite
def xml_rpc_url
unless @xmlrpc_url
headers = Browser.instance.get(@uri.to_s).headers_hash
value = headers["x-pingback"]
value = headers['x-pingback']
if value.nil? or value.empty?
@xmlrpc_url = nil
else
@@ -105,7 +106,7 @@ module WebSite
# Return the MD5 hash of a 404 page
def error_404_hash
unless @error_404_hash
non_existant_page = Digest::MD5.hexdigest(rand(9999999999).to_s) + ".html"
non_existant_page = Digest::MD5.hexdigest(rand(999_999_999).to_s) + '.html'
@error_404_hash = WebSite.page_hash(@uri.merge(non_existant_page).to_s)
end
@error_404_hash

View File

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

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -25,6 +26,6 @@ module WpFullPathDisclosure
end
def full_path_disclosure_url
@uri.merge("wp-includes/rss-functions.php").to_s
@uri.merge('wp-includes/rss-functions.php').to_s
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -37,10 +38,10 @@ module WpLoginProtection
plugin_name = symbol_to_call[LOGIN_PROTECTION_METHOD_PATTERN, 1].gsub('_', '-')
return @login_protection_plugin = WpPlugin.new(
:name => plugin_name,
:base_url => @uri,
:path => "/plugins/#{plugin_name}/",
:wp_content_dir => @wp_content_dir
name: plugin_name,
base_url: @uri,
path: "/plugins/#{plugin_name}/",
wp_content_dir: @wp_content_dir
)
end
end
@@ -67,10 +68,10 @@ module WpLoginProtection
end
def better_wp_security_url
WpPlugin.new(:wp_content_dir => @wp_content_dir,
:base_url => @uri,
:path => "/plugins/better-wp-security/",
:name => "better-wp-security"
WpPlugin.new(wp_content_dir: @wp_content_dir,
base_url: @uri,
path: '/plugins/better-wp-security/',
name: 'better-wp-security'
).get_url_without_filename
end
@@ -80,10 +81,10 @@ module WpLoginProtection
end
def simple_login_lockdown_url
WpPlugin.new(:wp_content_dir => @wp_content_dir,
:base_url => @uri,
:path => "/plugins/simple-login-lockdown/",
:name => "simple-login-lockdown"
WpPlugin.new(wp_content_dir: @wp_content_dir,
base_url: @uri,
path: '/plugins/simple-login-lockdown/',
name: 'simple-login-lockdown'
).get_url_without_filename
end
@@ -93,10 +94,10 @@ module WpLoginProtection
end
def login_security_solution_url
WpPlugin.new(:wp_content_dir => @wp_content_dir,
:base_url => @uri,
:path => "/plugins/login-security-solution/",
:name => "login-security-solution"
WpPlugin.new(wp_content_dir: @wp_content_dir,
base_url: @uri,
path: '/plugins/login-security-solution/',
name: 'login-security-solution'
).get_url_without_filename
end
@@ -106,10 +107,10 @@ module WpLoginProtection
end
def limit_login_attempts_url
WpPlugin.new(:wp_content_dir => @wp_content_dir,
:base_url => @uri,
:path => "/plugins/limit-login-attempts/",
:name => "limit-login-attempts"
WpPlugin.new(wp_content_dir: @wp_content_dir,
base_url: @uri,
path: '/plugins/limit-login-attempts/',
name: 'limit-login-attempts'
).get_url_without_filename
end
@@ -119,10 +120,10 @@ module WpLoginProtection
end
def bluetrait_event_viewer_url
WpPlugin.new(:wp_content_dir => @wp_content_dir,
:base_url => @uri,
:path => "/plugins/bluetrait-event-viewer/",
:name => "bluetrait-event-viewer"
WpPlugin.new(wp_content_dir: @wp_content_dir,
base_url: @uri,
path: '/plugins/bluetrait-event-viewer/',
name: 'bluetrait-event-viewer'
).get_url_without_filename
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -22,22 +23,24 @@ module WpPlugins
#
# return array of WpPlugin
def plugins_from_aggressive_detection(options)
if options[:vulns_file].nil? or options[:vulns_file] == ''
options[:vulns_file] = PLUGINS_VULNS_FILE
end
options[:file] = options[:file] || (options[:full] ? PLUGINS_FULL_FILE : PLUGINS_FILE)
options[:vulns_file] = (options[:vulns_file] != nil and options[:vulns_file] != "") ?
options[:vulns_file] : PLUGINS_VULNS_FILE
options[:vulns_xpath] = "//plugin[@name='#{@name}']/vulnerability"
options[:vulns_xpath_2] = "//plugin"
options[:type] = "plugins"
options[:vulns_xpath_2] = '//plugin'
options[:type] = 'plugins'
result = WpDetector.aggressive_detection(options)
plugins = []
result.each do |r|
plugins << WpPlugin.new(
:base_url => r.base_url,
:path => r.path,
:wp_content_dir => r.wp_content_dir,
:name => r.name,
:type => "plugins",
:wp_plugins_dir => r.wp_plugins_dir
base_url: r.base_url,
path: r.path,
wp_content_dir: r.wp_content_dir,
name: r.name,
type: 'plugins',
wp_plugins_dir: r.wp_plugins_dir
)
end
plugins.sort_by { |p| p.name }
@@ -51,16 +54,16 @@ module WpPlugins
# return array of WpPlugin
def plugins_from_passive_detection(options)
plugins = []
temp = WpDetector.passive_detection(options[:base_url], "plugins", options[:wp_content_dir])
temp = WpDetector.passive_detection(options[:base_url], 'plugins', options[:wp_content_dir])
temp.each do |item|
plugins << WpPlugin.new(
:base_url => item.base_url,
:name => item.name,
:path => item.path,
:wp_content_dir => options[:wp_content_dir],
:type => "plugins",
:wp_plugins_dir => options[:wp_plugins_dir]
base_url: item.base_url,
name: item.name,
path: item.path,
wp_content_dir: options[:wp_content_dir],
type: 'plugins',
wp_plugins_dir: options[:wp_plugins_dir]
)
end
plugins.sort_by { |p| p.name }

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -31,6 +32,6 @@ module WpReadme
end
def readme_url
@uri.merge("readme.html").to_s
@uri.merge('readme.html').to_s
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -19,20 +20,22 @@
module WpThemes
def themes_from_aggressive_detection(options)
if options[:vulns_file].nil? or options[:vulns_file] == ''
options[:vulns_file] = THEMES_VULNS_FILE
end
options[:file] = options[:file] || (options[:full] ? THEMES_FULL_FILE : THEMES_FILE)
options[:vulns_file] = (options[:vulns_file] != nil and options[:vulns_file] != "") ?
options[:vulns_file] : THEMES_VULNS_FILE
options[:vulns_xpath] = "//theme[@name='#{@name}']/vulnerability"
options[:vulns_xpath_2] = "//theme"
options[:type] = "themes"
options[:vulns_xpath_2] = '//theme'
options[:type] = 'themes'
result = WpDetector.aggressive_detection(options)
themes = []
result.each do |r|
themes << WpTheme.new(
:base_url => r.base_url,
:path => r.path,
:wp_content_dir => r.wp_content_dir,
:name => r.name
base_url: r.base_url,
path: r.path,
wp_content_dir: r.wp_content_dir,
name: r.name
)
end
themes.sort_by { |t| t.name }
@@ -40,14 +43,14 @@ module WpThemes
def themes_from_passive_detection(options)
themes = []
temp = WpDetector.passive_detection(options[:base_url], "themes", options[:wp_content_dir])
temp = WpDetector.passive_detection(options[:base_url], 'themes', options[:wp_content_dir])
temp.each do |item|
themes << WpTheme.new(
:base_url => item.base_url,
:name => item.name,
:path => item.path,
:wp_content_dir => options[:wp_content_dir]
base_url: item.base_url,
name: item.name,
path: item.path,
wp_content_dir: options[:wp_content_dir]
)
end
themes.sort_by { |t| t.name }

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -18,7 +19,10 @@
module WpTimthumbs
# Used as cache : nil => timthumbs not checked, [] => no timthumbs, otherwise array of timthumbs url found
# Used as cache :
# nil => timthumbs not checked,
# [] => no timthumbs,
# otherwise array of timthumbs url found
@wp_timthumbs = nil
def has_timthumbs?(theme_name, options = {})
@@ -27,12 +31,12 @@ module WpTimthumbs
def timthumbs(theme_name = nil, options = {})
if @wp_timthumbs.nil?
options[:type] = "timthumbs"
options[:type] = 'timthumbs'
options[:only_vulnerable_ones] = false
options[:file] = options[:file] || DATA_DIR + "/timthumbs.txt"
options[:vulns_file] = "xxx"
options[:vulns_xpath] = "xxx"
options[:vulns_xpath_2] = "xxx"
options[:file] = options[:file] || DATA_DIR + '/timthumbs.txt'
options[:vulns_file] = 'xxx'
options[:vulns_xpath] = 'xxx'
options[:vulns_xpath_2] = 'xxx'
WpOptions.check_options(options)
if theme_name == nil
@@ -55,13 +59,13 @@ module WpTimthumbs
scripts/timthumb.php tools/timthumb.php functions/timthumb.php
}.each do |file|
targets << WpItem.new(
:base_url => options[:base_url],
:path => "themes/#{theme_name}/#{file}",
:wp_content_dir => options[:wp_content_dir],
:name => theme_name,
:vulns_file => "XX",
:type => "timthumbs",
:wp_plugins_dir => options[:wp_plugins_dir]
base_url: options[:base_url],
path: "themes/#{theme_name}/#{file}",
wp_content_dir: options[:wp_content_dir],
name: theme_name,
vulns_file: 'XX',
type: 'timthumbs',
wp_plugins_dir: options[:wp_plugins_dir]
)
end
targets

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -58,7 +59,7 @@ module WpUsernames
end
def get_nickname_from_url(url)
resp = Browser.instance.get(url, {:follow_location => true, :max_redirects => 2})
resp = Browser.instance.get(url, { follow_location: true, max_redirects: 2 })
nickname = nil
if resp.code == 200
nickname = extract_nickname_from_body(resp.body)
@@ -80,21 +81,21 @@ module WpUsernames
def remove_junk_from_nickname(usernames)
unless usernames.kind_of? Array
raise("Need an array as input")
raise('Need an array as input')
end
nicknames = []
usernames.each do |u|
unless u.kind_of? WpUser
raise("Items must be of type WpUser")
raise('Items must be of type WpUser')
end
nickname = u.nickname
unless nickname == "empty"
unless nickname == 'empty'
nicknames << nickname
end
end
junk = get_equal_string_end(nicknames)
usernames.each do |u|
u.nickname = u.nickname.sub(/#{Regexp.escape(junk)}$/, "")
u.nickname = u.nickname.sub(/#{Regexp.escape(junk)}$/, '')
end
usernames
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -30,10 +31,10 @@ class Vulnerable
xml.xpath(@vulns_xpath).each do |node|
vulnerabilities << WpVulnerability.new(
node.search("title").text,
node.search("reference").map(&:text),
node.search("type").text,
node.search("metasploit").map(&:text)
node.search('title').text,
node.search('reference').map(&:text),
node.search('type').text,
node.search('metasploit').map(&:text)
)
end
vulnerabilities

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -63,12 +64,12 @@ class WpDetector
names.each do |item|
items << WpItem.new(
:base_url => url,
:name => item,
:type => type,
:path => "#{item}/",
:wp_content_dir => wp_content_dir,
:vulns_file => ""
base_url: url,
name: item,
type: type,
path: "#{item}/",
wp_content_dir: wp_content_dir,
vulns_file: ''
)
end
items

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -54,7 +55,7 @@ class WpEnumerator
targets.each do |target|
url = target.get_full_url
request = enum_browser.forge_request(url, { :cache_timeout => 0, :follow_location => true })
request = enum_browser.forge_request(url, { cache_timeout: 0, follow_location: true })
request_count += 1
request.on_complete do |response|
@@ -102,17 +103,17 @@ class WpEnumerator
unless only_vulnerable
# Open and parse the 'most popular' plugin list...
File.open(file, "r") do |f|
File.open(file, 'r') do |f|
f.readlines.collect do |line|
l = line.strip
targets_url << WpItem.new(
:base_url => url,
:path => l,
:wp_content_dir => wp_content_dir,
:name => l =~ /.+\/.+/ ? File.dirname(l) : l.sub(/\/$/, ""),
:vulns_file => vulns_file,
:type => type,
:wp_plugins_dir => plugins_dir
base_url: url,
path: l,
wp_content_dir: wp_content_dir,
name: l =~ /.+\/.+/ ? File.dirname(l) : l.sub(/\/$/, ''),
vulns_file: vulns_file,
type: type,
wp_plugins_dir: plugins_dir
)
end
end
@@ -126,15 +127,15 @@ class WpEnumerator
# We check if the plugin name from the plugin_vulns_file is already in targets, otherwise we add it
xml.xpath(options[:vulns_xpath_2]).each do |node|
name = node.attribute("name").text
name = node.attribute('name').text
targets_url << WpItem.new(
:base_url => url,
:path => name,
:wp_content_dir => wp_content_dir,
:name => name,
:vulns_file => vulns_file,
:type => type,
:wp_plugins_dir => plugins_dir
base_url: url,
path: name,
wp_content_dir: wp_content_dir,
name: name,
vulns_file: vulns_file,
type: type,
wp_plugins_dir: plugins_dir
)
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -24,7 +25,7 @@ class WpItem < Vulnerable
def initialize(options)
@type = options[:type]
@wp_content_dir = options[:wp_content_dir] ? options[:wp_content_dir].sub(/^\//, "").sub(/\/$/, "") : "wp-content"
@wp_content_dir = options[:wp_content_dir] ? options[:wp_content_dir].sub(/^\//, '').sub(/\/$/, '') : 'wp-content'
@wp_plugins_dir = options[:wp_plugins_dir] || "#@wp_content_dir/plugins"
@base_url = options[:base_url]
@path = options[:path]
@@ -32,36 +33,36 @@ class WpItem < Vulnerable
@vulns_file = options[:vulns_file]
@vulns_xpath = options[:vulns_xpath].sub(/\$name\$/, @name) unless options[:vulns_xpath] == nil
raise("base_url not set") unless @base_url
raise("path not set") unless @path
raise("wp_content_dir not set") unless @wp_content_dir
raise("name not set") unless @name
raise("vulns_file not set") unless @vulns_file
raise("type not set") unless @type
raise('base_url not set') unless @base_url
raise('path not set') unless @path
raise('wp_content_dir not set') unless @wp_content_dir
raise('name not set') unless @name
raise('vulns_file not set') unless @vulns_file
raise('type not set') unless @type
end
# The wordpress.org plugins directory URL
# See: https://github.com/wpscanteam/wpscan/issues/100
def wp_org_url
case @type
when "themes"
return URI("http://wordpress.org/extend/themes/").merge("#@name/")
when "plugins"
return URI("http://wordpress.org/extend/plugins/").merge("#@name/")
else
raise("No Wordpress URL for #@type")
when 'themes'
return URI('http://wordpress.org/extend/themes/').merge("#@name/")
when 'plugins'
return URI('http://wordpress.org/extend/plugins/').merge("#@name/")
else
raise("No Wordpress URL for #@type")
end
end
# returns true if this theme or plugin is hosted on wordpress.org
def wp_org_item?
case @type
when "themes"
file = THEMES_FULL_FILE
when "plugins"
file = PLUGINS_FULL_FILE
else
raise("Unknown type #@type")
when 'themes'
file = THEMES_FULL_FILE
when 'plugins'
file = PLUGINS_FULL_FILE
else
raise("Unknown type #@type")
end
f = File.readlines(file).grep(/^#{Regexp.escape(@name)}$/i)
f.empty? ? false : true
@@ -69,28 +70,28 @@ class WpItem < Vulnerable
def get_sub_folder
case @type
when "themes"
folder = "themes"
when "timthumbs"
# not needed
folder = nil
else
raise("unknown type #@type")
when 'themes'
folder = 'themes'
when 'timthumbs'
# not needed
folder = nil
else
raise("unknown type #@type")
end
folder
end
# Get the full url for this item
def get_full_url
url = @base_url.to_s.end_with?("/") ? @base_url.to_s : "#@base_url/"
url = @base_url.to_s.end_with?('/') ? @base_url.to_s : "#@base_url/"
# remove first and last /
wp_content_dir = @wp_content_dir.sub(/^\//, "").sub(/\/$/, "")
wp_content_dir = @wp_content_dir.sub(/^\//, "").sub(/\/$/, '')
# remove first /
path = @path.sub(/^\//, "")
if type =="plugins"
path = @path.sub(/^\//, '')
if type == 'plugins'
# plugins can be outside of wp-content. wp_content_dir included in wp_plugins_dir
ret = URI.parse(URI.encode("#{url}#@wp_plugins_dir/#{path}"))
elsif type == "timthumbs"
elsif type == 'timthumbs'
# timthumbs have folder in path variable
ret = URI.parse(URI.encode("#{url}#{wp_content_dir}/#{path}"))
else
@@ -112,7 +113,7 @@ class WpItem < Vulnerable
# Returns version number from readme.txt if it exists
def version
unless @version
response = Browser.instance.get(get_full_url.merge("readme.txt").to_s)
response = Browser.instance.get(get_full_url.merge('readme.txt').to_s)
@version = response.body[%r{stable tag: #{WpVersion.version_pattern}}i, 1]
end
@version
@@ -152,12 +153,12 @@ class WpItem < Vulnerable
# Url for readme.txt
def readme_url
get_url_without_filename.merge("readme.txt")
get_url_without_filename.merge('readme.txt')
end
# Url for changelog.txt
def changelog_url
get_url_without_filename.merge("changelog.txt")
get_url_without_filename.merge('changelog.txt')
end
# readme.txt present?

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -32,16 +33,16 @@
# * +type+ - Type: plugins, themes
class WpOptions
def self.check_options(options)
raise("base_url must be set") unless options[:base_url] != nil and options[:base_url].to_s.length > 0
raise("only_vulnerable_ones must be set") unless options[:only_vulnerable_ones] != nil
raise("file must be set") unless options[:file] != nil and options[:file].length > 0
raise("vulns_file must be set") unless options[:vulns_file] != nil and options[:vulns_file].length > 0
raise("vulns_xpath must be set") unless options[:vulns_xpath] != nil and options[:vulns_xpath].length > 0
raise("vulns_xpath_2 must be set") unless options[:vulns_xpath_2] != nil and options[:vulns_xpath_2].length > 0
raise("wp_content_dir must be set") unless options[:wp_content_dir] != nil and options[:wp_content_dir].length > 0
raise("show_progression must be set") unless options[:show_progression] != nil
raise("error_404_hash must be set") unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0
raise("type must be set") unless options[:type] != nil and options[:type].length > 0
raise('base_url must be set') unless options[:base_url] != nil and options[:base_url].to_s.length > 0
raise('only_vulnerable_ones must be set') unless options[:only_vulnerable_ones] != nil
raise('file must be set') unless options[:file] != nil and options[:file].length > 0
raise('vulns_file must be set') unless options[:vulns_file] != nil and options[:vulns_file].length > 0
raise('vulns_xpath must be set') unless options[:vulns_xpath] != nil and options[:vulns_xpath].length > 0
raise('vulns_xpath_2 must be set') unless options[:vulns_xpath_2] != nil and options[:vulns_xpath_2].length > 0
raise('wp_content_dir must be set') unless options[:wp_content_dir] != nil and options[:wp_content_dir].length > 0
raise('show_progression must be set') unless options[:show_progression] != nil
raise('error_404_hash must be set') unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0
raise('type must be set') unless options[:type] != nil and options[:type].length > 0
unless options[:type] =~ /plugins/i or options[:type] =~ /themes/i or options[:type] =~ /timthumbs/i
raise("Unknown type #{options[:type]}")

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -18,11 +19,14 @@
class WpPlugin < WpItem
def initialize(options = {})
options[:vulns_file] = (options[:vulns_file] != nil and options[:vulns_file] != "") ?
options[:vulns_file] : PLUGINS_VULNS_FILE
if options[:vulns_file].nil? or options[:vulns_file] == ''
options[:vulns_file] = PLUGINS_VULNS_FILE
end
options[:vulns_xpath] = "//plugin[@name='$name$']/vulnerability"
options[:vulns_xpath_2] = "//plugin"
options[:type] = "plugins"
options[:vulns_xpath_2] = '//plugin'
options[:type] = 'plugins'
super(options)
end
@@ -32,11 +36,11 @@ class WpPlugin < WpItem
# however can also be found in their specific plugin dir.
# http://www.exploit-db.com/ghdb/3714/
def error_log?
response_body = Browser.instance.get(error_log_url(), :headers => {"range" => "bytes=0-700"}).body
response_body = Browser.instance.get(error_log_url(), headers: {'range' => 'bytes=0-700'}).body
response_body[%r{PHP Fatal error}i] ? true : false
end
def error_log_url
get_full_url.merge("error_log").to_s
get_full_url.merge('error_log').to_s
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -47,7 +48,7 @@ class WpTarget
end
def login_url
url = @uri.merge("wp-login.php").to_s
url = @uri.merge('wp-login.php').to_s
# Let's check if the login url is redirected (to https url for example)
redirection = redirection(url)
@@ -80,9 +81,9 @@ class WpTarget
uri_path = @uri.path
if index_body[/\/wp-content\/(?:themes|plugins)\//i]
@wp_content_dir = "wp-content"
@wp_content_dir = 'wp-content'
else
domains_excluded = "(?:www\.)?(facebook|twitter)\.com"
domains_excluded = '(?:www\.)?(facebook|twitter)\.com'
@wp_content_dir = index_body[/(?:href|src)\s*=\s*(?:"|').+#{Regexp.escape(uri_path)}((?!#{domains_excluded})[^"']+)\/(?:themes|plugins)\/.*(?:"|')/i, 1]
end
end
@@ -102,7 +103,7 @@ class WpTarget
def has_debug_log?
# We only get the first 700 bytes of the file to avoid loading huge file (like 2Go)
response_body = Browser.instance.get(debug_log_url(), :headers => {"range" => "bytes=0-700"}).body
response_body = Browser.instance.get(debug_log_url(), headers: {'range' => 'bytes=0-700'}).body
response_body[%r{\[[^\]]+\] PHP (?:Warning|Error|Notice):}] ? true : false
end
@@ -114,7 +115,7 @@ class WpTarget
# reveals databse credentials after hitting submit
# http://interconnectit.com/124/search-and-replace-for-wordpress-databases/
def search_replace_db_2_url
@uri.merge("searchreplacedb2.php").to_s
@uri.merge('searchreplacedb2.php').to_s
end
def search_replace_db_2_exists?
@@ -126,7 +127,7 @@ class WpTarget
def registration_enabled?
resp = Browser.instance.get(registration_url)
# redirect only on non multi sites
if resp.code == 302 and resp.headers_hash["location"] =~ /wp-login\.php\?registration=disabled/i
if resp.code == 302 and resp.headers_hash['location'] =~ /wp-login\.php\?registration=disabled/i
enabled = false
# multi site registration form
elsif resp.code == 200 and resp.body =~ /<form id="setupform" method="post" action="[^"]*wp-signup\.php[^"]*">/i
@@ -142,18 +143,18 @@ class WpTarget
end
def registration_url
is_multisite? ? @uri.merge("wp-signup.php") : @uri.merge("wp-login.php?action=register")
is_multisite? ? @uri.merge('wp-signup.php') : @uri.merge('wp-login.php?action=register')
end
def is_multisite?
unless @multisite
# when multi site, there is no redirection or a redirect to the site itself
# otherwise redirect to wp-login.php
url = @uri.merge("wp-signup.php")
url = @uri.merge('wp-signup.php')
resp = Browser.instance.get(url)
if resp.code == 302 and resp.headers_hash["location"] =~ /wp-login\.php\?action=register/
if resp.code == 302 and resp.headers_hash['location'] =~ /wp-login\.php\?action=register/
@multisite = false
elsif resp.code == 302 and resp.headers_hash["location"] =~ /wp-signup\.php/
elsif resp.code == 302 and resp.headers_hash['location'] =~ /wp-signup\.php/
@multisite = true
elsif resp.code == 200
@multisite = true

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -23,12 +24,15 @@ class WpTheme < WpItem
attr_reader :style_url, :version
def initialize(options = {})
options[:vulns_file] = (options[:vulns_file] != nil and options[:vulns_file] != "") ?
options[:vulns_file] : THEMES_VULNS_FILE
if options[:vulns_file].nil? or options[:vulns_file] == ''
options[:vulns_file] = THEMES_VULNS_FILE
end
options[:vulns_xpath] = "//theme[@name='$name$']/vulnerability"
options[:type] = "themes"
options[:type] = 'themes'
@version = options[:version]
@style_url = options[:style_url]
super(options)
end
@@ -58,7 +62,7 @@ class WpTheme < WpItem
# Discover the wordpress theme name by parsing the css link rel
def self.find_from_css_link(target_uri)
response = Browser.instance.get(target_uri.to_s, {:follow_location => true, :max_redirects => 2})
response = Browser.instance.get(target_uri.to_s, { follow_location: true, max_redirects: 2 })
matches = %r{https?://[^"']+/([^/]+)/themes/([^"']+)/style.css}i.match(response.body)
if matches
@@ -66,11 +70,12 @@ class WpTheme < WpItem
wp_content_dir = matches[1]
theme_name = matches[2]
return new(:name => theme_name,
:style_url => style_url,
:base_url => target_uri,
:path => theme_name,
:wp_content_dir => wp_content_dir
return new(
name: theme_name,
style_url: style_url,
base_url: target_uri,
path: theme_name,
wp_content_dir: wp_content_dir
)
end
end
@@ -86,11 +91,12 @@ class WpTheme < WpItem
woo_theme_version = matches[2]
woo_framework_version = matches[3] # Not used at this time
return new(:name => woo_theme_name,
:version => woo_theme_version,
:base_url => matches[0],
:path => "",
:wp_content_dir => ""
return new(
name: woo_theme_name,
version: woo_theme_version,
base_url: matches[0],
path: '',
wp_content_dir: ''
)
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -20,7 +21,7 @@ class WpUser
def name
if @name.nil? or @name.to_s.strip.empty?
return "empty"
return 'empty'
end
@name
end
@@ -31,7 +32,7 @@ class WpUser
def id
if @id.nil? or @id.to_s.strip.empty?
return "empty"
return 'empty'
end
@id
end
@@ -42,7 +43,7 @@ class WpUser
def nickname
if @nickname.nil? or @nickname.to_s.strip.empty?
return "empty"
return 'empty'
end
@nickname
end
@@ -57,15 +58,15 @@ class WpUser
self.nickname = nickname
end
def <=>(item)
item.name <=> self.name
def <=>(other)
other.name <=> self.name
end
def ===(item)
item.name === self.name and item.id === self.id and item.nickname === self.nickname
def ===(other)
other.name === self.name and other.id === self.id and other.nickname === self.nickname
end
def eql?(item)
item.name === self.name and item.id === self.id and item.nickname === self.nickname
def eql?(other)
other.name === self.name and other.id === self.id and other.nickname === self.nickname
end
end
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -38,14 +39,14 @@ class WpVersion < Vulnerable
# (find_from_meta_generator, find_from_rss_generator etc)
def self.find(target_uri, wp_content_dir)
options = {
:base_url => target_uri,
:wp_content_dir => wp_content_dir
base_url: target_uri,
wp_content_dir: wp_content_dir
}
self.methods.grep(/find_from_/).each do |method_to_call|
version = self.send(method_to_call, options)
if version
return new(version, :discovery_method => method_to_call[%r{find_from_(.*)}, 1].gsub('_', ' '))
return new(version, discovery_method: method_to_call[%r{find_from_(.*)}, 1].gsub('_', ' '))
end
end
nil
@@ -60,7 +61,7 @@ class WpVersion < Vulnerable
# that it is reinstated on upgrade.
def self.find_from_meta_generator(options)
target_uri = options[:base_url]
response = Browser.instance.get(target_uri.to_s, {:follow_location => true, :max_redirects => 2})
response = Browser.instance.get(target_uri.to_s, { follow_location: true, max_redirects: 2 })
response.body[%r{name="generator" content="wordpress #{WpVersion.version_pattern}"}i, 1]
end
@@ -69,7 +70,7 @@ class WpVersion < Vulnerable
# the generator tag in the RSS feed source.
def self.find_from_rss_generator(options)
target_uri = options[:base_url]
response = Browser.instance.get(target_uri.merge("feed/").to_s, {:follow_location => true, :max_redirects => 2})
response = Browser.instance.get(target_uri.merge('feed/').to_s, { follow_location: true, max_redirects: 2 })
response.body[%r{<generator>http://wordpress.org/\?v=#{WpVersion.version_pattern}</generator>}i, 1]
end
@@ -78,7 +79,7 @@ class WpVersion < Vulnerable
# the generator tag in the RDF feed source.
def self.find_from_rdf_generator(options)
target_uri = options[:base_url]
response = Browser.instance.get(target_uri.merge("feed/rdf/").to_s, {:follow_location => true, :max_redirects => 2})
response = Browser.instance.get(target_uri.merge('feed/rdf/').to_s, { follow_location: true, max_redirects: 2 })
response.body[%r{<admin:generatorAgent rdf:resource="http://wordpress.org/\?v=#{WpVersion.version_pattern}" />}i, 1]
end
@@ -89,7 +90,7 @@ class WpVersion < Vulnerable
# Have not been able to find an example of this - Ryan
#def self.find_from_rss2_generator(options)
# target_uri = options[:base_url]
# response = Browser.instance.get(target_uri.merge("feed/rss/").to_s, {:follow_location => true, :max_redirects => 2})
# response = Browser.instance.get(target_uri.merge('feed/rss/').to_s, {:follow_location => true, :max_redirects => 2})
#
# response.body[%r{<generator>http://wordpress.org/?v=(#{WpVersion.version_pattern})</generator>}i, 1]
#end
@@ -98,7 +99,7 @@ class WpVersion < Vulnerable
# the generator tag in the Atom source.
def self.find_from_atom_generator(options)
target_uri = options[:base_url]
response = Browser.instance.get(target_uri.merge("feed/atom/").to_s, {:follow_location => true, :max_redirects => 2})
response = Browser.instance.get(target_uri.merge('feed/atom/').to_s, { follow_location: true, max_redirects: 2 })
response.body[%r{<generator uri="http://wordpress.org/" version="#{WpVersion.version_pattern}">WordPress</generator>}i, 1]
end
@@ -109,7 +110,7 @@ class WpVersion < Vulnerable
# Have not been able to find an example of this - Ryan
#def self.find_from_comments_rss_generator(options)
# target_uri = options[:base_url]
# response = Browser.instance.get(target_uri.merge("comments/feed/").to_s, {:follow_location => true, :max_redirects => 2})
# response = Browser.instance.get(target_uri.merge('comments/feed/').to_s, {:follow_location => true, :max_redirects => 2})
#
# response.body[%r{<!-- generator="WordPress/#{WpVersion.version_pattern}" -->}i, 1]
#end
@@ -129,7 +130,7 @@ class WpVersion < Vulnerable
config.noblanks
end
xml.xpath("//file").each do |node|
xml.xpath('//file').each do |node|
wp_content = options[:wp_content_dir]
wp_plugins = "#{wp_content}/plugins"
file_url = target_uri.merge(node.attribute('src').text).to_s
@@ -149,7 +150,7 @@ class WpVersion < Vulnerable
# Attempts to find the WordPress version from the readme.html file.
def self.find_from_readme(options)
target_uri = options[:base_url]
Browser.instance.get(target_uri.merge("readme.html").to_s).body[%r{<br />\sversion #{WpVersion.version_pattern}}i, 1]
Browser.instance.get(target_uri.merge('readme.html').to_s).body[%r{<br />\sversion #{WpVersion.version_pattern}}i, 1]
end
# Attempts to find the WordPress version from the sitemap.xml file.
@@ -157,13 +158,13 @@ class WpVersion < Vulnerable
# See: http://code.google.com/p/wpscan/issues/detail?id=109
def self.find_from_sitemap_generator(options)
target_uri = options[:base_url]
Browser.instance.get(target_uri.merge("sitemap.xml").to_s).body[%r{generator="wordpress/#{WpVersion.version_pattern}"}i, 1]
Browser.instance.get(target_uri.merge('sitemap.xml').to_s).body[%r{generator="wordpress/#{WpVersion.version_pattern}"}i, 1]
end
# Attempts to find the WordPress version from the p-links-opml.php file.
def self.find_from_links_opml(options)
target_uri = options[:base_url]
Browser.instance.get(target_uri.merge("wp-links-opml.php").to_s).body[%r{generator="wordpress/#{WpVersion.version_pattern}"}i, 1]
Browser.instance.get(target_uri.merge('wp-links-opml.php').to_s).body[%r{generator="wordpress/#{WpVersion.version_pattern}"}i, 1]
end
# Used to check if the version is correct: must contain at least one dot.

View File

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

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -18,95 +19,95 @@
require File.expand_path(File.dirname(__FILE__) + '/../common_helper')
require_files_from_directory(WPSCAN_LIB_DIR, "**/*.rb")
require_files_from_directory(WPSCAN_LIB_DIR, '**/*.rb')
# wpscan usage
def usage()
def usage
script_name = $0
puts
puts "Examples :"
puts 'Examples :'
puts
puts "-Further help ..."
puts '-Further help ...'
puts "ruby #{script_name} --help"
puts
puts "-Do 'non-intrusive' checks ..."
puts "ruby #{script_name} --url www.example.com"
puts
puts "-Do wordlist password brute force on enumerated users using 50 threads ..."
puts '-Do wordlist password brute force on enumerated users using 50 threads ...'
puts "ruby #{script_name} --url www.example.com --wordlist darkc0de.lst --threads 50"
puts
puts "-Do wordlist password brute force on the 'admin' username only ..."
puts "ruby #{script_name} --url www.example.com --wordlist darkc0de.lst --username admin"
puts
puts "-Enumerate installed plugins ..."
puts '-Enumerate installed plugins ...'
puts "ruby #{script_name} --url www.example.com --enumerate p"
puts
puts "-Enumerate installed themes ..."
puts '-Enumerate installed themes ...'
puts "ruby #{script_name} --url www.example.com --enumerate t"
puts
puts "-Enumerate users ..."
puts '-Enumerate users ...'
puts "ruby #{script_name} --url www.example.com --enumerate u"
puts
puts "-Enumerate installed timthumbs ..."
puts '-Enumerate installed timthumbs ...'
puts "ruby #{script_name} --url www.example.com --enumerate tt"
puts
puts "-Use a HTTP proxy ..."
puts '-Use a HTTP proxy ...'
puts "ruby #{script_name} --url www.example.com --proxy 127.0.0.1:8118"
puts
puts "-Use a SOCKS5 proxy ... (cURL >= v7.21.7 needed)"
puts '-Use a SOCKS5 proxy ... (cURL >= v7.21.7 needed)'
puts "ruby #{script_name} --url www.example.com --proxy socks5://127.0.0.1:9000"
puts
puts "-Use custom content directory ..."
puts '-Use custom content directory ...'
puts "ruby #{script_name} -u www.example.com --wp-content-dir custom-content"
puts
puts "-Use custom plugins directory ..."
puts '-Use custom plugins directory ...'
puts "ruby #{script_name} -u www.example.com --wp-plugins-dir wp-content/custom-plugins"
puts
puts "-Update ..."
puts '-Update ...'
puts "ruby #{script_name} --update"
puts
puts "See README for further information."
puts 'See README for further information.'
puts
end
# command help
def help()
puts "Help :"
def help
puts 'Help :'
puts
puts "Some values are settable in conf/browser.conf.json :"
puts " user-agent, proxy, proxy-auth, threads, cache timeout and request timeout"
puts 'Some values are settable in conf/browser.conf.json :'
puts ' user-agent, proxy, proxy-auth, threads, cache timeout and request timeout'
puts
puts "--update Update to the latest revision"
puts "--url | -u <target url> The WordPress URL/domain to scan."
puts "--force | -f Forces WPScan to not check if the remote site is running WordPress."
puts "--enumerate | -e [option(s)] Enumeration."
puts " option :"
puts " u usernames from id 1 to 10"
puts " u[10-20] usernames from id 10 to 20 (you must write [] chars)"
puts " p plugins"
puts " vp only vulnerable plugins"
puts " ap all plugins (can take a long time)"
puts " tt timthumbs"
puts " t themes"
puts " vt only vulnerable themes"
puts " at all themes (can take a long time)"
puts " Multiple values are allowed : '-e t,p' will enumerate timthumbs and plugins"
puts " If no option is supplied, the default is 'vt,tt,u,vp'"
puts '--update Update to the latest revision'
puts '--url | -u <target url> The WordPress URL/domain to scan.'
puts '--force | -f Forces WPScan to not check if the remote site is running WordPress.'
puts '--enumerate | -e [option(s)] Enumeration.'
puts ' option :'
puts ' u usernames from id 1 to 10'
puts ' u[10-20] usernames from id 10 to 20 (you must write [] chars)'
puts ' p plugins'
puts ' vp only vulnerable plugins'
puts ' ap all plugins (can take a long time)'
puts ' tt timthumbs'
puts ' t themes'
puts ' vt only vulnerable themes'
puts ' at all themes (can take a long time)'
puts ' Multiple values are allowed : "-e t,p" will enumerate timthumbs and plugins'
puts ' If no option is supplied, the default is "vt,tt,u,vp"'
puts
puts "--exclude-content-based '<regexp or string>' Used with the enumeration option, will exclude all occurence based on the regexp or string supplied"
puts " You do not need to provide the regexp delimiters, but you must write the quotes (simple or double)"
puts "--config-file | -c <config file> Use the specified config file"
puts "--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not"
puts "--wp-content-dir <wp content dir> WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed"
puts "--wp-plugins-dir <wp plugins dir> Same thing than --wp-content-dir but for the plugins directory. If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed"
puts "--proxy <[protocol://]host:port> Supply a proxy (will override the one from conf/browser.conf.json)."
puts " HTTP, SOCKS4 SOCKS4A and SOCKS5 are supported. If no protocol is given (format host:port), HTTP will be used"
puts "--proxy-auth <username:password> Supply the proxy login credentials (will override the one from conf/browser.conf.json)."
puts "--basic-auth <username:password> Set the HTTP Basic authentification"
puts "--wordlist | -w <wordlist> Supply a wordlist for the password bruter and do the brute."
puts "--threads | -t <number of threads> The number of threads to use when multi-threading requests. (will override the value from conf/browser.conf.json)"
puts "--username | -U <username> Only brute force the supplied username."
puts "--help | -h This help screen."
puts "--verbose | -v Verbose output."
puts '--exclude-content-based "<regexp or string>" Used with the enumeration option, will exclude all occurence based on the regexp or string supplied'
puts ' You do not need to provide the regexp delimiters, but you must write the quotes (simple or double)'
puts '--config-file | -c <config file> Use the specified config file'
puts '--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not'
puts '--wp-content-dir <wp content dir> WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed'
puts '--wp-plugins-dir <wp plugins dir> Same thing than --wp-content-dir but for the plugins directory. If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed'
puts '--proxy <[protocol://]host:port> Supply a proxy (will override the one from conf/browser.conf.json).'
puts ' HTTP, SOCKS4 SOCKS4A and SOCKS5 are supported. If no protocol is given (format host:port), HTTP will be used'
puts '--proxy-auth <username:password> Supply the proxy login credentials (will override the one from conf/browser.conf.json).'
puts '--basic-auth <username:password> Set the HTTP Basic authentification'
puts '--wordlist | -w <wordlist> Supply a wordlist for the password bruter and do the brute.'
puts '--threads | -t <number of threads> The number of threads to use when multi-threading requests. (will override the value from conf/browser.conf.json)'
puts '--username | -U <username> Only brute force the supplied username.'
puts '--help | -h This help screen.'
puts '--verbose | -v Verbose output.'
puts
end

View File

@@ -1,3 +1,4 @@
# encoding: UTF-8
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012-2013
@@ -56,7 +57,7 @@ class WpscanOptions
end
def url=(url)
raise "Empty URL given" if !url
raise 'Empty URL given' if !url
@url = URI.parse(add_http_protocol(url)).to_s
end
@@ -75,7 +76,7 @@ class WpscanOptions
def proxy=(proxy)
if proxy.index(':') == nil
raise "Invalid proxy format. Should be host:port."
raise 'Invalid proxy format. Should be host:port.'
else
@proxy = proxy
end
@@ -83,7 +84,7 @@ class WpscanOptions
def proxy_auth=(auth)
if auth.index(':') == nil
raise "Invalid proxy auth format, username:password expected"
raise 'Invalid proxy auth format, username:password expected'
else
@proxy_auth = auth
end
@@ -91,7 +92,7 @@ class WpscanOptions
def enumerate_plugins=(enumerate_plugins)
if enumerate_plugins === true and (@enumerate_all_plugins === true or @enumerate_only_vulnerable_plugins === true)
raise "Please choose only one plugin enumeration option"
raise 'Please choose only one plugin enumeration option'
else
@enumerate_plugins = enumerate_plugins
end
@@ -99,7 +100,7 @@ class WpscanOptions
def enumerate_only_vulnerable_plugins=(enumerate_only_vulnerable_plugins)
if enumerate_only_vulnerable_plugins === true and (@enumerate_all_plugins === true or @enumerate_plugins === true)
raise "Please choose only one plugin enumeration option"
raise 'Please choose only one plugin enumeration option'
else
@enumerate_only_vulnerable_plugins = enumerate_only_vulnerable_plugins
end
@@ -107,7 +108,7 @@ class WpscanOptions
def enumerate_all_plugins=(enumerate_all_plugins)
if enumerate_all_plugins === true and (@enumerate_plugins === true or @enumerate_only_vulnerable_plugins === true)
raise "Please choose only one plugin enumeration option"
raise 'Please choose only one plugin enumeration option'
else
@enumerate_all_plugins = enumerate_all_plugins
end
@@ -115,7 +116,7 @@ class WpscanOptions
def enumerate_themes=(enumerate_themes)
if enumerate_themes === true and (@enumerate_all_themes === true or @enumerate_only_vulnerable_themes === true)
raise "Please choose only one theme enumeration option"
raise 'Please choose only one theme enumeration option'
else
@enumerate_themes = enumerate_themes
end
@@ -123,7 +124,7 @@ class WpscanOptions
def enumerate_only_vulnerable_themes=(enumerate_only_vulnerable_themes)
if enumerate_only_vulnerable_themes === true and (@enumerate_all_themes === true or @enumerate_themes === true)
raise "Please choose only one theme enumeration option"
raise 'Please choose only one theme enumeration option'
else
@enumerate_only_vulnerable_themes = enumerate_only_vulnerable_themes
end
@@ -131,14 +132,14 @@ class WpscanOptions
def enumerate_all_themes=(enumerate_all_themes)
if enumerate_all_themes === true and (@enumerate_themes === true or @enumerate_only_vulnerable_themes === true)
raise "Please choose only one theme enumeration option"
raise 'Please choose only one theme enumeration option'
else
@enumerate_all_themes = enumerate_all_themes
end
end
def basic_auth=(basic_auth)
raise "Invalid basic authentication format, login:password expected" if basic_auth.index(':').nil?
raise 'Invalid basic authentication format, login:password expected' if basic_auth.index(':').nil?
@basic_auth = "Basic #{Base64.encode64(basic_auth).chomp}"
end
@@ -183,9 +184,9 @@ class WpscanOptions
WpscanOptions.option_to_instance_variable_setter(cli_option),
cli_value
)
elsif cli_option === "--enumerate" # Special cases
elsif cli_option === '--enumerate' # Special cases
# Default value if no argument is given
cli_value = "vt,tt,u,vp" if cli_value.length == 0
cli_value = 'vt,tt,u,vp' if cli_value.length == 0
enumerate_options_from_string(cli_value)
else
@@ -200,7 +201,7 @@ class WpscanOptions
def enumerate_options_from_string(value)
# Usage of self is mandatory because there are overridden setters
value = value.split(',').map{ |c| c.downcase }
value = value.split(',').map { |c| c.downcase }
self.enumerate_only_vulnerable_plugins = true if value.include?('vp')
@@ -231,23 +232,23 @@ class WpscanOptions
# Even if a short option is given (IE : -u), the long one will be returned (IE : --url)
def self.get_opt_long
GetoptLong.new(
["--url", "-u", GetoptLong::REQUIRED_ARGUMENT],
["--enumerate", "-e", GetoptLong::OPTIONAL_ARGUMENT],
["--username", "-U", GetoptLong::REQUIRED_ARGUMENT],
["--wordlist", "-w", GetoptLong::REQUIRED_ARGUMENT],
["--threads", "-t", GetoptLong::REQUIRED_ARGUMENT],
["--force", "-f", GetoptLong::NO_ARGUMENT],
["--help", "-h", GetoptLong::NO_ARGUMENT],
["--verbose", "-v", GetoptLong::NO_ARGUMENT],
["--proxy", GetoptLong::REQUIRED_ARGUMENT],
["--proxy-auth", GetoptLong::REQUIRED_ARGUMENT],
["--update", GetoptLong::NO_ARGUMENT],
["--follow-redirection", GetoptLong::NO_ARGUMENT],
["--wp-content-dir", GetoptLong::REQUIRED_ARGUMENT],
["--wp-plugins-dir", GetoptLong::REQUIRED_ARGUMENT],
["--config-file", "-c", GetoptLong::REQUIRED_ARGUMENT],
["--exclude-content-based", GetoptLong::REQUIRED_ARGUMENT],
["--basic-auth", GetoptLong::REQUIRED_ARGUMENT]
['--url', '-u', GetoptLong::REQUIRED_ARGUMENT],
['--enumerate', '-e', GetoptLong::OPTIONAL_ARGUMENT],
['--username', '-U', GetoptLong::REQUIRED_ARGUMENT],
['--wordlist', '-w', GetoptLong::REQUIRED_ARGUMENT],
['--threads', '-t', GetoptLong::REQUIRED_ARGUMENT],
['--force', '-f', GetoptLong::NO_ARGUMENT],
['--help', '-h', GetoptLong::NO_ARGUMENT],
['--verbose', '-v', GetoptLong::NO_ARGUMENT],
['--proxy', GetoptLong::REQUIRED_ARGUMENT],
['--proxy-auth', GetoptLong::REQUIRED_ARGUMENT],
['--update', GetoptLong::NO_ARGUMENT],
['--follow-redirection', GetoptLong::NO_ARGUMENT],
['--wp-content-dir', GetoptLong::REQUIRED_ARGUMENT],
['--wp-plugins-dir', GetoptLong::REQUIRED_ARGUMENT],
['--config-file', '-c', GetoptLong::REQUIRED_ARGUMENT],
['--exclude-content-based', GetoptLong::REQUIRED_ARGUMENT],
['--basic-auth', GetoptLong::REQUIRED_ARGUMENT]
)
end