wpscan 3.0

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