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.
Files changed (253) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +104 -30
  3. data/app/app.rb +26 -0
  4. data/app/controllers/aliases.rb +2 -2
  5. data/app/controllers/authenticated_inventory.rb +43 -0
  6. data/app/controllers/core/cli_options.rb +151 -0
  7. data/app/controllers/core.rb +200 -25
  8. data/app/controllers/custom_directories.rb +1 -1
  9. data/app/controllers/enumeration/cli_options.rb +21 -31
  10. data/app/controllers/enumeration/enum_methods.rb +145 -38
  11. data/app/controllers/enumeration.rb +26 -3
  12. data/app/controllers/interesting_findings.rb +25 -0
  13. data/app/controllers/main_theme.rb +1 -1
  14. data/app/controllers/password_attack.rb +14 -6
  15. data/app/controllers/vuln_api.rb +9 -3
  16. data/app/controllers/wp_version.rb +1 -1
  17. data/app/controllers.rb +1 -0
  18. data/app/finders/backup_folders/known_locations.rb +66 -0
  19. data/app/finders/backup_folders.rb +19 -0
  20. data/app/finders/config_backups/known_filenames.rb +6 -4
  21. data/app/finders/config_backups.rb +1 -1
  22. data/app/finders/db_exports/known_locations.rb +16 -14
  23. data/app/finders/db_exports.rb +1 -1
  24. data/app/finders/interesting_findings/backup_db.rb +1 -1
  25. data/app/finders/interesting_findings/debug_log.rb +1 -1
  26. data/app/finders/interesting_findings/duplicator_installer_log.rb +1 -1
  27. data/app/finders/interesting_findings/emergency_pwd_reset_script.rb +1 -1
  28. data/app/finders/interesting_findings/fantastico_fileslist.rb +21 -0
  29. data/app/finders/interesting_findings/full_path_disclosure.rb +1 -1
  30. data/app/finders/interesting_findings/headers.rb +17 -0
  31. data/app/finders/interesting_findings/mu_plugins.rb +1 -1
  32. data/app/finders/interesting_findings/multisite.rb +1 -1
  33. data/app/finders/interesting_findings/php_disabled.rb +2 -2
  34. data/app/finders/interesting_findings/readme.rb +1 -1
  35. data/app/finders/interesting_findings/registration.rb +1 -1
  36. data/app/finders/interesting_findings/robots_txt.rb +20 -0
  37. data/app/finders/interesting_findings/search_replace_db_2.rb +19 -0
  38. data/app/finders/interesting_findings/tmm_db_migrate.rb +1 -1
  39. data/app/finders/interesting_findings/upload_directory_listing.rb +1 -1
  40. data/app/finders/interesting_findings/upload_sql_dump.rb +2 -2
  41. data/app/finders/interesting_findings/wp_cron.rb +1 -1
  42. data/app/finders/interesting_findings/xml_rpc.rb +61 -0
  43. data/app/finders/interesting_findings.rb +13 -4
  44. data/app/finders/main_theme/css_style_in_homepage.rb +1 -1
  45. data/app/finders/main_theme/urls_in_homepage.rb +3 -7
  46. data/app/finders/main_theme/woo_framework_meta_generator.rb +4 -4
  47. data/app/finders/main_theme.rb +1 -1
  48. data/app/finders/medias/attachment_brute_forcing.rb +2 -2
  49. data/app/finders/medias.rb +1 -1
  50. data/app/finders/passwords/wp_login.rb +2 -2
  51. data/app/finders/passwords/xml_rpc.rb +2 -2
  52. data/app/finders/passwords/xml_rpc_multicall.rb +1 -1
  53. data/app/finders/plugin_version/readme.rb +1 -1
  54. data/app/finders/plugin_version.rb +1 -1
  55. data/app/finders/plugins/known_locations.rb +17 -7
  56. data/app/finders/plugins/urls_in_homepage.rb +3 -7
  57. data/app/finders/plugins/wp_json_api.rb +85 -0
  58. data/app/finders/plugins.rb +2 -1
  59. data/app/finders/theme_version/style.rb +1 -1
  60. data/app/finders/theme_version/woo_framework_meta_generator.rb +1 -1
  61. data/app/finders/theme_version.rb +1 -1
  62. data/app/finders/themes/known_locations.rb +12 -6
  63. data/app/finders/themes/urls_in_homepage.rb +3 -7
  64. data/app/finders/themes/wp_json_api.rb +74 -0
  65. data/app/finders/themes.rb +2 -1
  66. data/app/finders/timthumb_version/bad_request.rb +1 -1
  67. data/app/finders/timthumb_version.rb +1 -1
  68. data/app/finders/timthumbs/known_locations.rb +6 -4
  69. data/app/finders/timthumbs.rb +1 -1
  70. data/app/finders/users/author_id_brute_forcing.rb +11 -7
  71. data/app/finders/users/author_posts.rb +1 -1
  72. data/app/finders/users/author_sitemap.rb +1 -1
  73. data/app/finders/users/login_error_messages.rb +1 -1
  74. data/app/finders/users/oembed_api.rb +3 -1
  75. data/app/finders/users/wp_json_api.rb +11 -7
  76. data/app/finders/users.rb +1 -1
  77. data/app/finders/wp_items/urls_in_page.rb +1 -1
  78. data/app/finders/wp_version/atom_generator.rb +1 -1
  79. data/app/finders/wp_version/rdf_generator.rb +1 -1
  80. data/app/finders/wp_version/readme.rb +1 -1
  81. data/app/finders/wp_version/rss_generator.rb +1 -1
  82. data/app/finders/wp_version/unique_fingerprinting.rb +2 -2
  83. data/app/finders/wp_version.rb +1 -1
  84. data/app/finders.rb +1 -0
  85. data/app/formatters/cli.rb +79 -0
  86. data/app/formatters/cli_no_color.rb +9 -0
  87. data/app/formatters/cli_no_colour.rb +17 -0
  88. data/app/formatters/json.rb +14 -0
  89. data/app/formatters/jsonl.rb +29 -0
  90. data/app/formatters/sarif.rb +311 -0
  91. data/app/models/backup_folder.rb +39 -0
  92. data/app/models/fantastico_fileslist.rb +34 -0
  93. data/app/models/headers.rb +44 -0
  94. data/app/models/interesting_finding.rb +41 -2
  95. data/app/models/plugin.rb +8 -2
  96. data/app/models/robots_txt.rb +31 -0
  97. data/app/models/search_replace_db_2.rb +17 -0
  98. data/app/models/theme.rb +9 -2
  99. data/app/models/timthumb.rb +4 -4
  100. data/app/models/user.rb +35 -0
  101. data/app/models/version.rb +49 -0
  102. data/app/models/wp_item/wordpress_org_data.rb +55 -0
  103. data/app/models/wp_item.rb +116 -14
  104. data/app/models/wp_version.rb +5 -3
  105. data/app/models/xml_rpc.rb +73 -3
  106. data/app/models.rb +2 -1
  107. data/app/user_agents.txt +46 -0
  108. data/app/views/cli/core/banner.erb +3 -3
  109. data/app/views/cli/core/finished.erb +15 -0
  110. data/app/views/cli/core/help.erb +4 -0
  111. data/app/views/cli/core/started.erb +11 -0
  112. data/app/views/cli/enumeration/backup_folders.erb +11 -0
  113. data/app/views/cli/enumeration/plugin.erb +13 -0
  114. data/app/views/cli/enumeration/plugins.erb +1 -12
  115. data/app/views/cli/enumeration/theme.erb +4 -0
  116. data/app/views/cli/enumeration/themes.erb +1 -3
  117. data/app/views/cli/enumeration/user.erb +4 -0
  118. data/app/views/cli/enumeration/users.erb +1 -3
  119. data/app/views/cli/finding.erb +1 -1
  120. data/app/views/cli/interesting_findings/_array.erb +10 -0
  121. data/app/views/cli/interesting_findings/findings.erb +23 -0
  122. data/app/views/cli/scan_aborted.erb +5 -0
  123. data/app/views/cli/update_aborted.erb +5 -0
  124. data/app/views/cli/vuln_api/status.erb +2 -0
  125. data/app/views/cli/vulnerability.erb +6 -0
  126. data/app/views/cli/wp_item.erb +4 -1
  127. data/app/views/json/core/banner.erb +2 -8
  128. data/app/views/json/core/finished.erb +13 -0
  129. data/app/views/json/core/help.erb +4 -0
  130. data/app/views/json/core/started.erb +10 -0
  131. data/app/views/json/enumeration/backup_folders.erb +11 -0
  132. data/app/views/json/enumeration/plugin.erb +15 -0
  133. data/app/views/json/enumeration/theme.erb +5 -0
  134. data/app/views/json/enumeration/user.erb +6 -0
  135. data/app/views/json/finding.erb +8 -2
  136. data/app/views/json/interesting_findings/findings.erb +24 -0
  137. data/app/views/json/notice.erb +1 -0
  138. data/app/views/json/scan_aborted.erb +5 -0
  139. data/app/views/json/update_aborted.erb +5 -0
  140. data/app/views/json/vuln_api/status.erb +2 -0
  141. data/app/views/json/wp_item.erb +4 -1
  142. data/bin/wpscan +1 -0
  143. data/lib/opt_parse_validator/config_files_loader_merger/base.rb +26 -0
  144. data/lib/opt_parse_validator/config_files_loader_merger/json.rb +17 -0
  145. data/lib/opt_parse_validator/config_files_loader_merger/yml.rb +17 -0
  146. data/lib/opt_parse_validator/config_files_loader_merger.rb +62 -0
  147. data/lib/opt_parse_validator/errors.rb +9 -0
  148. data/lib/opt_parse_validator/hacks.rb +19 -0
  149. data/lib/opt_parse_validator/opts/alias.rb +28 -0
  150. data/lib/opt_parse_validator/opts/array.rb +34 -0
  151. data/lib/opt_parse_validator/opts/base.rb +142 -0
  152. data/lib/opt_parse_validator/opts/boolean.rb +19 -0
  153. data/lib/opt_parse_validator/opts/choice.rb +43 -0
  154. data/lib/opt_parse_validator/opts/credentials.rb +15 -0
  155. data/lib/opt_parse_validator/opts/directory_path.rb +17 -0
  156. data/lib/opt_parse_validator/opts/file_path.rb +34 -0
  157. data/lib/opt_parse_validator/opts/headers.rb +33 -0
  158. data/lib/opt_parse_validator/opts/integer.rb +15 -0
  159. data/lib/opt_parse_validator/opts/integer_range.rb +37 -0
  160. data/lib/opt_parse_validator/opts/multi_choices.rb +135 -0
  161. data/lib/opt_parse_validator/opts/path.rb +78 -0
  162. data/lib/opt_parse_validator/opts/positive_integer.rb +16 -0
  163. data/lib/opt_parse_validator/opts/proxy.rb +7 -0
  164. data/lib/opt_parse_validator/opts/regexp.rb +14 -0
  165. data/lib/opt_parse_validator/opts/smart_list.rb +30 -0
  166. data/lib/opt_parse_validator/opts/string.rb +8 -0
  167. data/lib/opt_parse_validator/opts/uri.rb +41 -0
  168. data/lib/opt_parse_validator/opts/url.rb +11 -0
  169. data/lib/opt_parse_validator/opts.rb +9 -0
  170. data/lib/opt_parse_validator/version.rb +6 -0
  171. data/lib/opt_parse_validator.rb +161 -0
  172. data/lib/wpscan/browser/actions.rb +48 -0
  173. data/lib/wpscan/browser/options.rb +92 -0
  174. data/lib/wpscan/browser.rb +87 -2
  175. data/lib/wpscan/browser_authenticator.rb +64 -0
  176. data/lib/wpscan/cache/file_store.rb +77 -0
  177. data/lib/wpscan/cache/typhoeus.rb +25 -0
  178. data/lib/wpscan/controller.rb +100 -4
  179. data/lib/wpscan/controllers.rb +78 -3
  180. data/lib/wpscan/db/dynamic_finders/base.rb +3 -7
  181. data/lib/wpscan/db/dynamic_finders/plugin.rb +2 -2
  182. data/lib/wpscan/db/dynamic_finders/wordpress.rb +1 -1
  183. data/lib/wpscan/db/fingerprints.rb +2 -2
  184. data/lib/wpscan/db/updater.rb +23 -13
  185. data/lib/wpscan/db/vuln_api.rb +25 -9
  186. data/lib/wpscan/db/wp_item.rb +2 -2
  187. data/lib/wpscan/errors/enumeration.rb +4 -4
  188. data/lib/wpscan/errors/http.rb +82 -3
  189. data/lib/wpscan/errors/saml.rb +28 -0
  190. data/lib/wpscan/errors/scan.rb +14 -0
  191. data/lib/wpscan/errors/update.rb +11 -3
  192. data/lib/wpscan/errors/vuln_api.rb +24 -0
  193. data/lib/wpscan/errors/wordpress.rb +2 -2
  194. data/lib/wpscan/errors/wp_auth.rb +37 -0
  195. data/lib/wpscan/errors.rb +4 -3
  196. data/lib/wpscan/exit_code.rb +25 -0
  197. data/lib/wpscan/finders/base_finders.rb +45 -0
  198. data/lib/wpscan/finders/dynamic_finder/finder.rb +1 -1
  199. data/lib/wpscan/finders/dynamic_finder/version/body_pattern.rb +1 -1
  200. data/lib/wpscan/finders/dynamic_finder/version/comment.rb +1 -1
  201. data/lib/wpscan/finders/dynamic_finder/version/header_pattern.rb +1 -1
  202. data/lib/wpscan/finders/dynamic_finder/version/javascript_var.rb +1 -1
  203. data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +3 -5
  204. data/lib/wpscan/finders/dynamic_finder/version/xpath.rb +1 -1
  205. data/lib/wpscan/finders/dynamic_finder/wp_items/finder.rb +3 -3
  206. data/lib/wpscan/finders/dynamic_finder/wp_version.rb +1 -1
  207. data/lib/wpscan/finders/finder/breadth_first_dictionary_attack.rb +257 -0
  208. data/lib/wpscan/finders/finder/enumerator.rb +77 -0
  209. data/lib/wpscan/finders/finder/fingerprinter.rb +48 -0
  210. data/lib/wpscan/finders/finder/smart_url_checker/findings.rb +33 -0
  211. data/lib/wpscan/finders/finder/smart_url_checker.rb +60 -0
  212. data/lib/wpscan/finders/finder/wp_version/smart_url_checker.rb +1 -1
  213. data/lib/wpscan/finders/finder.rb +78 -0
  214. data/lib/wpscan/finders/finding.rb +54 -0
  215. data/lib/wpscan/finders/findings.rb +33 -0
  216. data/lib/wpscan/finders/independent_finder.rb +33 -0
  217. data/lib/wpscan/finders/independent_finders.rb +26 -0
  218. data/lib/wpscan/finders/same_type_finder.rb +19 -0
  219. data/lib/wpscan/finders/same_type_finders.rb +28 -0
  220. data/lib/wpscan/finders/unique_finder.rb +19 -0
  221. data/lib/wpscan/finders/unique_finders.rb +47 -0
  222. data/lib/wpscan/finders.rb +11 -12
  223. data/lib/wpscan/formatter/buffer.rb +17 -0
  224. data/lib/wpscan/formatter.rb +152 -0
  225. data/lib/wpscan/helper.rb +7 -1
  226. data/lib/wpscan/http_status_tracking.rb +128 -0
  227. data/lib/wpscan/numeric.rb +13 -0
  228. data/lib/wpscan/parsed_cli.rb +31 -2
  229. data/lib/wpscan/progressbar_null_output.rb +23 -0
  230. data/lib/wpscan/public_suffix/domain.rb +44 -0
  231. data/lib/wpscan/references.rb +118 -4
  232. data/lib/wpscan/scan.rb +130 -0
  233. data/lib/wpscan/target/hashes.rb +45 -0
  234. data/lib/wpscan/target/platform/php.rb +124 -0
  235. data/lib/wpscan/target/platform/wordpress/custom_directories.rb +3 -3
  236. data/lib/wpscan/target/platform/wordpress.rb +7 -8
  237. data/lib/wpscan/target/platform.rb +3 -0
  238. data/lib/wpscan/target/scope.rb +103 -0
  239. data/lib/wpscan/target/server/apache.rb +27 -0
  240. data/lib/wpscan/target/server/generic.rb +72 -0
  241. data/lib/wpscan/target/server/iis.rb +29 -0
  242. data/lib/wpscan/target/server/nginx.rb +27 -0
  243. data/lib/wpscan/target/server.rb +6 -0
  244. data/lib/wpscan/target.rb +129 -9
  245. data/lib/wpscan/typhoeus/hydra.rb +12 -0
  246. data/lib/wpscan/typhoeus/response.rb +24 -1
  247. data/lib/wpscan/version.rb +1 -1
  248. data/lib/wpscan/vulnerability.rb +157 -5
  249. data/lib/wpscan/vulnerability_filter.rb +68 -0
  250. data/lib/wpscan/vulnerable.rb +13 -1
  251. data/lib/wpscan/web_site.rb +152 -0
  252. data/lib/wpscan.rb +126 -29
  253. 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 'cms_scanner'
8
+ require 'typhoeus'
9
+ require 'nokogiri'
9
10
  require 'yajl/json_gem'
11
+ require 'public_suffix'
10
12
  require 'addressable/uri'
11
- # Standard Lib
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
- # Monkey Patches/Fixes/Override
18
- require 'wpscan/typhoeus/response' # Adds a from_vuln_api? method
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/db'
22
- require 'wpscan/version'
36
+ require 'wpscan/exit_code'
23
37
  require 'wpscan/errors'
24
- require 'wpscan/parsed_cli'
25
- require 'wpscan/browser'
38
+ require 'wpscan/cache/typhoeus'
26
39
  require 'wpscan/target'
27
- require 'wpscan/finders'
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/vulnerable'
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
- include CMSScanner
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
- DB_DIR = Pathname.new(Dir.home).join('.wpscan', 'db')
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
- next if response.cached? || !response.from_vuln_api?
83
+ self.cached_requests += 1 if response.cached?
45
84
 
46
- self.api_requests += 1
47
- end
85
+ next if response.cached?
48
86
 
49
- # Override, otherwise it would be returned as 'wp_scan'
50
- #
51
- # @return [ String ]
52
- def self.app_name
53
- 'wpscan'
54
- end
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
- # @return [ Integer ]
57
- def self.api_requests
58
- @@api_requests ||= 0
96
+ WPScan::Browser.instance.trottle!
59
97
  end
60
98
 
61
- # @param [ Integer ] value
62
- def self.api_requests=(value)
63
- @@api_requests = value
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