wpscan 3.4.5 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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