Check for API access and /wp-json/'s users output
This commit is contained in:
@@ -304,3 +304,11 @@ end
|
|||||||
def url_encode(str)
|
def url_encode(str)
|
||||||
CGI.escape(str).gsub("+", "%20")
|
CGI.escape(str).gsub("+", "%20")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Check valid JSON?
|
||||||
|
def valid_json?(json)
|
||||||
|
JSON.parse(json)
|
||||||
|
return true
|
||||||
|
rescue JSON::ParserError => e
|
||||||
|
return false
|
||||||
|
end
|
||||||
@@ -1,22 +1,24 @@
|
|||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
require 'web_site'
|
require 'web_site'
|
||||||
require 'wp_target/wp_readme'
|
require 'wp_target/wp_api'
|
||||||
require 'wp_target/wp_registrable'
|
|
||||||
require 'wp_target/wp_config_backup'
|
require 'wp_target/wp_config_backup'
|
||||||
require 'wp_target/wp_must_use_plugins'
|
|
||||||
require 'wp_target/wp_login_protection'
|
|
||||||
require 'wp_target/wp_custom_directories'
|
require 'wp_target/wp_custom_directories'
|
||||||
require 'wp_target/wp_full_path_disclosure'
|
require 'wp_target/wp_full_path_disclosure'
|
||||||
|
require 'wp_target/wp_login_protection'
|
||||||
|
require 'wp_target/wp_must_use_plugins'
|
||||||
|
require 'wp_target/wp_readme'
|
||||||
|
require 'wp_target/wp_registrable'
|
||||||
|
|
||||||
class WpTarget < WebSite
|
class WpTarget < WebSite
|
||||||
include WpTarget::WpReadme
|
include WpTarget::WpAPI
|
||||||
include WpTarget::WpRegistrable
|
|
||||||
include WpTarget::WpConfigBackup
|
include WpTarget::WpConfigBackup
|
||||||
include WpTarget::WpMustUsePlugins
|
|
||||||
include WpTarget::WpLoginProtection
|
|
||||||
include WpTarget::WpCustomDirectories
|
include WpTarget::WpCustomDirectories
|
||||||
include WpTarget::WpFullPathDisclosure
|
include WpTarget::WpFullPathDisclosure
|
||||||
|
include WpTarget::WpLoginProtection
|
||||||
|
include WpTarget::WpMustUsePlugins
|
||||||
|
include WpTarget::WpReadme
|
||||||
|
include WpTarget::WpRegistrable
|
||||||
|
|
||||||
attr_reader :verbose
|
attr_reader :verbose
|
||||||
|
|
||||||
|
|||||||
66
lib/wpscan/wp_target/wp_api.rb
Normal file
66
lib/wpscan/wp_target/wp_api.rb
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# encoding: UTF-8
|
||||||
|
|
||||||
|
class WpTarget < WebSite
|
||||||
|
module WpAPI
|
||||||
|
|
||||||
|
# Checks to see if the REST API is enabled
|
||||||
|
#
|
||||||
|
# This by default in a WordPress installation since 4.5+
|
||||||
|
# @return [ Boolean ]
|
||||||
|
def has_api?(url)
|
||||||
|
# Make the request
|
||||||
|
response = Browser.get(url)
|
||||||
|
|
||||||
|
# Able to view the output?
|
||||||
|
if valid_json?(response.body)
|
||||||
|
# Read in JSON
|
||||||
|
data = JSON.parse(response.body)
|
||||||
|
|
||||||
|
# If there is nothing there, return false
|
||||||
|
return false if data.empty?
|
||||||
|
|
||||||
|
# WAF/API disabled response
|
||||||
|
return false if data.include?('message') and data['message'] =~ /Only authenticated users can access the REST API/
|
||||||
|
|
||||||
|
# Success!
|
||||||
|
return true if response.code == 200
|
||||||
|
end
|
||||||
|
|
||||||
|
# Something went wrong
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ] The API/JSON URL
|
||||||
|
def json_url
|
||||||
|
@uri.merge('/wp-json/').to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ] The API/JSON URL to show users
|
||||||
|
def json_users_url
|
||||||
|
@uri.merge('/wp-json/wp/v2/users').to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [ String ] The API/JSON URL to show users
|
||||||
|
def json_get_users(url)
|
||||||
|
# Make the request
|
||||||
|
response = Browser.get(url)
|
||||||
|
|
||||||
|
# Able to view the output?
|
||||||
|
return false if not valid_json?(response.body)
|
||||||
|
|
||||||
|
# Read in JSON
|
||||||
|
data = JSON.parse(response.body)
|
||||||
|
|
||||||
|
# If there is nothing there, return false
|
||||||
|
return false if data.empty?
|
||||||
|
|
||||||
|
# If not HTTP 200, return false
|
||||||
|
return false if response.code != 200
|
||||||
|
|
||||||
|
data.each do |child|
|
||||||
|
puts notice("ID: #{child['id']} | Name: #{child['name']}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
15
wpscan.rb
15
wpscan.rb
@@ -299,6 +299,21 @@ def main
|
|||||||
puts info("XML-RPC Interface available under: #{wp_target.xml_rpc_url}")
|
puts info("XML-RPC Interface available under: #{wp_target.xml_rpc_url}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if wp_target.has_api?(wp_target.json_url)
|
||||||
|
puts info("API exposed: #{wp_target.json_url}")
|
||||||
|
|
||||||
|
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
|
||||||
|
end
|
||||||
|
|
||||||
|
if wp_target.has_full_path_disclosure?
|
||||||
|
puts warning("Full Path Disclosure (FPD) in '#{wp_target.full_path_disclosure_url}': #{wp_target.full_path_disclosure_data}")
|
||||||
|
end
|
||||||
|
|
||||||
if wp_target.upload_directory_listing_enabled?
|
if wp_target.upload_directory_listing_enabled?
|
||||||
puts warning("Upload directory has directory listing enabled: #{wp_target.upload_dir_url}")
|
puts warning("Upload directory has directory listing enabled: #{wp_target.upload_dir_url}")
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user