wpscan 3.8.28 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +104 -30
- data/app/app.rb +26 -0
- data/app/controllers/aliases.rb +2 -2
- data/app/controllers/authenticated_inventory.rb +43 -0
- data/app/controllers/core/cli_options.rb +151 -0
- data/app/controllers/core.rb +200 -25
- data/app/controllers/custom_directories.rb +1 -1
- data/app/controllers/enumeration/cli_options.rb +21 -31
- data/app/controllers/enumeration/enum_methods.rb +145 -38
- data/app/controllers/enumeration.rb +26 -3
- data/app/controllers/interesting_findings.rb +25 -0
- data/app/controllers/main_theme.rb +1 -1
- data/app/controllers/password_attack.rb +14 -6
- data/app/controllers/vuln_api.rb +9 -3
- data/app/controllers/wp_version.rb +1 -1
- data/app/controllers.rb +1 -0
- data/app/finders/backup_folders/known_locations.rb +66 -0
- data/app/finders/backup_folders.rb +19 -0
- data/app/finders/config_backups/known_filenames.rb +6 -4
- data/app/finders/config_backups.rb +1 -1
- data/app/finders/db_exports/known_locations.rb +16 -14
- data/app/finders/db_exports.rb +1 -1
- data/app/finders/interesting_findings/backup_db.rb +1 -1
- data/app/finders/interesting_findings/debug_log.rb +1 -1
- data/app/finders/interesting_findings/duplicator_installer_log.rb +1 -1
- data/app/finders/interesting_findings/emergency_pwd_reset_script.rb +1 -1
- data/app/finders/interesting_findings/fantastico_fileslist.rb +21 -0
- data/app/finders/interesting_findings/full_path_disclosure.rb +1 -1
- data/app/finders/interesting_findings/headers.rb +17 -0
- data/app/finders/interesting_findings/mu_plugins.rb +1 -1
- data/app/finders/interesting_findings/multisite.rb +1 -1
- data/app/finders/interesting_findings/php_disabled.rb +2 -2
- data/app/finders/interesting_findings/readme.rb +1 -1
- data/app/finders/interesting_findings/registration.rb +1 -1
- data/app/finders/interesting_findings/robots_txt.rb +20 -0
- data/app/finders/interesting_findings/search_replace_db_2.rb +19 -0
- data/app/finders/interesting_findings/tmm_db_migrate.rb +1 -1
- data/app/finders/interesting_findings/upload_directory_listing.rb +1 -1
- data/app/finders/interesting_findings/upload_sql_dump.rb +2 -2
- data/app/finders/interesting_findings/wp_cron.rb +1 -1
- data/app/finders/interesting_findings/xml_rpc.rb +61 -0
- data/app/finders/interesting_findings.rb +13 -4
- data/app/finders/main_theme/css_style_in_homepage.rb +1 -1
- data/app/finders/main_theme/urls_in_homepage.rb +3 -7
- data/app/finders/main_theme/woo_framework_meta_generator.rb +4 -4
- data/app/finders/main_theme.rb +1 -1
- data/app/finders/medias/attachment_brute_forcing.rb +2 -2
- data/app/finders/medias.rb +1 -1
- data/app/finders/passwords/wp_login.rb +2 -2
- data/app/finders/passwords/xml_rpc.rb +2 -2
- data/app/finders/passwords/xml_rpc_multicall.rb +1 -1
- data/app/finders/plugin_version/readme.rb +1 -1
- data/app/finders/plugin_version.rb +1 -1
- data/app/finders/plugins/known_locations.rb +17 -7
- data/app/finders/plugins/urls_in_homepage.rb +3 -7
- data/app/finders/plugins/wp_json_api.rb +85 -0
- data/app/finders/plugins.rb +2 -1
- data/app/finders/theme_version/style.rb +1 -1
- data/app/finders/theme_version/woo_framework_meta_generator.rb +1 -1
- data/app/finders/theme_version.rb +1 -1
- data/app/finders/themes/known_locations.rb +12 -6
- data/app/finders/themes/urls_in_homepage.rb +3 -7
- data/app/finders/themes/wp_json_api.rb +74 -0
- data/app/finders/themes.rb +2 -1
- data/app/finders/timthumb_version/bad_request.rb +1 -1
- data/app/finders/timthumb_version.rb +1 -1
- data/app/finders/timthumbs/known_locations.rb +6 -4
- data/app/finders/timthumbs.rb +1 -1
- data/app/finders/users/author_id_brute_forcing.rb +11 -7
- data/app/finders/users/author_posts.rb +1 -1
- data/app/finders/users/author_sitemap.rb +1 -1
- data/app/finders/users/login_error_messages.rb +1 -1
- data/app/finders/users/oembed_api.rb +3 -1
- data/app/finders/users/wp_json_api.rb +11 -7
- data/app/finders/users.rb +1 -1
- data/app/finders/wp_items/urls_in_page.rb +1 -1
- data/app/finders/wp_version/atom_generator.rb +1 -1
- data/app/finders/wp_version/rdf_generator.rb +1 -1
- data/app/finders/wp_version/readme.rb +1 -1
- data/app/finders/wp_version/rss_generator.rb +1 -1
- data/app/finders/wp_version/unique_fingerprinting.rb +2 -2
- data/app/finders/wp_version.rb +1 -1
- data/app/finders.rb +1 -0
- data/app/formatters/cli.rb +79 -0
- data/app/formatters/cli_no_color.rb +9 -0
- data/app/formatters/cli_no_colour.rb +17 -0
- data/app/formatters/json.rb +14 -0
- data/app/formatters/jsonl.rb +29 -0
- data/app/formatters/sarif.rb +311 -0
- data/app/models/backup_folder.rb +39 -0
- data/app/models/fantastico_fileslist.rb +34 -0
- data/app/models/headers.rb +44 -0
- data/app/models/interesting_finding.rb +41 -2
- data/app/models/plugin.rb +8 -2
- data/app/models/robots_txt.rb +31 -0
- data/app/models/search_replace_db_2.rb +17 -0
- data/app/models/theme.rb +9 -2
- data/app/models/timthumb.rb +4 -4
- data/app/models/user.rb +35 -0
- data/app/models/version.rb +49 -0
- data/app/models/wp_item/wordpress_org_data.rb +55 -0
- data/app/models/wp_item.rb +116 -14
- data/app/models/wp_version.rb +5 -3
- data/app/models/xml_rpc.rb +73 -3
- data/app/models.rb +2 -1
- data/app/user_agents.txt +46 -0
- data/app/views/cli/core/banner.erb +3 -3
- data/app/views/cli/core/finished.erb +15 -0
- data/app/views/cli/core/help.erb +4 -0
- data/app/views/cli/core/started.erb +11 -0
- data/app/views/cli/enumeration/backup_folders.erb +11 -0
- data/app/views/cli/enumeration/plugin.erb +13 -0
- data/app/views/cli/enumeration/plugins.erb +1 -12
- data/app/views/cli/enumeration/theme.erb +4 -0
- data/app/views/cli/enumeration/themes.erb +1 -3
- data/app/views/cli/enumeration/user.erb +4 -0
- data/app/views/cli/enumeration/users.erb +1 -3
- data/app/views/cli/finding.erb +1 -1
- data/app/views/cli/interesting_findings/_array.erb +10 -0
- data/app/views/cli/interesting_findings/findings.erb +23 -0
- data/app/views/cli/scan_aborted.erb +5 -0
- data/app/views/cli/update_aborted.erb +5 -0
- data/app/views/cli/vuln_api/status.erb +2 -0
- data/app/views/cli/vulnerability.erb +6 -0
- data/app/views/cli/wp_item.erb +4 -1
- data/app/views/json/core/banner.erb +2 -8
- data/app/views/json/core/finished.erb +13 -0
- data/app/views/json/core/help.erb +4 -0
- data/app/views/json/core/started.erb +10 -0
- data/app/views/json/enumeration/backup_folders.erb +11 -0
- data/app/views/json/enumeration/plugin.erb +15 -0
- data/app/views/json/enumeration/theme.erb +5 -0
- data/app/views/json/enumeration/user.erb +6 -0
- data/app/views/json/finding.erb +8 -2
- data/app/views/json/interesting_findings/findings.erb +24 -0
- data/app/views/json/notice.erb +1 -0
- data/app/views/json/scan_aborted.erb +5 -0
- data/app/views/json/update_aborted.erb +5 -0
- data/app/views/json/vuln_api/status.erb +2 -0
- data/app/views/json/wp_item.erb +4 -1
- data/bin/wpscan +1 -0
- data/lib/opt_parse_validator/config_files_loader_merger/base.rb +26 -0
- data/lib/opt_parse_validator/config_files_loader_merger/json.rb +17 -0
- data/lib/opt_parse_validator/config_files_loader_merger/yml.rb +17 -0
- data/lib/opt_parse_validator/config_files_loader_merger.rb +62 -0
- data/lib/opt_parse_validator/errors.rb +9 -0
- data/lib/opt_parse_validator/hacks.rb +19 -0
- data/lib/opt_parse_validator/opts/alias.rb +28 -0
- data/lib/opt_parse_validator/opts/array.rb +34 -0
- data/lib/opt_parse_validator/opts/base.rb +142 -0
- data/lib/opt_parse_validator/opts/boolean.rb +19 -0
- data/lib/opt_parse_validator/opts/choice.rb +43 -0
- data/lib/opt_parse_validator/opts/credentials.rb +15 -0
- data/lib/opt_parse_validator/opts/directory_path.rb +17 -0
- data/lib/opt_parse_validator/opts/file_path.rb +34 -0
- data/lib/opt_parse_validator/opts/headers.rb +33 -0
- data/lib/opt_parse_validator/opts/integer.rb +15 -0
- data/lib/opt_parse_validator/opts/integer_range.rb +37 -0
- data/lib/opt_parse_validator/opts/multi_choices.rb +135 -0
- data/lib/opt_parse_validator/opts/path.rb +78 -0
- data/lib/opt_parse_validator/opts/positive_integer.rb +16 -0
- data/lib/opt_parse_validator/opts/proxy.rb +7 -0
- data/lib/opt_parse_validator/opts/regexp.rb +14 -0
- data/lib/opt_parse_validator/opts/smart_list.rb +30 -0
- data/lib/opt_parse_validator/opts/string.rb +8 -0
- data/lib/opt_parse_validator/opts/uri.rb +41 -0
- data/lib/opt_parse_validator/opts/url.rb +11 -0
- data/lib/opt_parse_validator/opts.rb +9 -0
- data/lib/opt_parse_validator/version.rb +6 -0
- data/lib/opt_parse_validator.rb +161 -0
- data/lib/wpscan/browser/actions.rb +48 -0
- data/lib/wpscan/browser/options.rb +92 -0
- data/lib/wpscan/browser.rb +87 -2
- data/lib/wpscan/browser_authenticator.rb +64 -0
- data/lib/wpscan/cache/file_store.rb +77 -0
- data/lib/wpscan/cache/typhoeus.rb +25 -0
- data/lib/wpscan/controller.rb +100 -4
- data/lib/wpscan/controllers.rb +78 -3
- data/lib/wpscan/db/dynamic_finders/base.rb +3 -7
- data/lib/wpscan/db/dynamic_finders/plugin.rb +2 -2
- data/lib/wpscan/db/dynamic_finders/wordpress.rb +1 -1
- data/lib/wpscan/db/fingerprints.rb +2 -2
- data/lib/wpscan/db/updater.rb +23 -13
- data/lib/wpscan/db/vuln_api.rb +25 -9
- data/lib/wpscan/db/wp_item.rb +2 -2
- data/lib/wpscan/errors/enumeration.rb +4 -4
- data/lib/wpscan/errors/http.rb +82 -3
- data/lib/wpscan/errors/saml.rb +28 -0
- data/lib/wpscan/errors/scan.rb +14 -0
- data/lib/wpscan/errors/update.rb +11 -3
- data/lib/wpscan/errors/vuln_api.rb +24 -0
- data/lib/wpscan/errors/wordpress.rb +2 -2
- data/lib/wpscan/errors/wp_auth.rb +37 -0
- data/lib/wpscan/errors.rb +4 -3
- data/lib/wpscan/exit_code.rb +25 -0
- data/lib/wpscan/finders/base_finders.rb +45 -0
- data/lib/wpscan/finders/dynamic_finder/finder.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/version/body_pattern.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/version/comment.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/version/header_pattern.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/version/javascript_var.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +3 -5
- data/lib/wpscan/finders/dynamic_finder/version/xpath.rb +1 -1
- data/lib/wpscan/finders/dynamic_finder/wp_items/finder.rb +3 -3
- data/lib/wpscan/finders/dynamic_finder/wp_version.rb +1 -1
- data/lib/wpscan/finders/finder/breadth_first_dictionary_attack.rb +257 -0
- data/lib/wpscan/finders/finder/enumerator.rb +77 -0
- data/lib/wpscan/finders/finder/fingerprinter.rb +48 -0
- data/lib/wpscan/finders/finder/smart_url_checker/findings.rb +33 -0
- data/lib/wpscan/finders/finder/smart_url_checker.rb +60 -0
- data/lib/wpscan/finders/finder/wp_version/smart_url_checker.rb +1 -1
- data/lib/wpscan/finders/finder.rb +78 -0
- data/lib/wpscan/finders/finding.rb +54 -0
- data/lib/wpscan/finders/findings.rb +33 -0
- data/lib/wpscan/finders/independent_finder.rb +33 -0
- data/lib/wpscan/finders/independent_finders.rb +26 -0
- data/lib/wpscan/finders/same_type_finder.rb +19 -0
- data/lib/wpscan/finders/same_type_finders.rb +28 -0
- data/lib/wpscan/finders/unique_finder.rb +19 -0
- data/lib/wpscan/finders/unique_finders.rb +47 -0
- data/lib/wpscan/finders.rb +11 -12
- data/lib/wpscan/formatter/buffer.rb +17 -0
- data/lib/wpscan/formatter.rb +152 -0
- data/lib/wpscan/helper.rb +7 -1
- data/lib/wpscan/http_status_tracking.rb +128 -0
- data/lib/wpscan/numeric.rb +13 -0
- data/lib/wpscan/parsed_cli.rb +31 -2
- data/lib/wpscan/progressbar_null_output.rb +23 -0
- data/lib/wpscan/public_suffix/domain.rb +44 -0
- data/lib/wpscan/references.rb +118 -4
- data/lib/wpscan/scan.rb +130 -0
- data/lib/wpscan/target/hashes.rb +45 -0
- data/lib/wpscan/target/platform/php.rb +124 -0
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +3 -3
- data/lib/wpscan/target/platform/wordpress.rb +7 -8
- data/lib/wpscan/target/platform.rb +3 -0
- data/lib/wpscan/target/scope.rb +103 -0
- data/lib/wpscan/target/server/apache.rb +27 -0
- data/lib/wpscan/target/server/generic.rb +72 -0
- data/lib/wpscan/target/server/iis.rb +29 -0
- data/lib/wpscan/target/server/nginx.rb +27 -0
- data/lib/wpscan/target/server.rb +6 -0
- data/lib/wpscan/target.rb +129 -9
- data/lib/wpscan/typhoeus/hydra.rb +12 -0
- data/lib/wpscan/typhoeus/response.rb +24 -1
- data/lib/wpscan/version.rb +1 -1
- data/lib/wpscan/vulnerability.rb +157 -5
- data/lib/wpscan/vulnerability_filter.rb +68 -0
- data/lib/wpscan/vulnerable.rb +13 -1
- data/lib/wpscan/web_site.rb +152 -0
- data/lib/wpscan.rb +126 -29
- metadata +362 -20
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module WPScan
|
|
4
|
+
# WebSite Implementation
|
|
5
|
+
class WebSite
|
|
6
|
+
attr_reader :uri, :opts
|
|
7
|
+
|
|
8
|
+
# @param [ String ] site_url
|
|
9
|
+
# @param [ Hash ] opts
|
|
10
|
+
def initialize(site_url, opts = {})
|
|
11
|
+
self.url = site_url
|
|
12
|
+
@opts = opts
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def url=(site_url)
|
|
16
|
+
new_url = site_url.dup
|
|
17
|
+
|
|
18
|
+
# Add a trailing slash to the URL
|
|
19
|
+
new_url << '/' if new_url[-1, 1] != '/'
|
|
20
|
+
|
|
21
|
+
# Use the validator to ensure the URL has a correct format
|
|
22
|
+
OptParseValidator::OptURL.new([]).validate(new_url)
|
|
23
|
+
|
|
24
|
+
@uri = Addressable::URI.parse(new_url).normalize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param [ String ] path Optional path to merge with the uri
|
|
28
|
+
#
|
|
29
|
+
# @return [ String ]
|
|
30
|
+
def url(path = nil)
|
|
31
|
+
return @uri.to_s unless path
|
|
32
|
+
|
|
33
|
+
@uri.join(Addressable::URI.encode(path).gsub('#', '%23')).to_s
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @return [ String ] The IP address of the target
|
|
37
|
+
def ip
|
|
38
|
+
@ip ||= IPSocket.getaddress(uri.host)
|
|
39
|
+
rescue SocketError
|
|
40
|
+
'Unknown'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
attr_writer :homepage_res
|
|
44
|
+
|
|
45
|
+
# @return [ Typhoeus::Response ]
|
|
46
|
+
#
|
|
47
|
+
# As webmock does not support redirects mocking, coverage is ignored
|
|
48
|
+
# :nocov:
|
|
49
|
+
def homepage_res
|
|
50
|
+
@homepage_res ||= WPScan::Browser.get_and_follow_location(url)
|
|
51
|
+
end
|
|
52
|
+
# :nocov:
|
|
53
|
+
|
|
54
|
+
# @return [ String ]
|
|
55
|
+
def homepage_url
|
|
56
|
+
@homepage_url ||= homepage_res.effective_url
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Discards the cached homepage response and URL so the next access refetches.
|
|
60
|
+
# Used after mutating cookies/auth state mid-scan.
|
|
61
|
+
def reset_homepage_cache!
|
|
62
|
+
@homepage_res = nil
|
|
63
|
+
@homepage_url = nil
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @return [ Typhoeus::Response ]
|
|
67
|
+
def error_404_res
|
|
68
|
+
@error_404_res ||= WPScan::Browser.get_and_follow_location(error_404_url)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# @return [ String ] The URL of an unlikely existant page
|
|
72
|
+
def error_404_url
|
|
73
|
+
@error_404_url ||= uri.join("#{Digest::MD5.hexdigest(rand(999_999).to_s)[0..6]}.html").to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Checks if the remote website is up.
|
|
77
|
+
#
|
|
78
|
+
# @param [ String ] path
|
|
79
|
+
#
|
|
80
|
+
# @return [ Boolean ]
|
|
81
|
+
def online?(path = nil)
|
|
82
|
+
WPScan::Browser.get(url(path)).code.nonzero? ? true : false
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# @param [ String ] path
|
|
86
|
+
#
|
|
87
|
+
# @return [ Boolean ]
|
|
88
|
+
def http_auth?(path = nil)
|
|
89
|
+
WPScan::Browser.get(url(path)).code == 401
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# @param [ String ] path
|
|
93
|
+
#
|
|
94
|
+
# @return [ Boolean ]
|
|
95
|
+
def access_forbidden?(path = nil)
|
|
96
|
+
WPScan::Browser.get(url(path)).code == 403
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @param [ String ] path
|
|
100
|
+
#
|
|
101
|
+
# @return [ Boolean ]
|
|
102
|
+
def proxy_auth?(path = nil)
|
|
103
|
+
WPScan::Browser.get(url(path)).code == 407
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @param [ String ] url
|
|
107
|
+
#
|
|
108
|
+
# @return [ String ] The redirection url or nil
|
|
109
|
+
#
|
|
110
|
+
# As webmock does not support redirects mocking, coverage is ignored
|
|
111
|
+
# :nocov:
|
|
112
|
+
def redirection(url = nil)
|
|
113
|
+
url ||= @uri.to_s
|
|
114
|
+
|
|
115
|
+
return unless [301, 302].include?(WPScan::Browser.get(url).code)
|
|
116
|
+
|
|
117
|
+
res = WPScan::Browser.get(url, followlocation: true, maxredirs: 10)
|
|
118
|
+
|
|
119
|
+
res.effective_url == url ? nil : res.effective_url
|
|
120
|
+
end
|
|
121
|
+
# :nocov:
|
|
122
|
+
|
|
123
|
+
# @return [ Hash ] The Typhoeus params to use to perform head requests
|
|
124
|
+
def head_or_get_params
|
|
125
|
+
@head_or_get_params ||= if [0, 405, 501].include?(WPScan::Browser.head(homepage_url).code)
|
|
126
|
+
{ method: :get, maxfilesize: 1 }
|
|
127
|
+
else
|
|
128
|
+
{ method: :head }
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Perform a HEAD request to the path provided, then if its response code
|
|
133
|
+
# is in the array of codes given, a GET is done and the response returned. Otherwise the
|
|
134
|
+
# HEAD response is returned.
|
|
135
|
+
#
|
|
136
|
+
# @param [ String ] path
|
|
137
|
+
# @param [ Array<String> ] codes
|
|
138
|
+
# @param [ Hash ] params The requests params
|
|
139
|
+
# @option params [ Hash ] :head Request params for the HEAD
|
|
140
|
+
# @option params [ hash ] :get Request params for the GET
|
|
141
|
+
#
|
|
142
|
+
# @return [ Typhoeus::Response ]
|
|
143
|
+
def head_and_get(path, codes = [200], params = {})
|
|
144
|
+
url_to_get = url(path)
|
|
145
|
+
head_params = (params[:head] || {}).merge(head_or_get_params)
|
|
146
|
+
|
|
147
|
+
head_res = WPScan::Browser.forge_request(url_to_get, head_params).run
|
|
148
|
+
|
|
149
|
+
codes.include?(head_res.code) ? WPScan::Browser.get(url_to_get, params[:get] || {}) : head_res
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
data/lib/wpscan.rb
CHANGED
|
@@ -5,62 +5,159 @@
|
|
|
5
5
|
# otherwise encoding issues can happen when using JSON format.
|
|
6
6
|
# Not kidding.
|
|
7
7
|
require 'active_support/all'
|
|
8
|
-
require '
|
|
8
|
+
require 'typhoeus'
|
|
9
|
+
require 'nokogiri'
|
|
9
10
|
require 'yajl/json_gem'
|
|
11
|
+
require 'public_suffix'
|
|
10
12
|
require 'addressable/uri'
|
|
11
|
-
|
|
13
|
+
require 'get_process_mem'
|
|
14
|
+
require 'ruby-progressbar'
|
|
15
|
+
require 'opt_parse_validator'
|
|
16
|
+
# Standard Libs
|
|
17
|
+
require 'erb'
|
|
12
18
|
require 'uri'
|
|
13
19
|
require 'time'
|
|
14
|
-
require 'readline'
|
|
15
20
|
require 'securerandom'
|
|
16
21
|
require 'resolv'
|
|
17
|
-
|
|
18
|
-
require '
|
|
22
|
+
require 'fileutils'
|
|
23
|
+
require 'pathname'
|
|
24
|
+
require 'socket'
|
|
25
|
+
require 'timeout'
|
|
26
|
+
require 'xmlrpc/client'
|
|
27
|
+
# Monkey Patches/Fixes
|
|
28
|
+
require 'wpscan/typhoeus/response' # Adds Response#html and from_vuln_api?
|
|
29
|
+
require 'wpscan/typhoeus/hydra' # https://github.com/typhoeus/typhoeus/issues/439
|
|
30
|
+
require 'wpscan/public_suffix/domain' # Adds Domain#match
|
|
31
|
+
require 'wpscan/numeric' # Adds Numeric#bytes_to_human
|
|
19
32
|
# Custom Libs
|
|
33
|
+
require 'wpscan/scan'
|
|
34
|
+
require 'wpscan/parsed_cli'
|
|
20
35
|
require 'wpscan/helper'
|
|
21
|
-
require 'wpscan/
|
|
22
|
-
require 'wpscan/version'
|
|
36
|
+
require 'wpscan/exit_code'
|
|
23
37
|
require 'wpscan/errors'
|
|
24
|
-
require 'wpscan/
|
|
25
|
-
require 'wpscan/browser'
|
|
38
|
+
require 'wpscan/cache/typhoeus'
|
|
26
39
|
require 'wpscan/target'
|
|
27
|
-
require 'wpscan/
|
|
40
|
+
require 'wpscan/browser'
|
|
41
|
+
require 'wpscan/version'
|
|
28
42
|
require 'wpscan/controller'
|
|
29
43
|
require 'wpscan/controllers'
|
|
44
|
+
require 'wpscan/formatter'
|
|
30
45
|
require 'wpscan/references'
|
|
31
|
-
require 'wpscan/
|
|
46
|
+
require 'wpscan/finders'
|
|
32
47
|
require 'wpscan/vulnerability'
|
|
48
|
+
require 'wpscan/vulnerability_filter'
|
|
49
|
+
require 'wpscan/progressbar_null_output'
|
|
50
|
+
require 'wpscan/db'
|
|
51
|
+
require 'wpscan/vulnerable'
|
|
52
|
+
require 'wpscan/http_status_tracking'
|
|
53
|
+
require 'wpscan/browser_authenticator'
|
|
33
54
|
|
|
34
55
|
Encoding.default_external = Encoding::UTF_8
|
|
35
56
|
|
|
36
|
-
# WPScan
|
|
37
57
|
module WPScan
|
|
38
|
-
|
|
58
|
+
class << self
|
|
59
|
+
# The lowercase name of the scanner.
|
|
60
|
+
# Mainly used in directory paths like the default cookie-jar file and
|
|
61
|
+
# path to load the cli options from files.
|
|
62
|
+
def app_name
|
|
63
|
+
'wpscan'
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
extend HttpStatusTracking
|
|
39
68
|
|
|
40
69
|
APP_DIR = Pathname.new(__FILE__).dirname.join('..', 'app').expand_path
|
|
41
|
-
|
|
70
|
+
|
|
71
|
+
# Avoid memory leak when using Hydra, see https://github.com/typhoeus/typhoeus/issues/562
|
|
72
|
+
# Requests are still cached via the provided Cache system
|
|
73
|
+
Typhoeus::Config.memoize = false
|
|
74
|
+
|
|
75
|
+
# XDG support for DB_DIR
|
|
76
|
+
# If the legacy path exists, it will be used. Otherwise, we'll use
|
|
77
|
+
# $XDG_CACHE_HOME/wpscan/db or ~/.cache/wpscan/db when XDG_CACHE_HOME is unset.
|
|
78
|
+
legacy_path = Pathname.new(Dir.home).join(".#{WPScan.app_name}", 'db')
|
|
79
|
+
xdg_path = Pathname.new(ENV['XDG_CACHE_HOME'] || Pathname.new(Dir.home).join('.cache')).join(WPScan.app_name, 'db')
|
|
80
|
+
DB_DIR = legacy_path.exist? ? legacy_path : xdg_path
|
|
42
81
|
|
|
43
82
|
Typhoeus.on_complete do |response|
|
|
44
|
-
|
|
83
|
+
self.cached_requests += 1 if response.cached?
|
|
45
84
|
|
|
46
|
-
|
|
47
|
-
end
|
|
85
|
+
next if response.cached?
|
|
48
86
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
87
|
+
self.total_requests += 1
|
|
88
|
+
self.total_data_sent += response.request_size
|
|
89
|
+
self.total_data_received += response.size
|
|
90
|
+
|
|
91
|
+
# Track HTTP status codes
|
|
92
|
+
increment_status_code(response.code)
|
|
93
|
+
|
|
94
|
+
self.api_requests += 1 if response.respond_to?(:from_vuln_api?) && response.from_vuln_api?
|
|
55
95
|
|
|
56
|
-
|
|
57
|
-
def self.api_requests
|
|
58
|
-
@@api_requests ||= 0
|
|
96
|
+
WPScan::Browser.instance.trottle!
|
|
59
97
|
end
|
|
60
98
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
99
|
+
class << self
|
|
100
|
+
def user_cache_dir
|
|
101
|
+
Pathname.new(ENV['XDG_CACHE_HOME'] || Pathname.new(Dir.home).join('.cache')).join(app_name)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def cached_requests
|
|
105
|
+
@@cached_requests ||= 0
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def cached_requests=(value)
|
|
109
|
+
@@cached_requests = value
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def total_requests
|
|
113
|
+
@@total_requests ||= 0
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def total_requests=(value)
|
|
117
|
+
@@total_requests = value
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def total_data_sent
|
|
121
|
+
@@total_data_sent ||= 0
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def total_data_sent=(value)
|
|
125
|
+
@@total_data_sent = value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def total_data_received
|
|
129
|
+
@@total_data_received ||= 0
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def total_data_received=(value)
|
|
133
|
+
@@total_data_received = value
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Memory at the start of the scan (when Scan.new), in bytes.
|
|
137
|
+
def start_memory
|
|
138
|
+
@@start_memory ||= 0
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def start_memory=(value)
|
|
142
|
+
@@start_memory = value
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def api_requests
|
|
146
|
+
@@api_requests ||= 0
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def api_requests=(value)
|
|
150
|
+
@@api_requests = value
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Command line arguments used to start the scan
|
|
154
|
+
def command_line
|
|
155
|
+
@@command_line ||= ''
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def command_line=(value)
|
|
159
|
+
@@command_line = value
|
|
160
|
+
end
|
|
64
161
|
end
|
|
65
162
|
end
|
|
66
163
|
|