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,44 @@
1
+ # Gems
2
+ require 'cms_scanner'
3
+ require 'yajl/json_gem'
4
+ require 'addressable/uri'
5
+ require 'active_support/all'
6
+ # Standard Lib
7
+ require 'uri'
8
+ require 'time'
9
+ require 'readline'
10
+ require 'securerandom'
11
+ # Custom Libs
12
+ require 'wpscan/helper'
13
+ require 'wpscan/db'
14
+ require 'wpscan/version'
15
+ require 'wpscan/errors/wordpress'
16
+ require 'wpscan/errors/http'
17
+ require 'wpscan/errors/update'
18
+ require 'wpscan/browser'
19
+ require 'wpscan/target'
20
+ require 'wpscan/finders'
21
+ require 'wpscan/controller'
22
+ require 'wpscan/controllers'
23
+ require 'wpscan/references'
24
+ require 'wpscan/vulnerable'
25
+ require 'wpscan/vulnerability'
26
+
27
+ Encoding.default_external = Encoding::UTF_8
28
+
29
+ # WPScan
30
+ module WPScan
31
+ include CMSScanner
32
+
33
+ APP_DIR = Pathname.new(__FILE__).dirname.join('..', 'app').expand_path
34
+ DB_DIR = File.join(Dir.home, '.wpscan', 'db')
35
+
36
+ # Override, otherwise it would be returned as 'wp_scan'
37
+ #
38
+ # @return [ String ]
39
+ def self.app_name
40
+ 'wpscan'
41
+ end
42
+ end
43
+
44
+ require "#{WPScan::APP_DIR}/app"
@@ -0,0 +1,16 @@
1
+ module WPScan
2
+ # Custom Browser
3
+ class Browser < CMSScanner::Browser
4
+ extend Actions
5
+
6
+ # @return [ String ] The path to the user agents list
7
+ def user_agents_list
8
+ @user_agents_list ||= File.join(DB_DIR, 'user-agents.txt')
9
+ end
10
+
11
+ # @return [ String ]
12
+ def default_user_agent
13
+ "WPScan v#{VERSION} (http://wpscan.org/)"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module WPScan
2
+ # Needed to load at least the Core controller
3
+ # Otherwise, the following error will be raised:
4
+ # `initialize': uninitialized constant WPScan::Controller::Core (NameError)
5
+ module Controller
6
+ include CMSScanner::Controller
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module WPScan
2
+ # Override to set the OptParser's summary width to 45 (instead of 40 from the CMSScanner)
3
+ class Controllers < CMSScanner::Controllers
4
+ def initialize(option_parser = OptParseValidator::OptParser.new(nil, 45))
5
+ super(option_parser)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,28 @@
1
+ require 'dm-core'
2
+ require 'dm-migrations'
3
+ require 'dm-constraints'
4
+ require 'dm-sqlite-adapter'
5
+
6
+ require 'wpscan/db/wp_item'
7
+ require 'wpscan/db/schema'
8
+ require 'wpscan/db/updater'
9
+ require 'wpscan/db/wp_items'
10
+ require 'wpscan/db/plugins'
11
+ require 'wpscan/db/themes'
12
+ require 'wpscan/db/plugin'
13
+ require 'wpscan/db/theme'
14
+ require 'wpscan/db/wp_version'
15
+ require 'wpscan/db/dynamic_finders'
16
+
17
+ module WPScan
18
+ # DB
19
+ module DB
20
+ def self.init_db
21
+ db_file ||= File.join(DB_DIR, 'wordpress.db')
22
+
23
+ # DataMapper::Logger.new($stdout, :debug)
24
+ DataMapper.setup(:default, "sqlite://#{db_file}")
25
+ DataMapper.auto_upgrade!
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,63 @@
1
+ module WPScan
2
+ module DB
3
+ # Dynamic Finders
4
+ class DynamicFinders
5
+ # @return [ String ]
6
+ def self.db_file
7
+ @db_file ||= File.join(DB_DIR, 'dynamic_finders.yml')
8
+ end
9
+
10
+ # @return [ Hash ]
11
+ def self.db_data
12
+ @db_data ||= YAML.load_file(db_file)
13
+ end
14
+
15
+ # @return [ Hash ]
16
+ def self.finder_configs(finder_klass)
17
+ configs = {}
18
+
19
+ db_data.each do |slug, config|
20
+ next unless config[finder_klass]
21
+
22
+ configs[slug] = config[finder_klass].dup
23
+ end
24
+
25
+ configs
26
+ end
27
+ end
28
+
29
+ # Dynamic Plugin Finders
30
+ class DynamicPluginFinders < DynamicFinders
31
+ # @return [ Hash ]
32
+ def self.db_data
33
+ @db_data ||= super['plugins'] || {}
34
+ end
35
+
36
+ # @return [ Hash ]
37
+ def self.comments
38
+ unless @comments
39
+ @comments = finder_configs('Comments')
40
+
41
+ @comments.each do |slug, config|
42
+ @comments[slug]['pattern'] = Regexp.new(config['pattern'], Regexp::IGNORECASE)
43
+ end
44
+ end
45
+
46
+ @comments
47
+ end
48
+
49
+ # @return [ Hash ]
50
+ def self.urls_in_page
51
+ @urls_in_page ||= finder_configs('UrlsInPage')
52
+ end
53
+ end
54
+
55
+ # Dynamic Theme Finders (none ATM)
56
+ class DynamicThemeFinders < DynamicFinders
57
+ # @return [ Hash ]
58
+ def self.db_data
59
+ @db_data ||= super['themes'] || {}
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+ module WPScan
2
+ module DB
3
+ # Plugin DB
4
+ class Plugin < WpItem
5
+ # @return [ String ]
6
+ def self.db_file
7
+ @db_file ||= File.join(DB_DIR, 'plugins.json')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module WPScan
2
+ module DB
3
+ # WP Plugins
4
+ class Plugins < WpItems
5
+ # @return [ JSON ]
6
+ def self.db
7
+ Plugin.db
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ module WPScan
2
+ module DB
3
+ # WP Version
4
+ class Version < WpItem
5
+ include DataMapper::Resource
6
+
7
+ storage_names[:default] = 'versions'
8
+
9
+ has n, :fingerprints, constraint: :destroy
10
+
11
+ property :id, Serial
12
+ property :number, String, required: true, unique: true
13
+ end
14
+
15
+ # Path
16
+ class Path
17
+ include DataMapper::Resource
18
+
19
+ storage_names[:default] = 'paths'
20
+
21
+ has n, :fingerprints, constraint: :destroy
22
+
23
+ property :id, Serial
24
+ property :value, String, required: true, unique: true
25
+ end
26
+
27
+ # Fingerprint
28
+ class Fingerprint
29
+ include DataMapper::Resource
30
+
31
+ storage_names[:default] = 'fingerprints'
32
+
33
+ belongs_to :version, key: true
34
+ belongs_to :path, key: true
35
+
36
+ property :md5_hash, String, required: true, length: 32
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ module WPScan
2
+ module DB
3
+ # Theme DB
4
+ class Theme < WpItem
5
+ # @return [ String ]
6
+ def self.db_file
7
+ @db_file ||= File.join(DB_DIR, 'themes.json')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module WPScan
2
+ module DB
3
+ # WP Themes
4
+ class Themes < WpItems
5
+ # @return [ JSON ]
6
+ def self.db
7
+ Theme.db
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,148 @@
1
+ module WPScan
2
+ module DB
3
+ # Class used to perform DB updates
4
+ # :nocov:
5
+ class Updater
6
+ # /!\ Might want to also update the Enumeration#cli_options when some filenames are changed here
7
+ FILES = %w(
8
+ plugins.json themes.json wordpresses.json
9
+ timthumbs-v3.txt user-agents.txt config_backups.txt
10
+ dynamic_finders.yml wordpress.db LICENSE
11
+ ).freeze
12
+
13
+ attr_reader :repo_directory
14
+
15
+ def initialize(repo_directory)
16
+ @repo_directory = repo_directory
17
+
18
+ FileUtils.mkdir_p(repo_directory) unless Dir.exist?(repo_directory)
19
+
20
+ raise "#{repo_directory} is not writable" unless Pathname.new(repo_directory).writable?
21
+ end
22
+
23
+ # @return [ Time, nil ]
24
+ def last_update
25
+ Time.parse(File.read(last_update_file))
26
+ rescue ArgumentError, Errno::ENOENT
27
+ nil # returns nil if the file does not exist or contains invalid time data
28
+ end
29
+
30
+ # @return [ String ]
31
+ def last_update_file
32
+ @last_update_file ||= File.join(repo_directory, '.last_update')
33
+ end
34
+
35
+ # @return [ Boolean ]
36
+ def outdated?
37
+ date = last_update
38
+
39
+ date.nil? || date < 5.days.ago
40
+ end
41
+
42
+ # @return [ Boolean ]
43
+ def missing_files?
44
+ FILES.each do |file|
45
+ return true unless File.exist?(File.join(repo_directory, file))
46
+ end
47
+ false
48
+ end
49
+
50
+ # @return [ Hash ] The params for Typhoeus::Request
51
+ def request_params
52
+ {
53
+ ssl_verifyhost: 2,
54
+ ssl_verifypeer: true,
55
+ timeout: 300,
56
+ connecttimeout: 120,
57
+ accept_encoding: 'gzip, deflate',
58
+ cache_ttl: 0
59
+ }
60
+ end
61
+
62
+ # @return [ String ] The raw file URL associated with the given filename
63
+ def remote_file_url(filename)
64
+ "https://data.wpscan.org/#{filename}"
65
+ end
66
+
67
+ # @return [ String ] The checksum of the associated remote filename
68
+ def remote_file_checksum(filename)
69
+ url = "#{remote_file_url(filename)}.sha512"
70
+
71
+ res = Browser.get(url, request_params)
72
+ raise DownloadError, res if res.timed_out? || res.code != 200
73
+ res.body.chomp
74
+ end
75
+
76
+ def local_file_path(filename)
77
+ File.join(repo_directory, filename.to_s)
78
+ end
79
+
80
+ def local_file_checksum(filename)
81
+ Digest::SHA512.file(local_file_path(filename)).hexdigest
82
+ end
83
+
84
+ def backup_file_path(filename)
85
+ File.join(repo_directory, "#{filename}.back")
86
+ end
87
+
88
+ def create_backup(filename)
89
+ return unless File.exist?(local_file_path(filename))
90
+ FileUtils.cp(local_file_path(filename), backup_file_path(filename))
91
+ end
92
+
93
+ def restore_backup(filename)
94
+ return unless File.exist?(backup_file_path(filename))
95
+ FileUtils.cp(backup_file_path(filename), local_file_path(filename))
96
+ end
97
+
98
+ def delete_backup(filename)
99
+ FileUtils.rm(backup_file_path(filename))
100
+ end
101
+
102
+ # @return [ String ] The checksum of the downloaded file
103
+ def download(filename)
104
+ file_path = local_file_path(filename)
105
+ file_url = remote_file_url(filename)
106
+
107
+ res = Browser.get(file_url, request_params)
108
+ raise DownloadError, res if res.timed_out? || res.code != 200
109
+
110
+ File.open(file_path, 'wb') { |f| f.write(res.body) }
111
+
112
+ local_file_checksum(filename)
113
+ end
114
+
115
+ # rubocop:disable MethodLength
116
+ # @return [ Array<String> ] The filenames updated
117
+ def update
118
+ updated = []
119
+
120
+ FILES.each do |filename|
121
+ begin
122
+ db_checksum = remote_file_checksum(filename)
123
+
124
+ # Checking if the file needs to be updated
125
+ next if File.exist?(local_file_path(filename)) && db_checksum == local_file_checksum(filename)
126
+
127
+ create_backup(filename)
128
+ dl_checksum = download(filename)
129
+
130
+ raise "#{filename}: checksums do not match" unless dl_checksum == db_checksum
131
+ updated << filename
132
+ rescue => e
133
+ restore_backup(filename)
134
+ raise e
135
+ ensure
136
+ delete_backup(filename) if File.exist?(backup_file_path(filename))
137
+ end
138
+ end
139
+
140
+ File.write(last_update_file, Time.now)
141
+
142
+ updated
143
+ end
144
+ # rubocop:enable MethodLength
145
+ end
146
+ end
147
+ # :nocov:
148
+ end
@@ -0,0 +1,18 @@
1
+ module WPScan
2
+ module DB
3
+ # WpItem - super DB class for Plugin, Theme and Version
4
+ class WpItem
5
+ # @param [ String ] identifier The plugin/theme slug or version number
6
+ #
7
+ # @return [ Hash ] The JSON data from the DB associated to the identifier
8
+ def self.db_data(identifier)
9
+ db[identifier] || {}
10
+ end
11
+
12
+ # @return [ JSON ]
13
+ def self.db
14
+ @db ||= read_json_file(db_file)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module WPScan
2
+ module DB
3
+ # WP Items
4
+ class WpItems
5
+ # @return [ Array<String> ] The slug of all items
6
+ def self.all_slugs
7
+ db.keys
8
+ end
9
+
10
+ # @return [ Array<String> ] The slug of all popular items
11
+ def self.popular_slugs
12
+ db.select { |_key, item| item['popular'] == true }.keys
13
+ end
14
+
15
+ # @return [ Array<String> ] The slug of all vulnerable items
16
+ def self.vulnerable_slugs
17
+ db.select { |_key, item| !item['vulnerabilities'].empty? }.keys
18
+ end
19
+ end
20
+ end
21
+ end