Tried to make code climate happy
This commit is contained in:
@@ -95,7 +95,7 @@ class WpItems < Array
|
||||
code = tag.text.to_s
|
||||
next if code.empty?
|
||||
|
||||
if ! code.valid_encoding?
|
||||
if !code.valid_encoding?
|
||||
code = code.encode('UTF-16be', :invalid => :replace, :replace => '?').encode('UTF-8')
|
||||
end
|
||||
|
||||
|
||||
@@ -294,18 +294,25 @@ end
|
||||
def get_random_user_agent
|
||||
user_agents = []
|
||||
|
||||
unless File.exist?(USER_AGENTS_FILE)
|
||||
raise('[ERROR] Missing user-agent data. Please re-run with --update.')
|
||||
end
|
||||
# If we can't access the file, die
|
||||
raise('[ERROR] Missing user-agent data. Please re-run with just --update.') unless File.exist?(USER_AGENTS_FILE)
|
||||
|
||||
# Read in file
|
||||
f = File.open(USER_AGENTS_FILE, 'r')
|
||||
|
||||
# Read every line in the file
|
||||
f.each_line do |line|
|
||||
# ignore comments
|
||||
# Remove any End of Line issues, and leading/trailing spaces
|
||||
line = line.strip.chomp
|
||||
# Ignore empty files and comments
|
||||
next if line.empty? or line =~ /^\s*(#|\/\/)/
|
||||
# Add to array
|
||||
user_agents << line.strip
|
||||
end
|
||||
# Close file handler
|
||||
f.close
|
||||
# return ransom user-agent
|
||||
|
||||
# Return random user-agent
|
||||
user_agents.sample
|
||||
end
|
||||
|
||||
@@ -332,3 +339,8 @@ end
|
||||
def get_http_status(url)
|
||||
Browser.get(url.to_s).code
|
||||
end
|
||||
|
||||
# Check to see if we need a "s"
|
||||
def grammar_s(size)
|
||||
size.to_i >= 1 ? "s" : ""
|
||||
end
|
||||
@@ -3,12 +3,6 @@
|
||||
class WebSite
|
||||
module HumansTxt
|
||||
|
||||
# Checks if a humans.txt file exists
|
||||
# @return [ Boolean ]
|
||||
def has_humans?
|
||||
Browser.get(humans_url).code == 200
|
||||
end
|
||||
|
||||
# Gets a humans.txt URL
|
||||
# @return [ String ]
|
||||
def humans_url
|
||||
@@ -22,18 +16,15 @@ class WebSite
|
||||
response = Browser.get(humans_url.to_s)
|
||||
body = response.body
|
||||
|
||||
# Get all non-comments
|
||||
entries = body.split(/\n/)
|
||||
|
||||
# Did we get something?
|
||||
if entries
|
||||
entries.flatten!
|
||||
entries.uniq!
|
||||
|
||||
entries.each do |d|
|
||||
temp = d.strip
|
||||
return_object << temp.to_s
|
||||
end
|
||||
# Remove any rubbish
|
||||
entries = clean_uri(entries)
|
||||
end
|
||||
return_object
|
||||
return return_object
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -29,16 +29,12 @@ class WebSite
|
||||
|
||||
# Did we get something?
|
||||
if entries
|
||||
# Extract elements
|
||||
entries.flatten!
|
||||
# Remove any leading/trailing spaces
|
||||
entries.collect{|x| x.strip || x }
|
||||
# End Of Line issues
|
||||
entries.collect{|x| x.chomp! || x }
|
||||
# Remove nil's and sort
|
||||
entries.compact.sort!
|
||||
# Unique values only
|
||||
entries.uniq!
|
||||
# Remove any rubbish
|
||||
entries = clean_uri(entries)
|
||||
|
||||
# Sort
|
||||
entries.sort!
|
||||
|
||||
# Wordpress URL
|
||||
wordpress_path = @uri.path
|
||||
|
||||
@@ -50,19 +46,10 @@ class WebSite
|
||||
entries.delete(dir_with_subdir)
|
||||
end
|
||||
|
||||
# Each value now, try and make it a full URL
|
||||
entries.each do |d|
|
||||
begin
|
||||
temp = @uri.clone
|
||||
temp.path = d.strip
|
||||
rescue URI::Error
|
||||
temp = d.strip
|
||||
end
|
||||
return_object << temp.to_s
|
||||
end
|
||||
|
||||
# Convert to full URIs
|
||||
return_object = full_uri(entries)
|
||||
end
|
||||
return_object
|
||||
return return_object
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
class WebSite
|
||||
module SecurityTxt
|
||||
|
||||
# Checks if a security.txt file exists
|
||||
# @return [ Boolean ]
|
||||
def has_security?
|
||||
Browser.get(security_url).code == 200
|
||||
end
|
||||
|
||||
# Gets a security.txt URL
|
||||
# @return [ String ]
|
||||
def security_url
|
||||
@@ -25,16 +19,12 @@ class WebSite
|
||||
# Get all non-comments
|
||||
entries = body.split(/\n/)
|
||||
|
||||
# Did we get something?
|
||||
if entries
|
||||
entries.flatten!
|
||||
entries.uniq!
|
||||
|
||||
entries.each do |d|
|
||||
temp = d.strip
|
||||
return_object << temp.to_s
|
||||
end
|
||||
# Remove any rubbish
|
||||
entries = clean_uri(entries)
|
||||
end
|
||||
return_object
|
||||
return return_object
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -31,37 +31,22 @@ class WebSite
|
||||
|
||||
# Make request
|
||||
response = Browser.get(sitemap_url.to_s)
|
||||
body = response.body
|
||||
|
||||
# Get all allow and disallow urls
|
||||
entries = body.scan(/^sitemap\s*:\s*(.*)$/i)
|
||||
entries = response.body.scan(/^sitemap\s*:\s*(.*)$/i)
|
||||
|
||||
# Did we get something?
|
||||
if entries
|
||||
# Extract elements
|
||||
entries.flatten!
|
||||
# Remove any leading/trailing spaces
|
||||
entries.collect{|x| x.strip || x }
|
||||
# End Of Line issues
|
||||
entries.collect{|x| x.chomp! || x }
|
||||
# Remove nil's and sort
|
||||
entries.compact.sort!
|
||||
# Unique values only
|
||||
entries.uniq!
|
||||
# Remove any rubbish
|
||||
entries = clean_uri(entries)
|
||||
|
||||
# Each value now, try and make it a full URL
|
||||
entries.each do |d|
|
||||
begin
|
||||
temp = @uri.clone
|
||||
temp.path = d.strip
|
||||
rescue URI::Error
|
||||
temp = d.strip
|
||||
end
|
||||
return_object << temp.to_s
|
||||
end
|
||||
# Sort
|
||||
entries.sort!
|
||||
|
||||
# Convert to full URIs
|
||||
return_object = full_uri(entries)
|
||||
end
|
||||
return_object
|
||||
return return_object
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -17,13 +17,15 @@ class WpTarget < WebSite
|
||||
data = JSON.parse(response.body)
|
||||
|
||||
# If there is nothing there, return false
|
||||
return false if data.empty?
|
||||
|
||||
if data.empty?
|
||||
return false
|
||||
# WAF/API disabled response
|
||||
return false if data.include?('message') and data['message'] =~ /Only authenticated users can access the REST API/
|
||||
|
||||
elsif data.include?('message') and data['message'] =~ /Only authenticated users can access the REST API/
|
||||
return false
|
||||
# Success!
|
||||
return true if response.code == 200
|
||||
elsif response.code == 200
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
# Something went wrong
|
||||
@@ -70,6 +72,10 @@ class WpTarget < WebSite
|
||||
# Sort and uniq
|
||||
users = users.sort.uniq
|
||||
|
||||
# Feedback
|
||||
grammar = grammar_s(users.size)
|
||||
puts warning("#{users.size} user#{grammar} exposed via API: #{json_users_url}")
|
||||
|
||||
# Print results
|
||||
table = Terminal::Table.new(headings: ['ID', 'Name', 'URL'],
|
||||
rows: users)
|
||||
|
||||
@@ -43,12 +43,13 @@ class WpTarget < WebSite
|
||||
end
|
||||
|
||||
if users
|
||||
# Feedback
|
||||
puts warning("Detected users from RSS feed:")
|
||||
|
||||
# Sort and uniq
|
||||
users = users.sort_by { |user| user.to_s.downcase }.uniq
|
||||
|
||||
# Feedback
|
||||
grammar = grammar_s(users.size)
|
||||
puts warning("Detected #{users.size} user#{grammar} from RSS feed:")
|
||||
|
||||
# Print results
|
||||
table = Terminal::Table.new(headings: ['Name'],
|
||||
rows: users)
|
||||
|
||||
@@ -120,6 +120,39 @@ def help
|
||||
puts
|
||||
end
|
||||
|
||||
|
||||
def clean_uri(entries)
|
||||
# Extract elements
|
||||
entries.flatten!
|
||||
# Remove any leading/trailing spaces
|
||||
entries.collect{|x| x.strip || x }
|
||||
# End Of Line issues
|
||||
entries.collect{|x| x.chomp! || x }
|
||||
# Remove nil's
|
||||
entries.compact
|
||||
# Unique values only
|
||||
entries.uniq!
|
||||
|
||||
return entries
|
||||
end
|
||||
|
||||
# Return the full URL
|
||||
def full_uri(entries)
|
||||
return_object = []
|
||||
# Each value now, try and make it a full URL
|
||||
entries.each do |d|
|
||||
begin
|
||||
temp = @uri.clone
|
||||
temp.path = d.strip
|
||||
rescue URI::Error
|
||||
temp = d.strip
|
||||
end
|
||||
return_object << temp.to_s
|
||||
end
|
||||
|
||||
return return_object
|
||||
end
|
||||
|
||||
# Hook to check if the target if down during the scan
|
||||
# And have the number of requests performed to display at the end of the scan
|
||||
# The target is considered down after 30 requests with status = 0
|
||||
@@ -138,3 +171,4 @@ Typhoeus.on_complete do |response|
|
||||
|
||||
sleep(Browser.instance.throttle)
|
||||
end
|
||||
|
||||
|
||||
41
wpscan.rb
41
wpscan.rb
@@ -248,7 +248,8 @@ def main
|
||||
end
|
||||
|
||||
if wp_target.has_sitemap?
|
||||
puts info("Sitemap found: #{wp_target.sitemap_url}")
|
||||
code = get_http_status(wp_target.robots_url)
|
||||
puts info("Sitemap found: #{wp_target.sitemap_url} [HTTP #{code}]")
|
||||
|
||||
wp_target.parse_sitemap.each do |dir|
|
||||
code = get_http_status(dir)
|
||||
@@ -257,8 +258,8 @@ def main
|
||||
spacer()
|
||||
end
|
||||
|
||||
if wp_target.has_humans?
|
||||
code = get_http_status(wp_target.humans_url)
|
||||
code = get_http_status(wp_target.humans_url)
|
||||
if code == 200
|
||||
puts info("humans.txt available under: #{wp_target.humans_url} [HTTP #{code}]")
|
||||
|
||||
wp_target.parse_humans_txt.each do |dir|
|
||||
@@ -267,8 +268,8 @@ def main
|
||||
spacer()
|
||||
end
|
||||
|
||||
if wp_target.has_security?
|
||||
code = get_http_status(wp_target.humans_url)
|
||||
code = get_http_status(wp_target.security_url)
|
||||
if code == 200
|
||||
puts info("security.txt available under: #{wp_target.security_url} [HTTP #{code}]")
|
||||
|
||||
wp_target.parse_security_txt.each do |dir|
|
||||
@@ -308,18 +309,18 @@ def main
|
||||
end
|
||||
|
||||
if wp_target.has_xml_rpc?
|
||||
puts info("XML-RPC Interface available under: #{wp_target.xml_rpc_url}")
|
||||
code = get_http_status(wp_target.xml_rpc_url)
|
||||
puts info("XML-RPC Interface available under: #{wp_target.xml_rpc_url} [HTTP #{code}]")
|
||||
spacer()
|
||||
end
|
||||
|
||||
# Test to see if MAIN API URL gives anything back
|
||||
if wp_target.has_api?(wp_target.json_url)
|
||||
puts info("API exposed: #{wp_target.json_url}")
|
||||
code = get_http_status(wp_target.json_url)
|
||||
puts info("API exposed: #{wp_target.json_url} [HTTP #{code}]")
|
||||
|
||||
# Test to see if USER API URL gives anything back
|
||||
if wp_target.has_api?(wp_target.json_users_url)
|
||||
puts warning("Users exposed via API: #{wp_target.json_users_url}")
|
||||
|
||||
# Print users from JSON
|
||||
wp_target.json_get_users(wp_target.json_users_url)
|
||||
end
|
||||
@@ -360,6 +361,7 @@ def main
|
||||
exclude_content: wpscan_options.exclude_content_based
|
||||
}
|
||||
|
||||
puts info('Enumerating WordPress version ...')
|
||||
if (wp_version = wp_target.version(WP_VERSIONS_FILE))
|
||||
if wp_target.has_readme? && VersionCompare::lesser?(wp_version.identifier, '4.7')
|
||||
puts warning("The WordPress '#{wp_target.readme_url}' file exists exposing a version number")
|
||||
@@ -398,14 +400,11 @@ def main
|
||||
|
||||
wp_plugins = WpPlugins.passive_detection(wp_target)
|
||||
if !wp_plugins.empty?
|
||||
if wp_plugins.size == 1
|
||||
puts " | #{wp_plugins.size} plugin found:"
|
||||
else
|
||||
puts " | #{wp_plugins.size} plugins found:"
|
||||
end
|
||||
grammar = grammar_s(wp_plugins.size)
|
||||
puts " | #{wp_plugins.size} plugin#{grammar} found:"
|
||||
wp_plugins.output(wpscan_options.verbose)
|
||||
else
|
||||
puts info('No plugins found')
|
||||
puts info('No plugins found passively')
|
||||
end
|
||||
spacer()
|
||||
end
|
||||
@@ -438,7 +437,7 @@ def main
|
||||
|
||||
puts
|
||||
if !wp_plugins.empty?
|
||||
grammar = wp_themes.size == 1 ? "" : "s"
|
||||
grammar = grammar_s(wp_plugins.size)
|
||||
puts info("We found #{wp_plugins.size} plugin#{grammar}:")
|
||||
|
||||
wp_plugins.output(wpscan_options.verbose)
|
||||
@@ -475,7 +474,7 @@ def main
|
||||
)
|
||||
puts
|
||||
if !wp_themes.empty?
|
||||
grammar = wp_themes.size == 1 ? "" : "s"
|
||||
grammar = grammar_s(wp_themes.size)
|
||||
puts info("We found #{wp_themes.size} theme#{grammar}:")
|
||||
|
||||
wp_themes.output(wpscan_options.verbose)
|
||||
@@ -498,7 +497,7 @@ def main
|
||||
)
|
||||
puts
|
||||
if !wp_timthumbs.empty?
|
||||
grammar = wp_timthumbs.size == 1 ? "" : "s"
|
||||
grammar = grammar_s(wp_timthumbs.size)
|
||||
puts info("We found #{wp_timthumbs.size} timthumb file#{grammar}:")
|
||||
|
||||
wp_timthumbs.output(wpscan_options.verbose)
|
||||
@@ -533,7 +532,7 @@ def main
|
||||
exit(1)
|
||||
end
|
||||
else
|
||||
grammar = wp_users.size == 1 ? "" : "s"
|
||||
grammar = grammar_s(wp_users.size)
|
||||
puts info("We identified the following #{wp_users.size} user#{grammar}:")
|
||||
wp_users.output(margin_left: ' ' * 4)
|
||||
if wp_users[0].login == "admin"
|
||||
@@ -544,21 +543,21 @@ def main
|
||||
else
|
||||
wp_users = WpUsers.new
|
||||
|
||||
# Username file?
|
||||
if wpscan_options.usernames
|
||||
File.open(wpscan_options.usernames).each do |username|
|
||||
wp_users << WpUser.new(wp_target.uri, login: username.chomp)
|
||||
end
|
||||
# Single username?
|
||||
else
|
||||
wp_users << WpUser.new(wp_target.uri, login: wpscan_options.username)
|
||||
end
|
||||
spacer()
|
||||
end
|
||||
|
||||
# Start the brute forcer
|
||||
bruteforce = true
|
||||
if wpscan_options.wordlist
|
||||
if wp_target.has_login_protection?
|
||||
|
||||
protection_plugin = wp_target.login_protection_plugin()
|
||||
|
||||
puts
|
||||
|
||||
Reference in New Issue
Block a user