wpscan 3.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 (180) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile.lock +139 -0
  3. data/LICENSE +74 -0
  4. data/README.md +146 -0
  5. data/app/app.rb +3 -0
  6. data/app/controllers.rb +6 -0
  7. data/app/controllers/brute_force.rb +126 -0
  8. data/app/controllers/core.rb +104 -0
  9. data/app/controllers/custom_directories.rb +23 -0
  10. data/app/controllers/enumeration.rb +53 -0
  11. data/app/controllers/enumeration/cli_options.rb +126 -0
  12. data/app/controllers/enumeration/enum_methods.rb +157 -0
  13. data/app/controllers/main_theme.rb +27 -0
  14. data/app/controllers/wp_version.rb +30 -0
  15. data/app/finders.rb +13 -0
  16. data/app/finders/config_backups.rb +17 -0
  17. data/app/finders/config_backups/known_filenames.rb +46 -0
  18. data/app/finders/interesting_findings.rb +33 -0
  19. data/app/finders/interesting_findings/backup_db.rb +25 -0
  20. data/app/finders/interesting_findings/debug_log.rb +20 -0
  21. data/app/finders/interesting_findings/duplicator_installer_log.rb +23 -0
  22. data/app/finders/interesting_findings/full_path_disclosure.rb +23 -0
  23. data/app/finders/interesting_findings/mu_plugins.rb +48 -0
  24. data/app/finders/interesting_findings/multisite.rb +29 -0
  25. data/app/finders/interesting_findings/readme.rb +26 -0
  26. data/app/finders/interesting_findings/registration.rb +31 -0
  27. data/app/finders/interesting_findings/tmm_db_migrate.rb +24 -0
  28. data/app/finders/interesting_findings/upload_directory_listing.rb +24 -0
  29. data/app/finders/interesting_findings/upload_sql_dump.rb +28 -0
  30. data/app/finders/main_theme.rb +22 -0
  31. data/app/finders/main_theme/css_style.rb +43 -0
  32. data/app/finders/main_theme/urls_in_homepage.rb +25 -0
  33. data/app/finders/main_theme/woo_framework_meta_generator.rb +22 -0
  34. data/app/finders/medias.rb +17 -0
  35. data/app/finders/medias/attachment_brute_forcing.rb +44 -0
  36. data/app/finders/plugin_version.rb +44 -0
  37. data/app/finders/plugin_version/layer_slider/translation_file.rb +40 -0
  38. data/app/finders/plugin_version/readme.rb +79 -0
  39. data/app/finders/plugin_version/revslider/release_log.rb +35 -0
  40. data/app/finders/plugin_version/sitepress_multilingual_cms/meta_generator.rb +27 -0
  41. data/app/finders/plugin_version/sitepress_multilingual_cms/version_parameter.rb +31 -0
  42. data/app/finders/plugin_version/w3_total_cache/headers.rb +28 -0
  43. data/app/finders/plugins.rb +24 -0
  44. data/app/finders/plugins/comments.rb +31 -0
  45. data/app/finders/plugins/headers.rb +36 -0
  46. data/app/finders/plugins/known_locations.rb +48 -0
  47. data/app/finders/plugins/urls_in_homepage.rb +29 -0
  48. data/app/finders/theme_version.rb +41 -0
  49. data/app/finders/theme_version/style.rb +43 -0
  50. data/app/finders/theme_version/woo_framework_meta_generator.rb +19 -0
  51. data/app/finders/themes.rb +20 -0
  52. data/app/finders/themes/known_locations.rb +48 -0
  53. data/app/finders/themes/urls_in_homepage.rb +23 -0
  54. data/app/finders/timthumb_version.rb +17 -0
  55. data/app/finders/timthumb_version/bad_request.rb +21 -0
  56. data/app/finders/timthumbs.rb +17 -0
  57. data/app/finders/timthumbs/known_locations.rb +56 -0
  58. data/app/finders/users.rb +24 -0
  59. data/app/finders/users/author_id_brute_forcing.rb +111 -0
  60. data/app/finders/users/author_posts.rb +61 -0
  61. data/app/finders/users/login_error_messages.rb +50 -0
  62. data/app/finders/users/wp_json_api.rb +31 -0
  63. data/app/finders/wp_items.rb +1 -0
  64. data/app/finders/wp_items/urls_in_homepage.rb +68 -0
  65. data/app/finders/wp_version.rb +34 -0
  66. data/app/finders/wp_version/atom_generator.rb +40 -0
  67. data/app/finders/wp_version/meta_generator.rb +27 -0
  68. data/app/finders/wp_version/opml_generator.rb +23 -0
  69. data/app/finders/wp_version/rdf_generator.rb +38 -0
  70. data/app/finders/wp_version/readme.rb +28 -0
  71. data/app/finders/wp_version/rss_generator.rb +43 -0
  72. data/app/finders/wp_version/sitemap_generator.rb +23 -0
  73. data/app/finders/wp_version/stylesheets.rb +55 -0
  74. data/app/finders/wp_version/unique_fingerprinting.rb +64 -0
  75. data/app/models.rb +10 -0
  76. data/app/models/config_backup.rb +5 -0
  77. data/app/models/interesting_finding.rb +6 -0
  78. data/app/models/media.rb +5 -0
  79. data/app/models/plugin.rb +25 -0
  80. data/app/models/theme.rb +99 -0
  81. data/app/models/timthumb.rb +74 -0
  82. data/app/models/user.rb +31 -0
  83. data/app/models/wp_item.rb +142 -0
  84. data/app/models/wp_version.rb +49 -0
  85. data/app/models/xml_rpc.rb +19 -0
  86. data/app/views/cli/brute_force/error.erb +1 -0
  87. data/app/views/cli/brute_force/found.erb +2 -0
  88. data/app/views/cli/brute_force/users.erb +9 -0
  89. data/app/views/cli/core/banner.erb +14 -0
  90. data/app/views/cli/core/db_update_finished.erb +8 -0
  91. data/app/views/cli/core/db_update_started.erb +1 -0
  92. data/app/views/cli/core/not_fully_configured.erb +1 -0
  93. data/app/views/cli/enumeration/config_backups.erb +11 -0
  94. data/app/views/cli/enumeration/medias.erb +11 -0
  95. data/app/views/cli/enumeration/plugins.erb +35 -0
  96. data/app/views/cli/enumeration/themes.erb +11 -0
  97. data/app/views/cli/enumeration/timthumbs.erb +18 -0
  98. data/app/views/cli/enumeration/users.erb +11 -0
  99. data/app/views/cli/finding.erb +32 -0
  100. data/app/views/cli/info.erb +1 -0
  101. data/app/views/cli/main_theme/theme.erb +6 -0
  102. data/app/views/cli/notice.erb +1 -0
  103. data/app/views/cli/theme.erb +64 -0
  104. data/app/views/cli/usage.erb +3 -0
  105. data/app/views/cli/vulnerability.erb +14 -0
  106. data/app/views/cli/wp_version/version.erb +6 -0
  107. data/app/views/json/brute_force/users.erb +10 -0
  108. data/app/views/json/core/banner.erb +12 -0
  109. data/app/views/json/core/db_update_finished.erb +2 -0
  110. data/app/views/json/core/db_update_started.erb +1 -0
  111. data/app/views/json/core/not_fully_configured.erb +1 -0
  112. data/app/views/json/enumeration/config_backups.erb +10 -0
  113. data/app/views/json/enumeration/medias.erb +10 -0
  114. data/app/views/json/enumeration/plugins.erb +25 -0
  115. data/app/views/json/enumeration/themes.erb +10 -0
  116. data/app/views/json/enumeration/timthumbs.erb +19 -0
  117. data/app/views/json/enumeration/users.erb +11 -0
  118. data/app/views/json/finding.erb +26 -0
  119. data/app/views/json/main_theme/theme.erb +7 -0
  120. data/app/views/json/theme.erb +38 -0
  121. data/app/views/json/wp_version/version.erb +8 -0
  122. data/bin/wpscan +15 -0
  123. data/coverage/assets/0.10.0/application.css +799 -0
  124. data/coverage/assets/0.10.0/application.js +1707 -0
  125. data/coverage/assets/0.10.0/colorbox/border.png +0 -0
  126. data/coverage/assets/0.10.0/colorbox/controls.png +0 -0
  127. data/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
  128. data/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
  129. data/coverage/assets/0.10.0/favicon_green.png +0 -0
  130. data/coverage/assets/0.10.0/favicon_red.png +0 -0
  131. data/coverage/assets/0.10.0/favicon_yellow.png +0 -0
  132. data/coverage/assets/0.10.0/loading.gif +0 -0
  133. data/coverage/assets/0.10.0/magnify.png +0 -0
  134. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  135. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  136. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  137. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  138. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  139. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  140. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  141. data/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  142. data/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  143. data/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  144. data/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  145. data/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  146. data/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  147. data/coverage/index.html +27510 -0
  148. data/lib/wpscan.rb +44 -0
  149. data/lib/wpscan/browser.rb +16 -0
  150. data/lib/wpscan/controller.rb +8 -0
  151. data/lib/wpscan/controllers.rb +8 -0
  152. data/lib/wpscan/db.rb +28 -0
  153. data/lib/wpscan/db/dynamic_finders.rb +63 -0
  154. data/lib/wpscan/db/plugin.rb +11 -0
  155. data/lib/wpscan/db/plugins.rb +11 -0
  156. data/lib/wpscan/db/schema.rb +39 -0
  157. data/lib/wpscan/db/theme.rb +11 -0
  158. data/lib/wpscan/db/themes.rb +11 -0
  159. data/lib/wpscan/db/updater.rb +148 -0
  160. data/lib/wpscan/db/wp_item.rb +18 -0
  161. data/lib/wpscan/db/wp_items.rb +21 -0
  162. data/lib/wpscan/db/wp_version.rb +11 -0
  163. data/lib/wpscan/errors/http.rb +34 -0
  164. data/lib/wpscan/errors/update.rb +8 -0
  165. data/lib/wpscan/errors/wordpress.rb +22 -0
  166. data/lib/wpscan/finders.rb +14 -0
  167. data/lib/wpscan/finders/finder/plugin_version/comments.rb +25 -0
  168. data/lib/wpscan/finders/finder/wp_version/smart_url_checker.rb +23 -0
  169. data/lib/wpscan/helper.rb +6 -0
  170. data/lib/wpscan/references.rb +31 -0
  171. data/lib/wpscan/target.rb +81 -0
  172. data/lib/wpscan/target/platform/wordpress.rb +74 -0
  173. data/lib/wpscan/target/platform/wordpress/custom_directories.rb +93 -0
  174. data/lib/wpscan/version.rb +4 -0
  175. data/lib/wpscan/vulnerability.rb +25 -0
  176. data/lib/wpscan/vulnerable.rb +10 -0
  177. data/wpscan-v3.sublime-project +8 -0
  178. data/wpscan-v3.sublime-workspace +895 -0
  179. data/wpscan.gemspec +55 -0
  180. metadata +419 -0
@@ -0,0 +1,28 @@
1
+ module WPScan
2
+ module Finders
3
+ module InterestingFindings
4
+ # UploadSQLDump finder
5
+ class UploadSQLDump < CMSScanner::Finders::Finder
6
+ SQL_PATTERN = /(?:(?:(?:DROP|CREATE) TABLE)|INSERT INTO)/
7
+
8
+ # @return [ InterestingFinding ]
9
+ def aggressive(_opts = {})
10
+ url = dump_url
11
+ res = Browser.get(url)
12
+
13
+ return unless res.code == 200 && res.body =~ SQL_PATTERN
14
+
15
+ WPScan::InterestingFinding.new(
16
+ url,
17
+ confidence: 100,
18
+ found_by: DIRECT_ACCESS
19
+ )
20
+ end
21
+
22
+ def dump_url
23
+ target.url('wp-content/uploads/dump.sql')
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'main_theme/css_style'
2
+ require_relative 'main_theme/woo_framework_meta_generator'
3
+ require_relative 'main_theme/urls_in_homepage'
4
+
5
+ module WPScan
6
+ module Finders
7
+ module MainTheme
8
+ # Main Theme Finder
9
+ class Base
10
+ include CMSScanner::Finders::UniqueFinder
11
+
12
+ # @param [ WPScan::Target ] target
13
+ def initialize(target)
14
+ finders <<
15
+ MainTheme::CssStyle.new(target) <<
16
+ MainTheme::WooFrameworkMetaGenerator.new(target) <<
17
+ MainTheme::UrlsInHomepage.new(target)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,43 @@
1
+ module WPScan
2
+ module Finders
3
+ module MainTheme
4
+ # From the css style
5
+ class CssStyle < CMSScanner::Finders::Finder
6
+ include Finders::WpItems::URLsInHomepage
7
+
8
+ def create_theme(name, style_url, opts)
9
+ WPScan::Theme.new(
10
+ name,
11
+ target,
12
+ opts.merge(found_by: found_by, confidence: 70, style_url: style_url)
13
+ )
14
+ end
15
+
16
+ def passive(opts = {})
17
+ passive_from_css_href(target.homepage_res, opts) || passive_from_style_code(target.homepage_res, opts)
18
+ end
19
+
20
+ def passive_from_css_href(res, opts)
21
+ target.in_scope_urls(res, '//style|//link') do |url|
22
+ next unless Addressable::URI.parse(url).path =~ %r{/themes/([^\/]+)/style.css\z}i
23
+
24
+ return create_theme(Regexp.last_match[1], url, opts)
25
+ end
26
+ nil
27
+ end
28
+
29
+ def passive_from_style_code(res, opts)
30
+ res.html.css('style').each do |tag|
31
+ code = tag.text.to_s
32
+ next if code.empty?
33
+
34
+ next unless code =~ %r{#{item_code_pattern('themes')}\\?/style\.css[^"'\( ]*}i
35
+
36
+ return create_theme(Regexp.last_match[1], Regexp.last_match[0].strip, opts)
37
+ end
38
+ nil
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ module WPScan
2
+ module Finders
3
+ module MainTheme
4
+ # URLs In Homepage Finder
5
+ class UrlsInHomepage < CMSScanner::Finders::Finder
6
+ include WpItems::URLsInHomepage
7
+
8
+ # @param [ Hash ] opts
9
+ #
10
+ # @return [ Array<Theme> ]
11
+ def passive(opts = {})
12
+ found = []
13
+
14
+ names = items_from_links('themes', false) + items_from_codes('themes', false)
15
+
16
+ names.each_with_object(Hash.new(0)) { |name, counts| counts[name] += 1 }.each do |name, occurences|
17
+ found << WPScan::Theme.new(name, target, opts.merge(found_by: found_by, confidence: 2 * occurences))
18
+ end
19
+
20
+ found
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module WPScan
2
+ module Finders
3
+ module MainTheme
4
+ # From the WooFramework meta generators
5
+ class WooFrameworkMetaGenerator < CMSScanner::Finders::Finder
6
+ THEME_PATTERN = %r{<meta name="generator" content="([^\s"]+)\s?([^"]+)?"\s+/?>}
7
+ FRAMEWORK_PATTERN = %r{<meta name="generator" content="WooFramework\s?([^"]+)?"\s+/?>}
8
+ PATTERN = /#{THEME_PATTERN}\s+#{FRAMEWORK_PATTERN}/i
9
+
10
+ def passive(opts = {})
11
+ return unless target.homepage_res.body =~ PATTERN
12
+
13
+ WPScan::Theme.new(
14
+ Regexp.last_match[1],
15
+ target,
16
+ opts.merge(found_by: found_by, confidence: 80)
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'medias/attachment_brute_forcing'
2
+
3
+ module WPScan
4
+ module Finders
5
+ module Medias
6
+ # Medias Finder
7
+ class Base
8
+ include CMSScanner::Finders::SameTypeFinder
9
+
10
+ # @param [ WPScan::Target ] target
11
+ def initialize(target)
12
+ finders << Medias::AttachmentBruteForcing.new(target)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,44 @@
1
+ module WPScan
2
+ module Finders
3
+ module Medias
4
+ # Medias Finder
5
+ class AttachmentBruteForcing < CMSScanner::Finders::Finder
6
+ include CMSScanner::Finders::Finder::Enumerator
7
+
8
+ # @param [ Hash ] opts
9
+ # @option opts [ Range ] :range Mandatory
10
+ #
11
+ # @return [ Array<Media> ]
12
+ def aggressive(opts = {})
13
+ found = []
14
+
15
+ enumerate(target_urls(opts), opts) do |res|
16
+ next unless res.code == 200
17
+
18
+ found << WPScan::Media.new(res.effective_url, opts.merge(found_by: found_by, confidence: 100))
19
+ end
20
+
21
+ found
22
+ end
23
+
24
+ # @param [ Hash ] opts
25
+ # @option opts [ Range ] :range Mandatory
26
+ #
27
+ # @return [ Hash ]
28
+ def target_urls(opts = {})
29
+ urls = {}
30
+
31
+ opts[:range].each do |id|
32
+ urls[target.uri.join("?attachment_id=#{id}").to_s] = id
33
+ end
34
+
35
+ urls
36
+ end
37
+
38
+ def create_progress_bar(opts = {})
39
+ super(opts.merge(title: ' Brute Forcing Attachment Ids -'))
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'plugin_version/readme'
2
+ # Plugins Specific
3
+ require_relative 'plugin_version/layer_slider/translation_file'
4
+ require_relative 'plugin_version/revslider/release_log'
5
+ require_relative 'plugin_version/sitepress_multilingual_cms/version_parameter'
6
+ require_relative 'plugin_version/sitepress_multilingual_cms/meta_generator'
7
+ require_relative 'plugin_version/w3_total_cache/headers'
8
+
9
+ module WPScan
10
+ module Finders
11
+ module PluginVersion
12
+ # Plugin Version Finder
13
+ class Base
14
+ include CMSScanner::Finders::UniqueFinder
15
+
16
+ # @param [ WPScan::Plugin ] plugin
17
+ def initialize(plugin)
18
+ finders << PluginVersion::Readme.new(plugin)
19
+
20
+ load_specific_finders(plugin)
21
+ end
22
+
23
+ # Load the finders associated with the plugin
24
+ #
25
+ # @param [ WPScan::Plugin ] plugin
26
+ def load_specific_finders(plugin)
27
+ module_name = plugin.classify_name.to_sym
28
+
29
+ return unless Finders::PluginVersion.constants.include?(module_name)
30
+
31
+ mod = Finders::PluginVersion.const_get(module_name)
32
+
33
+ mod.constants.each do |constant|
34
+ c = mod.const_get(constant)
35
+
36
+ next unless c.is_a?(Class)
37
+
38
+ finders << c.new(plugin)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,40 @@
1
+ module WPScan
2
+ module Finders
3
+ module PluginVersion
4
+ module LayerSlider
5
+ # Version from a Translation file
6
+ #
7
+ # See https://github.com/wpscanteam/wpscan/issues/765
8
+ class TranslationFile < CMSScanner::Finders::Finder
9
+ # @param [ Hash ] opts
10
+ #
11
+ # @return [ Version ]
12
+ def aggressive(_opts = {})
13
+ potential_urls.each do |url|
14
+ res = Browser.get(url)
15
+
16
+ next unless res.code == 200 && res.body =~ /Project-Id-Version: LayerSlider WP v?([0-9\.][^\\\s]+)/
17
+
18
+ return WPScan::Version.new(
19
+ Regexp.last_match[1],
20
+ found_by: 'Translation File (Aggressive Detection)',
21
+ confidence: 90,
22
+ interesting_entries: ["#{url}, Match: '#{Regexp.last_match}'"]
23
+ )
24
+ end
25
+ nil
26
+ end
27
+
28
+ # @return [ Array<String> ] The potential URLs where the version is disclosed
29
+ def potential_urls
30
+ # Recent versions seem to use the 'locales' directory instead of the 'languages' one.
31
+ # Maybe also check other locales ?
32
+ %w(locales languages).reduce([]) do |a, e|
33
+ a << target.url("#{e}/LayerSlider-en_US.po")
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,79 @@
1
+ module WPScan
2
+ module Finders
3
+ module PluginVersion
4
+ # Plugin Version Finder from the readme.txt file
5
+ class Readme < CMSScanner::Finders::Finder
6
+ # @return [ Version ]
7
+ def aggressive(_opts = {})
8
+ found_by_msg = 'Readme - %s (Aggressive Detection)'
9
+
10
+ WPScan::WpItem::READMES.each do |file|
11
+ url = target.url(file)
12
+ res = Browser.get(url)
13
+
14
+ next unless res.code == 200 && !(numbers = version_numbers(res.body)).empty?
15
+
16
+ return numbers.reduce([]) do |a, e|
17
+ a << WPScan::Version.new(
18
+ e[0],
19
+ found_by: format(found_by_msg, e[1]),
20
+ confidence: e[2],
21
+ interesting_entries: [url]
22
+ )
23
+ end
24
+ end
25
+ nil
26
+ end
27
+
28
+ # @return [ Array<String, String, Integer> ] number, found_by, confidence
29
+ def version_numbers(body)
30
+ numbers = []
31
+
32
+ if (number = from_stable_tag(body))
33
+ numbers << [number, 'Stable Tag', 80]
34
+ end
35
+
36
+ if (number = from_changelog_section(body))
37
+ numbers << [number, 'ChangeLog Section', 50]
38
+ end
39
+
40
+ numbers
41
+ end
42
+
43
+ # @param [ String ] body
44
+ #
45
+ # @return [ String, nil ] The version number detected from the stable tag
46
+ def from_stable_tag(body)
47
+ return unless body =~ /\b(?:stable tag|version):\s*(?!trunk)([0-9a-z\.-]+)/i
48
+
49
+ number = Regexp.last_match[1]
50
+
51
+ number if number =~ /[0-9]+/
52
+ end
53
+
54
+ # @param [ String ] body
55
+ #
56
+ # @return [ String, nil ] The best version number detected from the changelog section
57
+ def from_changelog_section(body)
58
+ extracted_versions = body.scan(%r{[=]+\s+(?:v(?:ersion)?\s*)?([0-9\.-]+)[ \ta-z0-9\(\)\.\-\/]*[=]+}i)
59
+
60
+ return if extracted_versions.nil? || extracted_versions.empty?
61
+
62
+ extracted_versions.flatten!
63
+ # must contain at least one number
64
+ extracted_versions = extracted_versions.select { |x| x =~ /[0-9]+/ }
65
+
66
+ sorted = extracted_versions.sort do |x, y|
67
+ begin
68
+ Gem::Version.new(x) <=> Gem::Version.new(y)
69
+ rescue
70
+ 0
71
+ end
72
+ end
73
+
74
+ sorted.last
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,35 @@
1
+ module WPScan
2
+ module Finders
3
+ module PluginVersion
4
+ module Revslider
5
+ # Version from the release_log.html
6
+ #
7
+ # See https://github.com/wpscanteam/wpscan/issues/817
8
+ class ReleaseLog < CMSScanner::Finders::Finder
9
+ # @param [ Hash ] opts
10
+ #
11
+ # @return [ Version ]
12
+ def aggressive(_opts = {})
13
+ res = Browser.get(release_log_url)
14
+
15
+ res.html.css('h3.version-number:first').each do |node|
16
+ next unless node.text =~ /\AVersion ([0-9\.]+).*\z/i
17
+
18
+ return WPScan::Version.new(
19
+ Regexp.last_match[1],
20
+ found_by: found_by,
21
+ confidence: 90,
22
+ interesting_entries: ["#{release_log_url}, Match: '#{Regexp.last_match}'"]
23
+ )
24
+ end
25
+ nil
26
+ end
27
+
28
+ def release_log_url
29
+ target.url('release_log.html')
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,27 @@
1
+ module WPScan
2
+ module Finders
3
+ module PluginVersion
4
+ module SitepressMultilingualCms
5
+ # Version from the meta generator
6
+ class MetaGenerator < CMSScanner::Finders::Finder
7
+ # @param [ Hash ] opts
8
+ #
9
+ # @return [ Version ]
10
+ def passive(_opts = {})
11
+ target.target.homepage_res.html.css('meta[name="generator"]').each do |node|
12
+ next unless node['content'] =~ /\AWPML\sver:([0-9\.]+)\sstt/i
13
+
14
+ return WPScan::Version.new(
15
+ Regexp.last_match(1),
16
+ found_by: 'Meta Generator (Passive detection)',
17
+ confidence: 50,
18
+ interesting_entries: ["#{target.target.url}, Match: '#{node}'"]
19
+ )
20
+ end
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module WPScan
2
+ module Finders
3
+ module PluginVersion
4
+ module SitepressMultilingualCms
5
+ # Version from the v parameter in href / src of stylesheets / scripts
6
+ class VersionParameter < CMSScanner::Finders::Finder
7
+ # @param [ Hash ] opts
8
+ #
9
+ # @return [ Version ]
10
+ def passive(_opts = {})
11
+ pattern = %r{#{Regexp.escape(target.target.plugins_dir)}/sitepress-multilingual-cms/}i
12
+
13
+ target.target.in_scope_urls(target.target.homepage_res, '//link|//script') do |url|
14
+ uri = Addressable::URI.parse(url)
15
+
16
+ next unless uri.path =~ pattern && uri.query =~ /v=([0-9\.]+)/
17
+
18
+ return WPScan::Version.new(
19
+ Regexp.last_match[1],
20
+ found_by: found_by,
21
+ confidence: 50,
22
+ interesting_entries: [url]
23
+ )
24
+ end
25
+ nil
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end