wpscan 3.4.5 → 3.5.0

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 (140) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +21 -14
  3. data/app/app.rb +2 -0
  4. data/app/controllers.rb +2 -0
  5. data/app/controllers/aliases.rb +2 -0
  6. data/app/controllers/core.rb +6 -4
  7. data/app/controllers/custom_directories.rb +3 -1
  8. data/app/controllers/enumeration.rb +6 -0
  9. data/app/controllers/enumeration/cli_options.rb +2 -0
  10. data/app/controllers/enumeration/enum_methods.rb +2 -0
  11. data/app/controllers/main_theme.rb +2 -0
  12. data/app/controllers/password_attack.rb +6 -4
  13. data/app/controllers/wp_version.rb +2 -0
  14. data/app/finders.rb +2 -0
  15. data/app/finders/config_backups.rb +2 -0
  16. data/app/finders/config_backups/known_filenames.rb +4 -3
  17. data/app/finders/db_exports.rb +2 -0
  18. data/app/finders/db_exports/known_locations.rb +15 -3
  19. data/app/finders/interesting_findings.rb +2 -0
  20. data/app/finders/interesting_findings/backup_db.rb +5 -4
  21. data/app/finders/interesting_findings/debug_log.rb +3 -1
  22. data/app/finders/interesting_findings/duplicator_installer_log.rb +6 -5
  23. data/app/finders/interesting_findings/emergency_pwd_reset_script.rb +6 -4
  24. data/app/finders/interesting_findings/full_path_disclosure.rb +3 -1
  25. data/app/finders/interesting_findings/mu_plugins.rb +4 -2
  26. data/app/finders/interesting_findings/multisite.rb +3 -1
  27. data/app/finders/interesting_findings/readme.rb +8 -6
  28. data/app/finders/interesting_findings/registration.rb +3 -1
  29. data/app/finders/interesting_findings/tmm_db_migrate.rb +4 -2
  30. data/app/finders/interesting_findings/upload_directory_listing.rb +3 -1
  31. data/app/finders/interesting_findings/upload_sql_dump.rb +8 -10
  32. data/app/finders/interesting_findings/wp_cron.rb +3 -1
  33. data/app/finders/main_theme.rb +2 -0
  34. data/app/finders/main_theme/css_style.rb +3 -1
  35. data/app/finders/main_theme/urls_in_homepage.rb +3 -1
  36. data/app/finders/main_theme/woo_framework_meta_generator.rb +3 -1
  37. data/app/finders/medias.rb +2 -0
  38. data/app/finders/medias/attachment_brute_forcing.rb +3 -1
  39. data/app/finders/passwords.rb +2 -0
  40. data/app/finders/passwords/wp_login.rb +4 -1
  41. data/app/finders/passwords/xml_rpc.rb +2 -0
  42. data/app/finders/passwords/xml_rpc_multicall.rb +4 -2
  43. data/app/finders/plugin_version.rb +4 -2
  44. data/app/finders/plugin_version/readme.rb +9 -5
  45. data/app/finders/plugins.rb +2 -0
  46. data/app/finders/plugins/body_pattern.rb +3 -1
  47. data/app/finders/plugins/comment.rb +3 -1
  48. data/app/finders/plugins/config_parser.rb +3 -1
  49. data/app/finders/plugins/header_pattern.rb +3 -1
  50. data/app/finders/plugins/javascript_var.rb +3 -1
  51. data/app/finders/plugins/known_locations.rb +10 -8
  52. data/app/finders/plugins/query_parameter.rb +2 -0
  53. data/app/finders/plugins/urls_in_homepage.rb +3 -1
  54. data/app/finders/plugins/xpath.rb +3 -1
  55. data/app/finders/theme_version.rb +4 -2
  56. data/app/finders/theme_version/style.rb +3 -1
  57. data/app/finders/theme_version/woo_framework_meta_generator.rb +3 -1
  58. data/app/finders/themes.rb +2 -0
  59. data/app/finders/themes/known_locations.rb +12 -10
  60. data/app/finders/themes/urls_in_homepage.rb +3 -1
  61. data/app/finders/timthumb_version.rb +3 -1
  62. data/app/finders/timthumb_version/bad_request.rb +3 -1
  63. data/app/finders/timthumbs.rb +2 -0
  64. data/app/finders/timthumbs/known_locations.rb +12 -3
  65. data/app/finders/users.rb +2 -0
  66. data/app/finders/users/author_id_brute_forcing.rb +3 -1
  67. data/app/finders/users/author_posts.rb +3 -1
  68. data/app/finders/users/login_error_messages.rb +3 -1
  69. data/app/finders/users/oembed_api.rb +6 -4
  70. data/app/finders/users/rss_generator.rb +7 -5
  71. data/app/finders/users/wp_json_api.rb +16 -6
  72. data/app/finders/users/yoast_seo_author_sitemap.rb +6 -4
  73. data/app/finders/wp_items.rb +2 -0
  74. data/app/finders/wp_items/urls_in_homepage.rb +2 -0
  75. data/app/finders/wp_version.rb +2 -0
  76. data/app/finders/wp_version/atom_generator.rb +2 -0
  77. data/app/finders/wp_version/rdf_generator.rb +2 -0
  78. data/app/finders/wp_version/readme.rb +4 -2
  79. data/app/finders/wp_version/rss_generator.rb +2 -0
  80. data/app/finders/wp_version/unique_fingerprinting.rb +3 -1
  81. data/app/models.rb +8 -0
  82. data/app/models/config_backup.rb +6 -2
  83. data/app/models/db_export.rb +6 -2
  84. data/app/models/interesting_finding.rb +36 -32
  85. data/app/models/media.rb +6 -2
  86. data/app/models/plugin.rb +25 -17
  87. data/app/models/theme.rb +83 -75
  88. data/app/models/timthumb.rb +58 -54
  89. data/app/models/wp_item.rb +140 -128
  90. data/app/models/wp_version.rb +47 -44
  91. data/app/models/xml_rpc.rb +18 -14
  92. data/app/views/cli/wp_item.erb +0 -3
  93. data/app/views/json/wp_item.erb +0 -1
  94. data/bin/wpscan +1 -0
  95. data/lib/wpscan.rb +2 -0
  96. data/lib/wpscan/browser.rb +2 -0
  97. data/lib/wpscan/controller.rb +2 -0
  98. data/lib/wpscan/controllers.rb +2 -0
  99. data/lib/wpscan/db.rb +2 -0
  100. data/lib/wpscan/db/dynamic_finders/base.rb +2 -0
  101. data/lib/wpscan/db/dynamic_finders/plugin.rb +4 -5
  102. data/lib/wpscan/db/dynamic_finders/theme.rb +2 -0
  103. data/lib/wpscan/db/dynamic_finders/wordpress.rb +2 -0
  104. data/lib/wpscan/db/fingerprints.rb +2 -0
  105. data/lib/wpscan/db/plugin.rb +2 -0
  106. data/lib/wpscan/db/plugins.rb +2 -0
  107. data/lib/wpscan/db/theme.rb +2 -0
  108. data/lib/wpscan/db/themes.rb +2 -0
  109. data/lib/wpscan/db/updater.rb +4 -2
  110. data/lib/wpscan/db/wp_item.rb +2 -0
  111. data/lib/wpscan/db/wp_items.rb +2 -0
  112. data/lib/wpscan/db/wp_version.rb +2 -0
  113. data/lib/wpscan/errors.rb +7 -1
  114. data/lib/wpscan/errors/http.rb +27 -23
  115. data/lib/wpscan/errors/update.rb +8 -4
  116. data/lib/wpscan/errors/wordpress.rb +24 -14
  117. data/lib/wpscan/errors/xmlrpc.rb +8 -4
  118. data/lib/wpscan/finders.rb +2 -0
  119. data/lib/wpscan/finders/dynamic_finder/finder.rb +2 -0
  120. data/lib/wpscan/finders/dynamic_finder/version/body_pattern.rb +2 -0
  121. data/lib/wpscan/finders/dynamic_finder/version/comment.rb +2 -0
  122. data/lib/wpscan/finders/dynamic_finder/version/config_parser.rb +2 -0
  123. data/lib/wpscan/finders/dynamic_finder/version/finder.rb +4 -2
  124. data/lib/wpscan/finders/dynamic_finder/version/header_pattern.rb +2 -0
  125. data/lib/wpscan/finders/dynamic_finder/version/javascript_var.rb +2 -0
  126. data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +2 -0
  127. data/lib/wpscan/finders/dynamic_finder/version/xpath.rb +2 -0
  128. data/lib/wpscan/finders/dynamic_finder/wp_item_version.rb +2 -0
  129. data/lib/wpscan/finders/dynamic_finder/wp_items/finder.rb +4 -2
  130. data/lib/wpscan/finders/dynamic_finder/wp_version.rb +4 -2
  131. data/lib/wpscan/finders/finder/wp_version/smart_url_checker.rb +4 -2
  132. data/lib/wpscan/helper.rb +2 -0
  133. data/lib/wpscan/references.rb +2 -0
  134. data/lib/wpscan/target.rb +12 -1
  135. data/lib/wpscan/target/platform/wordpress.rb +15 -1
  136. data/lib/wpscan/target/platform/wordpress/custom_directories.rb +23 -3
  137. data/lib/wpscan/version.rb +3 -1
  138. data/lib/wpscan/vulnerability.rb +2 -0
  139. data/lib/wpscan/vulnerable.rb +2 -0
  140. metadata +35 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
@@ -5,14 +7,14 @@ module WPScan
5
7
  class Readme < CMSScanner::Finders::Finder
6
8
  # @return [ InterestingFinding ]
7
9
  def aggressive(_opts = {})
8
- potential_files.each do |file|
9
- url = target.url(file)
10
- res = Browser.get(url)
10
+ potential_files.each do |path|
11
+ res = target.head_and_get(path)
12
+
13
+ next unless res.code == 200 && res.body =~ /wordpress/i
11
14
 
12
- if res.code == 200 && res.body =~ /wordpress/i
13
- return WPScan::Readme.new(url, confidence: 100, found_by: DIRECT_ACCESS)
14
- end
15
+ return Model::Readme.new(target.url(path), confidence: 100, found_by: DIRECT_ACCESS)
15
16
  end
17
+
16
18
  nil
17
19
  end
18
20
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
@@ -18,7 +20,7 @@ module WPScan
18
20
 
19
21
  target.registration_enabled = true
20
22
 
21
- WPScan::Registration.new(
23
+ Model::Registration.new(
22
24
  res.effective_url,
23
25
  confidence: 100,
24
26
  found_by: DIRECT_ACCESS,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
@@ -7,11 +9,11 @@ module WPScan
7
9
  def aggressive(_opts = {})
8
10
  path = 'wp-content/uploads/tmm_db_migrate/tmm_db_migrate.zip'
9
11
  url = target.url(path)
10
- res = Browser.get(url)
12
+ res = browser.forge_request(url, target.head_or_get_request_params).run
11
13
 
12
14
  return unless res.code == 200 && res.headers['Content-Type'] =~ %r{\Aapplication/zip}i
13
15
 
14
- WPScan::TmmDbMigrate.new(
16
+ Model::TmmDbMigrate.new(
15
17
  url,
16
18
  confidence: 100,
17
19
  found_by: DIRECT_ACCESS,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
@@ -11,7 +13,7 @@ module WPScan
11
13
 
12
14
  url = target.url(path)
13
15
 
14
- WPScan::UploadDirectoryListing.new(
16
+ Model::UploadDirectoryListing.new(
15
17
  url,
16
18
  confidence: 100,
17
19
  found_by: DIRECT_ACCESS,
@@ -1,27 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
4
6
  # UploadSQLDump finder
5
7
  class UploadSQLDump < CMSScanner::Finders::Finder
6
- SQL_PATTERN = /(?:(?:(?:DROP|CREATE) TABLE)|INSERT INTO)/.freeze
8
+ SQL_PATTERN = /(?:DROP|CREATE|(?:UN)?LOCK) TABLE|INSERT INTO/.freeze
7
9
 
8
10
  # @return [ InterestingFinding ]
9
11
  def aggressive(_opts = {})
10
- url = dump_url
11
- res = Browser.get(url)
12
+ path = 'wp-content/uploads/dump.sql'
13
+ res = target.head_and_get(path, [200], get: { headers: { 'Range' => 'bytes=0-3000' } })
12
14
 
13
- return unless res.code == 200 && res.body =~ SQL_PATTERN
15
+ return unless res.body =~ SQL_PATTERN
14
16
 
15
- WPScan::UploadSQLDump.new(
16
- url,
17
+ Model::UploadSQLDump.new(
18
+ target.url(path),
17
19
  confidence: 100,
18
20
  found_by: DIRECT_ACCESS
19
21
  )
20
22
  end
21
-
22
- def dump_url
23
- target.url('wp-content/uploads/dump.sql')
24
- end
25
23
  end
26
24
  end
27
25
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module InterestingFindings
@@ -9,7 +11,7 @@ module WPScan
9
11
 
10
12
  return unless res.code == 200
11
13
 
12
- WPScan::WPCron.new(
14
+ Model::WPCron.new(
13
15
  wp_cron_url,
14
16
  confidence: 60,
15
17
  found_by: DIRECT_ACCESS,
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'main_theme/css_style'
2
4
  require_relative 'main_theme/woo_framework_meta_generator'
3
5
  require_relative 'main_theme/urls_in_homepage'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module MainTheme
@@ -6,7 +8,7 @@ module WPScan
6
8
  include Finders::WpItems::URLsInHomepage
7
9
 
8
10
  def create_theme(slug, style_url, opts)
9
- WPScan::Theme.new(
11
+ Model::Theme.new(
10
12
  slug,
11
13
  target,
12
14
  opts.merge(found_by: found_by, confidence: 70, style_url: style_url)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module MainTheme
@@ -14,7 +16,7 @@ module WPScan
14
16
  slugs = items_from_links('themes', false) + items_from_codes('themes', false)
15
17
 
16
18
  slugs.each_with_object(Hash.new(0)) { |slug, counts| counts[slug] += 1 }.each do |slug, occurences|
17
- found << WPScan::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 2 * occurences))
19
+ found << Model::Theme.new(slug, target, opts.merge(found_by: found_by, confidence: 2 * occurences))
18
20
  end
19
21
 
20
22
  found
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module MainTheme
@@ -10,7 +12,7 @@ module WPScan
10
12
  def passive(opts = {})
11
13
  return unless target.homepage_res.body =~ PATTERN
12
14
 
13
- WPScan::Theme.new(
15
+ Model::Theme.new(
14
16
  Regexp.last_match[1],
15
17
  target,
16
18
  opts.merge(found_by: found_by, confidence: 80)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'medias/attachment_brute_forcing'
2
4
 
3
5
  module WPScan
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Medias
@@ -15,7 +17,7 @@ module WPScan
15
17
  enumerate(target_urls(opts), opts) do |res|
16
18
  next unless res.code == 200
17
19
 
18
- found << WPScan::Media.new(res.effective_url, opts.merge(found_by: found_by, confidence: 100))
20
+ found << Model::Media.new(res.effective_url, opts.merge(found_by: found_by, confidence: 100))
19
21
  end
20
22
 
21
23
  found
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'passwords/wp_login'
2
4
  require_relative 'passwords/xml_rpc'
3
5
  require_relative 'passwords/xml_rpc_multicall'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Passwords
@@ -10,7 +12,8 @@ module WPScan
10
12
  end
11
13
 
12
14
  def valid_credentials?(response)
13
- response.code == 302
15
+ response.code == 302 &&
16
+ response.headers['Set-Cookie']&.any? { |cookie| cookie =~ /wordpress_logged_in_/i }
14
17
  end
15
18
 
16
19
  def errored_response?(response)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Passwords
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Passwords
@@ -20,13 +22,13 @@ module WPScan
20
22
  target.multi_call(methods).run
21
23
  end
22
24
 
23
- # @param [ Array<CMSScanner::User> ] users
25
+ # @param [ Array<Model::User> ] users
24
26
  # @param [ Array<String> ] passwords
25
27
  # @param [ Hash ] opts
26
28
  # @option opts [ Boolean ] :show_progression
27
29
  # @option opts [ Integer ] :multicall_max_passwords
28
30
  #
29
- # @yield [ CMSScanner::User ] When a valid combination is found
31
+ # @yield [ Model::User ] When a valid combination is found
30
32
  #
31
33
  # TODO: Make rubocop happy about metrics etc
32
34
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'plugin_version/readme'
2
4
 
3
5
  module WPScan
@@ -7,7 +9,7 @@ module WPScan
7
9
  class Base
8
10
  include CMSScanner::Finders::UniqueFinder
9
11
 
10
- # @param [ WPScan::Plugin ] plugin
12
+ # @param [ Model::Plugin ] plugin
11
13
  def initialize(plugin)
12
14
  finders << PluginVersion::Readme.new(plugin)
13
15
 
@@ -16,7 +18,7 @@ module WPScan
16
18
 
17
19
  # Load the finders associated with the plugin
18
20
  #
19
- # @param [ WPScan::Plugin ] plugin
21
+ # @param [ Model::Plugin ] plugin
20
22
  def load_specific_finders(plugin)
21
23
  module_name = plugin.classify
22
24
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module PluginVersion
@@ -7,21 +9,23 @@ module WPScan
7
9
  def aggressive(_opts = {})
8
10
  found_by_msg = 'Readme - %s (Aggressive Detection)'
9
11
 
10
- WPScan::WpItem::READMES.each do |file|
11
- url = target.url(file)
12
- res = Browser.get(url)
12
+ # The target(plugin)#readme_url can't be used directly here
13
+ # as if the --detection-mode is passive, it will always return nil
14
+ Model::WpItem::READMES.each do |file|
15
+ res = target.head_and_get(file)
13
16
 
14
17
  next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?
15
18
 
16
19
  return numbers.reduce([]) do |a, e|
17
- a << WPScan::Version.new(
20
+ a << Model::Version.new(
18
21
  e[0],
19
22
  found_by: format(found_by_msg, e[1]),
20
23
  confidence: e[2],
21
- interesting_entries: [url]
24
+ interesting_entries: [res.effective_url]
22
25
  )
23
26
  end
24
27
  end
28
+
25
29
  nil
26
30
  end
27
31
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'plugins/urls_in_homepage'
2
4
  require_relative 'plugins/known_locations'
3
5
  # From the DynamicFinders
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -15,7 +17,7 @@ module WPScan
15
17
  def process_response(opts, response, slug, klass, config)
16
18
  return unless response.body =~ config['pattern']
17
19
 
18
- Plugin.new(
20
+ Model::Plugin.new(
19
21
  slug,
20
22
  target,
21
23
  opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -18,7 +20,7 @@ module WPScan
18
20
 
19
21
  next unless comment =~ config['pattern']
20
22
 
21
- return Plugin.new(
23
+ return Model::Plugin.new(
22
24
  slug,
23
25
  target,
24
26
  opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -19,7 +21,7 @@ module WPScan
19
21
  # when checking for plugins
20
22
  #
21
23
 
22
- Plugin.new(
24
+ Model::Plugin.new(
23
25
  slug,
24
26
  target,
25
27
  opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -18,7 +20,7 @@ module WPScan
18
20
  configs.each do |klass, config|
19
21
  next unless headers[config['header']] && headers[config['header']].to_s =~ config['pattern']
20
22
 
21
- found << Plugin.new(
23
+ found << Model::Plugin.new(
22
24
  slug,
23
25
  target,
24
26
  opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -16,7 +18,7 @@ module WPScan
16
18
  response.html.xpath(config['xpath'] || '//script[not(@src)]').each do |node|
17
19
  next if config['pattern'] && !node.text.match(config['pattern'])
18
20
 
19
- return Plugin.new(
21
+ return Model::Plugin.new(
20
22
  slug,
21
23
  target,
22
24
  opts.merge(found_by: found_by(klass), confidence: config['confidence'] || DEFAULT_CONFIDENCE)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module Plugins
@@ -5,6 +7,11 @@ module WPScan
5
7
  class KnownLocations < CMSScanner::Finders::Finder
6
8
  include CMSScanner::Finders::Finder::Enumerator
7
9
 
10
+ # @return [ Array<Integer> ]
11
+ def valid_response_codes
12
+ @valid_response_codes ||= [200, 401, 403, 301, 500].freeze
13
+ end
14
+
8
15
  # @param [ Hash ] opts
9
16
  # @option opts [ String ] :list
10
17
  #
@@ -12,12 +19,8 @@ module WPScan
12
19
  def aggressive(opts = {})
13
20
  found = []
14
21
 
15
- enumerate(target_urls(opts), opts) do |res, slug|
16
- # TODO: follow the location (from enumerate()) and remove the 301 here ?
17
- # As a result, it might remove false positive due to redirection to the homepage
18
- next unless [200, 401, 403, 301].include?(res.code)
19
-
20
- found << WPScan::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
22
+ enumerate(target_urls(opts), opts.merge(check_full_response: [200, 401, 403, 500])) do |_res, slug|
23
+ found << Model::Plugin.new(slug, target, opts.merge(found_by: found_by, confidence: 80))
21
24
  end
22
25
 
23
26
  found
@@ -30,10 +33,9 @@ module WPScan
30
33
  def target_urls(opts = {})
31
34
  slugs = opts[:list] || DB::Plugins.vulnerable_slugs
32
35
  urls = {}
33
- plugins_url = target.plugins_url
34
36
 
35
37
  slugs.each do |slug|
36
- urls["#{plugins_url}#{URI.encode(slug)}/"] = slug
38
+ urls[target.plugin_url(slug)] = slug
37
39
  end
38
40
 
39
41
  urls