-) Code formatting

-) rspec tests
This commit is contained in:
Christian Mehlmauer
2012-09-22 15:44:41 +02:00
parent 55fa6422b2
commit ae96d93cee
52 changed files with 897 additions and 463 deletions

View File

@@ -27,8 +27,8 @@ module Malwares
# return array of string (url of malwares found)
def malwares(malwares_file_path = nil)
if @malwares.nil?
malwares_found = []
malwares_file = Malwares.malwares_file(malwares_file_path)
malwares_found = []
malwares_file = Malwares.malwares_file(malwares_file_path)
index_page_body = Browser.instance.get(@uri.to_s).body
File.open(malwares_file, 'r') do |file|

View File

@@ -24,14 +24,14 @@ module WebSite
wordpress = false
response = Browser.instance.get(login_url(),
{ :follow_location => true, :max_redirects => 2 }
{:follow_location => true, :max_redirects => 2}
)
if response.body =~ %r{WordPress}i
wordpress = true
else
response = Browser.instance.get(xmlrpc_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

View File

@@ -22,14 +22,14 @@ module WpConfigBackup
# See http://www.feross.org/cmsploit/
# return an array of backup config files url
def config_backup
found = []
backups = WpConfigBackup.config_backup_files
browser = Browser.instance
hydra = browser.hydra
found = []
backups = WpConfigBackup.config_backup_files
browser = Browser.instance
hydra = browser.hydra
backups.each do |file|
file_url = @uri.merge(URI.escape(file)).to_s
request = browser.forge_request(file_url)
request = browser.forge_request(file_url)
request.on_complete do |response|
if response.body[%r{define}i] and not response.body[%r{<\s?html}i]

View File

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

View File

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

View File

@@ -47,7 +47,7 @@ module WpTimthumbs
protected
def targets_url_from_theme(theme_name, options)
targets = []
targets = []
theme_name = URI.escape(theme_name)
%w{
@@ -55,10 +55,10 @@ module WpTimthumbs
scripts/timthumb.php tools/timthumb.php functions/timthumb.php
}.each do |file|
targets << {
:url => options[:url],
:path => "themes/#{theme_name}/#{file}",
:url => options[:url],
:path => "themes/#{theme_name}/#{file}",
:wp_content_dir => options[:wp_content_dir],
:name => options[:name]
:name => options[:name]
}
end
targets

View File

@@ -26,9 +26,9 @@ module WpUsernames
#
# returns an array of WpUser (can be empty)
def usernames(options = {})
range = options[:range] || (1..10)
browser = Browser.instance
usernames = []
range = options[:range] || (1..10)
browser = Browser.instance
usernames = []
range.each do |author_id|
url = author_url(author_id)
@@ -58,7 +58,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)

View File

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

View File

@@ -32,16 +32,16 @@
# * +type+ - Type: plugins, themes
class WpOptions
def self.check_options(options)
raise("url must be set") unless options[:url] != nil and options[:url].to_s.length > 0
raise("url must be set") unless options[:url] != nil and options[:url].to_s.length > 0
raise("only_vulnerable_ones must be set") unless options[:only_vulnerable_ones] != nil
raise("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_progress_bar must be set") unless options[:show_progress_bar] != nil
raise("error_404_hash must be set") unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0
raise("type must be set") unless options[:type] != nil and options[:type].length > 0
raise("file must be set") unless options[:file] != nil and options[:file].length > 0
raise("vulns_file must be set") unless options[:vulns_file] != nil and options[:vulns_file].length > 0
raise("vulns_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_progress_bar must be set") unless options[:show_progress_bar] != nil
raise("error_404_hash must be set") unless options[:error_404_hash] != nil and options[:error_404_hash].length > 0
raise("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

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

View File

@@ -34,8 +34,8 @@ class WpTarget
attr_reader :uri, :verbose
def initialize(target_url, options = {})
@uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
@verbose = options[:verbose]
@uri = URI.parse(add_trailing_slash(add_http_protocol(target_url)))
@verbose = options[:verbose]
@wp_content_dir = options[:wp_content_dir]
@wp_plugins_dir = options[:wp_plugins_dir]
@@ -111,7 +111,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

View File

@@ -23,10 +23,10 @@ class WpTheme < WpItem
attr_reader :name, :style_url, :version
def initialize(options = {})
options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/wp_theme_vulns.xml'
options[:vulns_xml] = options[:vulns_xml] || DATA_DIR + '/wp_theme_vulns.xml'
options[:vulns_xpath] = "//theme[@name='$name$']/vulnerability"
@version = options[:version]
@style_url = options[:style_url]
@version = options[:version]
@style_url = options[:style_url]
super(options)
end
@@ -56,18 +56,18 @@ 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
style_url = matches[0]
theme_name = matches[1]
return new(:name => theme_name,
:style_url => style_url,
:url => style_url,
:path => "",
:wp_content_dir => ""
return new(:name => theme_name,
:style_url => style_url,
:url => style_url,
:path => "",
:wp_content_dir => ""
)
end
end
@@ -79,15 +79,15 @@ class WpTheme < WpItem
matches = regexp.match(body)
if matches
woo_theme_name = matches[1]
woo_theme_version = matches[2]
woo_theme_name = matches[1]
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,
:url => matches[0],
:path => "",
:wp_content_dir => ""
return new(:name => woo_theme_name,
:version => woo_theme_version,
:url => matches[0],
:path => "",
:wp_content_dir => ""
)
end
end

View File

@@ -23,10 +23,10 @@ class WpVersion < Vulnerable
attr_reader :number, :discovery_method
def initialize(number, options = {})
@number = number
@number = number
@discovery_method = options[:discovery_method]
@vulns_xml = options[:vulns_xml] || DATA_DIR + '/wp_vulns.xml'
@vulns_xpath = "//wordpress[@version='#{@number}']/vulnerability"
@vulns_xml = options[:vulns_xml] || DATA_DIR + '/wp_vulns.xml'
@vulns_xpath = "//wordpress[@version='#{@number}']/vulnerability"
end
# Will use all method self.find_from_* to try to detect the version
@@ -38,7 +38,7 @@ class WpVersion < Vulnerable
# (find_from_meta_generator, find_from_rss_generator etc)
def self.find(target_uri, wp_content_dir)
options = {
:url => target_uri,
:url => target_uri,
:wp_content_dir => wp_content_dir
}
self.methods.grep(/find_from_/).each do |method_to_call|
@@ -60,14 +60,14 @@ class WpVersion < Vulnerable
# that it is reinstated on upgrade.
def self.find_from_meta_generator(options)
target_uri = options[: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 ([^"]+)"}i, 1]
end
def self.find_from_rss_generator(options)
target_uri = options[: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=([^<]+)</generator>}i, 1]
end
@@ -105,11 +105,11 @@ class WpVersion < Vulnerable
file_url = target_uri.merge(node.attribute('src').text).to_s
file_url = file_url.gsub(/\$wp-plugins\$/i, wp_plugins).gsub(/\$wp-content\$/i, wp_content)
response = Browser.instance.get(file_url)
md5sum = Digest::MD5.hexdigest(response.body)
md5sum = Digest::MD5.hexdigest(response.body)
node.search('hash').each do |hash|
if hash.attribute('md5').text == md5sum
return hash.search('versions').text
return hash.search('versions').text
end
end
end

View File

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

View File

@@ -19,27 +19,27 @@
class WpscanOptions
ACCESSOR_OPTIONS = [
:enumerate_plugins,
:enumerate_only_vulnerable_plugins,
:enumerate_themes,
:enumerate_only_vulnerable_themes,
:enumerate_timthumbs,
:enumerate_usernames,
:enumerate_usernames_range,
:proxy,
:threads,
:url,
:wordlist,
:force,
:update,
:verbose,
:username,
:password,
:follow_redirection,
:wp_content_dir,
:wp_plugins_dir,
:help,
:config_file
:enumerate_plugins,
:enumerate_only_vulnerable_plugins,
:enumerate_themes,
:enumerate_only_vulnerable_themes,
:enumerate_timthumbs,
:enumerate_usernames,
:enumerate_usernames_range,
:proxy,
:threads,
:url,
:wordlist,
:force,
:update,
:verbose,
:username,
:password,
:follow_redirection,
:wp_content_dir,
:wp_plugins_dir,
:help,
:config_file
]
attr_accessor *ACCESSOR_OPTIONS
@@ -131,7 +131,7 @@ class WpscanOptions
if ARGV.length > 0
WpscanOptions.get_opt_long.each do |opt, arg|
wpscan_options.set_option_from_cli(opt, arg)
wpscan_options.set_option_from_cli(opt, arg)
end
end
@@ -144,11 +144,11 @@ class WpscanOptions
if WpscanOptions.is_long_option?(cli_option)
self.send(
WpscanOptions.option_to_instance_variable_setter(cli_option),
cli_value
WpscanOptions.option_to_instance_variable_setter(cli_option),
cli_value
)
elsif cli_option === "--enumerate" # Special cases
# Default value if no argument is given
# Default value if no argument is given
cli_value = "T!tup!" if cli_value.length == 0
enumerate_options_from_string(cli_value)
@@ -188,20 +188,20 @@ 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::OPTIONAL_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]
["--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::OPTIONAL_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]
)
end
@@ -221,7 +221,7 @@ class WpscanOptions
def self.option_to_instance_variable_setter(option)
cleaned_option = WpscanOptions.clean_option(option)
option_syms = ACCESSOR_OPTIONS.grep(%r{^#{cleaned_option}})
option_syms = ACCESSOR_OPTIONS.grep(%r{^#{cleaned_option}})
option_syms.length == 1 ? :"#{option_syms.at(0)}=" : nil
end