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
@@ -4,6 +4,5 @@
4
4
  "last_updated": <%= @wp_item.last_updated.to_json %>,
5
5
  "outdated": <%= @wp_item.outdated?.to_json %>,
6
6
  "readme_url": <%= @wp_item.readme_url.to_json %>,
7
- "changelog_url": <%= @wp_item.changelog_url.to_json %>,
8
7
  "directory_listing": <%= @wp_item.directory_listing?.to_json %>,
9
8
  "error_log_url": <% if @wp_item.error_log? %><%= @wp_item.url('error_log').to_json %><% else %>null<% end %>
data/bin/wpscan CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'wpscan'
4
5
 
data/lib/wpscan.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Gems
2
4
  # Believe it or not, active_support MUST be the first one,
3
5
  # otherwise encoding issues can happen when using JSON format.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  # Custom Browser
3
5
  class Browser < CMSScanner::Browser
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  # Needed to load at least the Core controller
3
5
  # Otherwise, the following error will be raised:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  # Override to set the OptParser's summary width to 45 (instead of 40 from the CMSScanner)
3
5
  class Controllers < CMSScanner::Controllers
data/lib/wpscan/db.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'db/wp_item'
2
4
  require_relative 'db/updater'
3
5
  require_relative 'db/wp_items'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  module DynamicFinders
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  module DynamicFinders
@@ -60,7 +62,7 @@ module WPScan
60
62
 
61
63
  # @param [ String ] slug
62
64
  # @return [ Constant ]
63
- def self.maybe_create_modudle(slug)
65
+ def self.maybe_create_module(slug)
64
66
  # What about slugs such as js_composer which will be done as JsComposer, just like js-composer
65
67
  constant_name = classify_slug(slug)
66
68
 
@@ -73,10 +75,7 @@ module WPScan
73
75
 
74
76
  def self.create_versions_finders
75
77
  versions_finders_configs.each do |slug, finders|
76
- # Kind of an issue here, module is created even if there is no valid classes
77
- # Could put the #maybe_ directly in the #send() BUT it would be checked everytime,
78
- # which is kind of a waste
79
- mod = maybe_create_modudle(slug)
78
+ mod = maybe_create_module(slug)
80
79
 
81
80
  finders.each do |finder_class, config|
82
81
  klass = config['class'] || finder_class
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  module DynamicFinders
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  module DynamicFinders
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # Fingerprints class
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # Plugin DB
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # WP Plugins
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # Theme DB
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # WP Themes
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # Class used to perform DB updates
@@ -80,7 +82,7 @@ module WPScan
80
82
  url = "#{remote_file_url(filename)}.sha512"
81
83
 
82
84
  res = Browser.get(url, request_params)
83
- raise DownloadError, res if res.timed_out? || res.code != 200
85
+ raise Error::Download, res if res.timed_out? || res.code != 200
84
86
 
85
87
  res.body.chomp
86
88
  end
@@ -121,7 +123,7 @@ module WPScan
121
123
  file_url = remote_file_url(filename)
122
124
 
123
125
  res = Browser.get(file_url, request_params)
124
- raise DownloadError, res if res.timed_out? || res.code != 200
126
+ raise Error::Download, res if res.timed_out? || res.code != 200
125
127
 
126
128
  File.open(file_path, 'wb') { |f| f.write(res.body) }
127
129
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # WpItem - super DB class for Plugin, Theme and Version
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # WP Items
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module DB
3
5
  # WP Version
data/lib/wpscan/errors.rb CHANGED
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
- class Error < StandardError
4
+ module Error
5
+ include CMSScanner::Error
6
+
7
+ class Standard < StandardError
8
+ end
3
9
  end
4
10
  end
5
11
 
@@ -1,34 +1,38 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
- # HTTP Error
3
- class HTTPError < Error
4
- attr_reader :response
4
+ module Error
5
+ # HTTP Error
6
+ class HTTP < Standard
7
+ attr_reader :response
5
8
 
6
- # @param [ Typhoeus::Response ] res
7
- def initialize(response)
8
- @response = response
9
- end
9
+ # @param [ Typhoeus::Response ] res
10
+ def initialize(response)
11
+ @response = response
12
+ end
10
13
 
11
- def failure_details
12
- msg = response.effective_url
14
+ def failure_details
15
+ msg = response.effective_url
13
16
 
14
- msg += if response.code.zero? || response.timed_out?
15
- " (#{response.return_message})"
16
- else
17
- " (status: #{response.code})"
18
- end
17
+ msg += if response.code.zero? || response.timed_out?
18
+ " (#{response.return_message})"
19
+ else
20
+ " (status: #{response.code})"
21
+ end
19
22
 
20
- msg
21
- end
23
+ msg
24
+ end
22
25
 
23
- def to_s
24
- "HTTP Error: #{failure_details}"
26
+ def to_s
27
+ "HTTP Error: #{failure_details}"
28
+ end
25
29
  end
26
- end
27
30
 
28
- # Used in the Updater
29
- class DownloadError < HTTPError
30
- def to_s
31
- "Unable to get #{failure_details}"
31
+ # Used in the Updater
32
+ class Download < HTTP
33
+ def to_s
34
+ "Unable to get #{failure_details}"
35
+ end
32
36
  end
33
37
  end
34
38
  end
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
- # Error raised when there is a missing DB file and --no-update supplied
3
- class MissingDatabaseFile < Error
4
- def to_s
5
- 'Update required, you can not run a scan if a database file is missing.'
4
+ module Error
5
+ # Error raised when there is a missing DB file and --no-update supplied
6
+ class MissingDatabaseFile < Standard
7
+ def to_s
8
+ 'Update required, you can not run a scan if a database file is missing.'
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -1,22 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
- # WordPress hosted (*.wordpress.com)
3
- class WordPressHostedError < Error
4
- def to_s
5
- 'Scanning *.wordpress.com hosted blogs is not supported.'
4
+ module Error
5
+ # WordPress hosted (*.wordpress.com)
6
+ class WordPressHosted < Standard
7
+ def to_s
8
+ 'Scanning *.wordpress.com hosted blogs is not supported.'
9
+ end
6
10
  end
7
- end
8
11
 
9
- # Not WordPress Error
10
- class NotWordPressError < Error
11
- def to_s
12
- 'The remote website is up, but does not seem to be running WordPress.'
12
+ # Not WordPress Error
13
+ class NotWordPress < Standard
14
+ def to_s
15
+ 'The remote website is up, but does not seem to be running WordPress.'
16
+ end
17
+ end
18
+
19
+ # Invalid Wp Version (used in the WpVersion#new)
20
+ class InvalidWordPressVersion < Standard
21
+ def to_s
22
+ 'The WordPress version is invalid'
23
+ end
13
24
  end
14
- end
15
25
 
16
- # Invalid Wp Version (used in the WpVersion#new)
17
- class InvalidWordPressVersion < Error
18
- def to_s
19
- 'The WordPress version is invalid'
26
+ class WpContentDirNotDetected < Standard
27
+ def to_s
28
+ 'Unable to identify the wp-content dir, please supply it with --wp-content-dir'
29
+ end
20
30
  end
21
31
  end
22
32
  end
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
- # XML-RPC Not Detected
3
- class XMLRPCNotDetected < Error
4
- def to_s
5
- 'The XML-RPC Interface was not detected.'
4
+ module Error
5
+ # XML-RPC Not Detected
6
+ class XMLRPCNotDetected < Standard
7
+ def to_s
8
+ 'The XML-RPC Interface was not detected.'
9
+ end
6
10
  end
7
11
  end
8
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'wpscan/finders/finder/wp_version/smart_url_checker'
2
4
 
3
5
  require 'wpscan/finders/dynamic_finder/finder'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -9,9 +11,9 @@ module WPScan
9
11
 
10
12
  # @param [ String ] number
11
13
  # @param [ Hash ] finding_opts
12
- # @return [ WPScan::Version ]
14
+ # @return [ Model::Version ]
13
15
  def create_version(number, finding_opts)
14
- WPScan::Version.new(number, version_finding_opts(finding_opts))
16
+ Model::Version.new(number, version_finding_opts(finding_opts))
15
17
  end
16
18
 
17
19
  # @param [ Hash ] opts
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module WPScan
2
4
  module Finders
3
5
  module DynamicFinder
@@ -31,7 +33,7 @@ module WPScan
31
33
  configs.each do |klass, config|
32
34
  item = process_response(opts, target.homepage_res, slug, klass, config)
33
35
 
34
- found << item if item.is_a?(WpItem)
36
+ found << item if item.is_a?(Model::WpItem)
35
37
  end
36
38
  end
37
39
 
@@ -70,7 +72,7 @@ module WPScan
70
72
 
71
73
  item = process_response(opts, response, slug, klass, config)
72
74
 
73
- found << item if item.is_a?(WpItem)
75
+ found << item if item.is_a?(Model::WpItem)
74
76
  end
75
77
  end
76
78