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.
- checksums.yaml +5 -5
- data/README.md +21 -14
- data/app/app.rb +2 -0
- data/app/controllers.rb +2 -0
- data/app/controllers/aliases.rb +2 -0
- data/app/controllers/core.rb +6 -4
- data/app/controllers/custom_directories.rb +3 -1
- data/app/controllers/enumeration.rb +6 -0
- data/app/controllers/enumeration/cli_options.rb +2 -0
- data/app/controllers/enumeration/enum_methods.rb +2 -0
- data/app/controllers/main_theme.rb +2 -0
- data/app/controllers/password_attack.rb +6 -4
- data/app/controllers/wp_version.rb +2 -0
- data/app/finders.rb +2 -0
- data/app/finders/config_backups.rb +2 -0
- data/app/finders/config_backups/known_filenames.rb +4 -3
- data/app/finders/db_exports.rb +2 -0
- data/app/finders/db_exports/known_locations.rb +15 -3
- data/app/finders/interesting_findings.rb +2 -0
- data/app/finders/interesting_findings/backup_db.rb +5 -4
- data/app/finders/interesting_findings/debug_log.rb +3 -1
- data/app/finders/interesting_findings/duplicator_installer_log.rb +6 -5
- data/app/finders/interesting_findings/emergency_pwd_reset_script.rb +6 -4
- data/app/finders/interesting_findings/full_path_disclosure.rb +3 -1
- data/app/finders/interesting_findings/mu_plugins.rb +4 -2
- data/app/finders/interesting_findings/multisite.rb +3 -1
- data/app/finders/interesting_findings/readme.rb +8 -6
- data/app/finders/interesting_findings/registration.rb +3 -1
- data/app/finders/interesting_findings/tmm_db_migrate.rb +4 -2
- data/app/finders/interesting_findings/upload_directory_listing.rb +3 -1
- data/app/finders/interesting_findings/upload_sql_dump.rb +8 -10
- data/app/finders/interesting_findings/wp_cron.rb +3 -1
- data/app/finders/main_theme.rb +2 -0
- data/app/finders/main_theme/css_style.rb +3 -1
- data/app/finders/main_theme/urls_in_homepage.rb +3 -1
- data/app/finders/main_theme/woo_framework_meta_generator.rb +3 -1
- data/app/finders/medias.rb +2 -0
- data/app/finders/medias/attachment_brute_forcing.rb +3 -1
- data/app/finders/passwords.rb +2 -0
- data/app/finders/passwords/wp_login.rb +4 -1
- data/app/finders/passwords/xml_rpc.rb +2 -0
- data/app/finders/passwords/xml_rpc_multicall.rb +4 -2
- data/app/finders/plugin_version.rb +4 -2
- data/app/finders/plugin_version/readme.rb +9 -5
- data/app/finders/plugins.rb +2 -0
- data/app/finders/plugins/body_pattern.rb +3 -1
- data/app/finders/plugins/comment.rb +3 -1
- data/app/finders/plugins/config_parser.rb +3 -1
- data/app/finders/plugins/header_pattern.rb +3 -1
- data/app/finders/plugins/javascript_var.rb +3 -1
- data/app/finders/plugins/known_locations.rb +10 -8
- data/app/finders/plugins/query_parameter.rb +2 -0
- data/app/finders/plugins/urls_in_homepage.rb +3 -1
- data/app/finders/plugins/xpath.rb +3 -1
- data/app/finders/theme_version.rb +4 -2
- data/app/finders/theme_version/style.rb +3 -1
- data/app/finders/theme_version/woo_framework_meta_generator.rb +3 -1
- data/app/finders/themes.rb +2 -0
- data/app/finders/themes/known_locations.rb +12 -10
- data/app/finders/themes/urls_in_homepage.rb +3 -1
- data/app/finders/timthumb_version.rb +3 -1
- data/app/finders/timthumb_version/bad_request.rb +3 -1
- data/app/finders/timthumbs.rb +2 -0
- data/app/finders/timthumbs/known_locations.rb +12 -3
- data/app/finders/users.rb +2 -0
- data/app/finders/users/author_id_brute_forcing.rb +3 -1
- data/app/finders/users/author_posts.rb +3 -1
- data/app/finders/users/login_error_messages.rb +3 -1
- data/app/finders/users/oembed_api.rb +6 -4
- data/app/finders/users/rss_generator.rb +7 -5
- data/app/finders/users/wp_json_api.rb +16 -6
- data/app/finders/users/yoast_seo_author_sitemap.rb +6 -4
- data/app/finders/wp_items.rb +2 -0
- data/app/finders/wp_items/urls_in_homepage.rb +2 -0
- data/app/finders/wp_version.rb +2 -0
- data/app/finders/wp_version/atom_generator.rb +2 -0
- data/app/finders/wp_version/rdf_generator.rb +2 -0
- data/app/finders/wp_version/readme.rb +4 -2
- data/app/finders/wp_version/rss_generator.rb +2 -0
- data/app/finders/wp_version/unique_fingerprinting.rb +3 -1
- data/app/models.rb +8 -0
- data/app/models/config_backup.rb +6 -2
- data/app/models/db_export.rb +6 -2
- data/app/models/interesting_finding.rb +36 -32
- data/app/models/media.rb +6 -2
- data/app/models/plugin.rb +25 -17
- data/app/models/theme.rb +83 -75
- data/app/models/timthumb.rb +58 -54
- data/app/models/wp_item.rb +140 -128
- data/app/models/wp_version.rb +47 -44
- data/app/models/xml_rpc.rb +18 -14
- data/app/views/cli/wp_item.erb +0 -3
- data/app/views/json/wp_item.erb +0 -1
- data/bin/wpscan +1 -0
- data/lib/wpscan.rb +2 -0
- data/lib/wpscan/browser.rb +2 -0
- data/lib/wpscan/controller.rb +2 -0
- data/lib/wpscan/controllers.rb +2 -0
- data/lib/wpscan/db.rb +2 -0
- data/lib/wpscan/db/dynamic_finders/base.rb +2 -0
- data/lib/wpscan/db/dynamic_finders/plugin.rb +4 -5
- data/lib/wpscan/db/dynamic_finders/theme.rb +2 -0
- data/lib/wpscan/db/dynamic_finders/wordpress.rb +2 -0
- data/lib/wpscan/db/fingerprints.rb +2 -0
- data/lib/wpscan/db/plugin.rb +2 -0
- data/lib/wpscan/db/plugins.rb +2 -0
- data/lib/wpscan/db/theme.rb +2 -0
- data/lib/wpscan/db/themes.rb +2 -0
- data/lib/wpscan/db/updater.rb +4 -2
- data/lib/wpscan/db/wp_item.rb +2 -0
- data/lib/wpscan/db/wp_items.rb +2 -0
- data/lib/wpscan/db/wp_version.rb +2 -0
- data/lib/wpscan/errors.rb +7 -1
- data/lib/wpscan/errors/http.rb +27 -23
- data/lib/wpscan/errors/update.rb +8 -4
- data/lib/wpscan/errors/wordpress.rb +24 -14
- data/lib/wpscan/errors/xmlrpc.rb +8 -4
- data/lib/wpscan/finders.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/finder.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/body_pattern.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/comment.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/config_parser.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/finder.rb +4 -2
- data/lib/wpscan/finders/dynamic_finder/version/header_pattern.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/javascript_var.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/query_parameter.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/version/xpath.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/wp_item_version.rb +2 -0
- data/lib/wpscan/finders/dynamic_finder/wp_items/finder.rb +4 -2
- data/lib/wpscan/finders/dynamic_finder/wp_version.rb +4 -2
- data/lib/wpscan/finders/finder/wp_version/smart_url_checker.rb +4 -2
- data/lib/wpscan/helper.rb +2 -0
- data/lib/wpscan/references.rb +2 -0
- data/lib/wpscan/target.rb +12 -1
- data/lib/wpscan/target/platform/wordpress.rb +15 -1
- data/lib/wpscan/target/platform/wordpress/custom_directories.rb +23 -3
- data/lib/wpscan/version.rb +3 -1
- data/lib/wpscan/vulnerability.rb +2 -0
- data/lib/wpscan/vulnerable.rb +2 -0
- metadata +35 -8
data/app/models/wp_item.rb
CHANGED
|
@@ -1,158 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module WPScan
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
4
|
+
module Model
|
|
5
|
+
# WpItem (superclass of Plugin & Theme)
|
|
6
|
+
class WpItem
|
|
7
|
+
include Vulnerable
|
|
8
|
+
include Finders::Finding
|
|
9
|
+
include CMSScanner::Target::Platform::PHP
|
|
10
|
+
include CMSScanner::Target::Server::Generic
|
|
11
|
+
|
|
12
|
+
READMES = %w[readme.txt README.txt README.md readme.md Readme.txt].freeze
|
|
13
|
+
|
|
14
|
+
attr_reader :uri, :slug, :detection_opts, :version_detection_opts, :blog, :path_from_blog, :db_data
|
|
15
|
+
|
|
16
|
+
delegate :homepage_res, :xpath_pattern_from_page, :in_scope_urls, :head_or_get_params, to: :blog
|
|
17
|
+
|
|
18
|
+
# @param [ String ] slug The plugin/theme slug
|
|
19
|
+
# @param [ Target ] blog The targeted blog
|
|
20
|
+
# @param [ Hash ] opts
|
|
21
|
+
# @option opts [ Symbol ] :mode The detection mode to use
|
|
22
|
+
# @option opts [ Hash ] :version_detection The options to use when looking for the version
|
|
23
|
+
# @option opts [ String ] :url The URL of the item
|
|
24
|
+
def initialize(slug, blog, opts = {})
|
|
25
|
+
@slug = URI.decode(slug)
|
|
26
|
+
@blog = blog
|
|
27
|
+
@uri = Addressable::URI.parse(opts[:url]) if opts[:url]
|
|
28
|
+
|
|
29
|
+
@detection_opts = { mode: opts[:mode] }
|
|
30
|
+
@version_detection_opts = opts[:version_detection] || {}
|
|
31
|
+
|
|
32
|
+
parse_finding_options(opts)
|
|
33
|
+
end
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
# @return [ Array<Vulnerabily> ]
|
|
36
|
+
def vulnerabilities
|
|
37
|
+
return @vulnerabilities if @vulnerabilities
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
@vulnerabilities = []
|
|
40
|
+
|
|
41
|
+
[*db_data['vulnerabilities']].each do |json_vuln|
|
|
42
|
+
vulnerability = Vulnerability.load_from_json(json_vuln)
|
|
43
|
+
@vulnerabilities << vulnerability if vulnerable_to?(vulnerability)
|
|
44
|
+
end
|
|
38
45
|
|
|
39
|
-
|
|
40
|
-
vulnerability = Vulnerability.load_from_json(json_vuln)
|
|
41
|
-
@vulnerabilities << vulnerability if vulnerable_to?(vulnerability)
|
|
46
|
+
@vulnerabilities
|
|
42
47
|
end
|
|
43
48
|
|
|
44
|
-
|
|
45
|
-
|
|
49
|
+
# Checks if the wp_item is vulnerable to a specific vulnerability
|
|
50
|
+
#
|
|
51
|
+
# @param [ Vulnerability ] vuln Vulnerability to check the item against
|
|
52
|
+
#
|
|
53
|
+
# @return [ Boolean ]
|
|
54
|
+
def vulnerable_to?(vuln)
|
|
55
|
+
return true unless version && vuln && vuln.fixed_in && !vuln.fixed_in.empty?
|
|
46
56
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# @param [ Vulnerability ] vuln Vulnerability to check the item against
|
|
50
|
-
#
|
|
51
|
-
# @return [ Boolean ]
|
|
52
|
-
def vulnerable_to?(vuln)
|
|
53
|
-
return true unless version && vuln && vuln.fixed_in && !vuln.fixed_in.empty?
|
|
57
|
+
version < vuln.fixed_in
|
|
58
|
+
end
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
# @return [ String ]
|
|
61
|
+
def latest_version
|
|
62
|
+
@latest_version ||= db_data['latest_version'] ? Model::Version.new(db_data['latest_version']) : nil
|
|
63
|
+
end
|
|
57
64
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
# Not used anywhere ATM
|
|
66
|
+
# @return [ Boolean ]
|
|
67
|
+
def popular?
|
|
68
|
+
@popular ||= db_data['popular']
|
|
69
|
+
end
|
|
62
70
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
end
|
|
71
|
+
# @return [ String ]
|
|
72
|
+
def last_updated
|
|
73
|
+
@last_updated ||= db_data['last_updated']
|
|
74
|
+
end
|
|
68
75
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
# @return [ Boolean ]
|
|
77
|
+
def outdated?
|
|
78
|
+
@outdated ||= if version && latest_version
|
|
79
|
+
version < latest_version
|
|
80
|
+
else
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
end
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
85
|
+
# URI.encode is preferered over Addressable::URI.encode as it will encode
|
|
86
|
+
# leading # character:
|
|
87
|
+
# URI.encode('#t#') => %23t%23
|
|
88
|
+
# Addressable::URI.encode('#t#') => #t%23
|
|
89
|
+
#
|
|
90
|
+
# @param [ String ] path Optional path to merge with the uri
|
|
91
|
+
#
|
|
92
|
+
# @return [ String ]
|
|
93
|
+
def url(path = nil)
|
|
94
|
+
return unless @uri
|
|
95
|
+
return @uri.to_s unless path
|
|
96
|
+
|
|
97
|
+
@uri.join(URI.encode(path)).to_s
|
|
98
|
+
end
|
|
82
99
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
#
|
|
88
|
-
# @param [ String ] path Optional path to merge with the uri
|
|
89
|
-
#
|
|
90
|
-
# @return [ String ]
|
|
91
|
-
def url(path = nil)
|
|
92
|
-
return unless @uri
|
|
93
|
-
return @uri.to_s unless path
|
|
94
|
-
|
|
95
|
-
@uri.join(URI.encode(path)).to_s
|
|
96
|
-
end
|
|
100
|
+
# @return [ Boolean ]
|
|
101
|
+
def ==(other)
|
|
102
|
+
self.class == other.class && slug == other.slug
|
|
103
|
+
end
|
|
97
104
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
end
|
|
105
|
+
def to_s
|
|
106
|
+
slug
|
|
107
|
+
end
|
|
102
108
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
# @return [ Symbol ] The Class symbol associated to the item
|
|
110
|
+
def classify
|
|
111
|
+
@classify ||= classify_slug(slug)
|
|
112
|
+
end
|
|
106
113
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
end
|
|
114
|
+
# @return [ String, False ] The readme url if found, false otherwise
|
|
115
|
+
def readme_url
|
|
116
|
+
return if detection_opts[:mode] == :passive
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
def readme_url
|
|
114
|
-
return if detection_opts[:mode] == :passive
|
|
118
|
+
return @readme_url unless @readme_url.nil?
|
|
115
119
|
|
|
116
|
-
if @readme_url.nil?
|
|
117
120
|
READMES.each do |path|
|
|
118
|
-
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
+
t_url = url(path)
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
# @return [ String, false ] The changelog urr if found
|
|
126
|
-
def changelog_url
|
|
127
|
-
return if detection_opts[:mode] == :passive
|
|
128
|
-
|
|
129
|
-
if @changelog_url.nil?
|
|
130
|
-
CHANGELOGS.each do |path|
|
|
131
|
-
return @changelog_url = url(path) if Browser.get(url(path)).code == 200
|
|
123
|
+
return @readme_url = t_url if Browser.forge_request(t_url, blog.head_or_get_params).run.code == 200
|
|
132
124
|
end
|
|
125
|
+
|
|
126
|
+
@readme_url = false
|
|
133
127
|
end
|
|
134
128
|
|
|
135
|
-
@
|
|
136
|
-
|
|
129
|
+
# @param [ String ] path
|
|
130
|
+
# @param [ Hash ] params The request params
|
|
131
|
+
#
|
|
132
|
+
# @return [ Boolean ]
|
|
133
|
+
def directory_listing?(path = nil, params = {})
|
|
134
|
+
return if detection_opts[:mode] == :passive
|
|
137
135
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
#
|
|
141
|
-
# @return [ Boolean ]
|
|
142
|
-
def directory_listing?(path = nil, params = {})
|
|
143
|
-
return if detection_opts[:mode] == :passive
|
|
136
|
+
super(path, params)
|
|
137
|
+
end
|
|
144
138
|
|
|
145
|
-
|
|
146
|
-
|
|
139
|
+
# @param [ String ] path
|
|
140
|
+
# @param [ Hash ] params The request params
|
|
141
|
+
#
|
|
142
|
+
# @return [ Boolean ]
|
|
143
|
+
def error_log?(path = 'error_log', params = {})
|
|
144
|
+
return if detection_opts[:mode] == :passive
|
|
147
145
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
#
|
|
151
|
-
# @return [ Boolean ]
|
|
152
|
-
def error_log?(path = 'error_log', params = {})
|
|
153
|
-
return if detection_opts[:mode] == :passive
|
|
146
|
+
super(path, params)
|
|
147
|
+
end
|
|
154
148
|
|
|
155
|
-
|
|
149
|
+
# See CMSScanner::Target#head_and_get
|
|
150
|
+
#
|
|
151
|
+
# This is used by the error_log? above in the super()
|
|
152
|
+
# to have the correct path (ie readme.txt checked from the plugin/theme location
|
|
153
|
+
# and not from the blog root). Could also be used in finders
|
|
154
|
+
#
|
|
155
|
+
# @param [ String ] path
|
|
156
|
+
# @param [ Array<String> ] codes
|
|
157
|
+
# @param [ Hash ] params The requests params
|
|
158
|
+
# @option params [ Hash ] :head Request params for the HEAD
|
|
159
|
+
# @option params [ hash ] :get Request params for the GET
|
|
160
|
+
#
|
|
161
|
+
# @return [ Typhoeus::Response ]
|
|
162
|
+
def head_and_get(path, codes = [200], params = {})
|
|
163
|
+
final_path = +@path_from_blog
|
|
164
|
+
final_path << URI.encode(path) unless path.nil?
|
|
165
|
+
|
|
166
|
+
blog.head_and_get(final_path, codes, params)
|
|
167
|
+
end
|
|
156
168
|
end
|
|
157
169
|
end
|
|
158
170
|
end
|
data/app/models/wp_version.rb
CHANGED
|
@@ -1,64 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module WPScan
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
module Model
|
|
5
|
+
# WP Version
|
|
6
|
+
class WpVersion < CMSScanner::Model::Version
|
|
7
|
+
include Vulnerable
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
def initialize(number, opts = {})
|
|
10
|
+
raise Error::InvalidWordPressVersion unless WpVersion.valid?(number.to_s)
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
super(number, opts)
|
|
13
|
+
end
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
# @param [ String ] number
|
|
16
|
+
#
|
|
17
|
+
# @return [ Boolean ] true if the number is a valid WP version, false otherwise
|
|
18
|
+
def self.valid?(number)
|
|
19
|
+
all.include?(number)
|
|
20
|
+
end
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
# @return [ Array<String> ] All the version numbers
|
|
23
|
+
def self.all
|
|
24
|
+
return @all_numbers if @all_numbers
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
@all_numbers = []
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
versions.each do |version|
|
|
28
|
-
@all_numbers << version unless @all_numbers.include?(version)
|
|
29
|
-
end
|
|
28
|
+
DB::Fingerprints.wp_fingerprints.each_value do |fp|
|
|
29
|
+
@all_numbers << fp.values
|
|
30
30
|
end
|
|
31
|
+
|
|
32
|
+
# @all_numbers.flatten.uniq.sort! {} doesn't produce the same result here.
|
|
33
|
+
@all_numbers.flatten!
|
|
34
|
+
@all_numbers.uniq!
|
|
35
|
+
@all_numbers.sort! { |a, b| Gem::Version.new(b) <=> Gem::Version.new(a) }
|
|
31
36
|
end
|
|
32
37
|
|
|
33
|
-
@
|
|
34
|
-
|
|
38
|
+
# @return [ JSON ]
|
|
39
|
+
def db_data
|
|
40
|
+
@db_data ||= DB::Version.db_data(number)
|
|
41
|
+
end
|
|
35
42
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
end
|
|
43
|
+
# @return [ Array<Vulnerability> ]
|
|
44
|
+
def vulnerabilities
|
|
45
|
+
return @vulnerabilities if @vulnerabilities
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
def vulnerabilities
|
|
43
|
-
return @vulnerabilities if @vulnerabilities
|
|
47
|
+
@vulnerabilities = []
|
|
44
48
|
|
|
45
|
-
|
|
49
|
+
[*db_data['vulnerabilities']].each do |json_vuln|
|
|
50
|
+
@vulnerabilities << Vulnerability.load_from_json(json_vuln)
|
|
51
|
+
end
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
@vulnerabilities << Vulnerability.load_from_json(json_vuln)
|
|
53
|
+
@vulnerabilities
|
|
49
54
|
end
|
|
50
55
|
|
|
51
|
-
@
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def release_date
|
|
56
|
-
@release_date ||= db_data['release_date'] || 'Unknown'
|
|
57
|
-
end
|
|
56
|
+
# @return [ String ]
|
|
57
|
+
def release_date
|
|
58
|
+
@release_date ||= db_data['release_date'] || 'Unknown'
|
|
59
|
+
end
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
# @return [ String ]
|
|
62
|
+
def status
|
|
63
|
+
@status ||= db_data['status'] || 'Unknown'
|
|
64
|
+
end
|
|
62
65
|
end
|
|
63
66
|
end
|
|
64
67
|
end
|
data/app/models/xml_rpc.rb
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module WPScan
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
module Model
|
|
5
|
+
# Override of the CMSScanner::XMLRPC to include the references
|
|
6
|
+
class XMLRPC < CMSScanner::Model::XMLRPC
|
|
7
|
+
include References # To be able to use the :wpvulndb reference if needed
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
# @return [ Hash ]
|
|
10
|
+
def references
|
|
11
|
+
{
|
|
12
|
+
url: ['http://codex.wordpress.org/XML-RPC_Pingback_API'],
|
|
13
|
+
metasploit: [
|
|
14
|
+
'auxiliary/scanner/http/wordpress_ghost_scanner',
|
|
15
|
+
'auxiliary/dos/http/wordpress_xmlrpc_dos',
|
|
16
|
+
'auxiliary/scanner/http/wordpress_xmlrpc_login',
|
|
17
|
+
'auxiliary/scanner/http/wordpress_pingback_access'
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
end
|
|
19
23
|
end
|
data/app/views/cli/wp_item.erb
CHANGED
|
@@ -8,9 +8,6 @@
|
|
|
8
8
|
<% if @wp_item.readme_url -%>
|
|
9
9
|
| Readme: <%= @wp_item.readme_url %>
|
|
10
10
|
<% end -%>
|
|
11
|
-
<% if @wp_item.changelog_url -%>
|
|
12
|
-
| Changelog: <%= @wp_item.changelog_url %>
|
|
13
|
-
<% end -%>
|
|
14
11
|
<% if @wp_item.latest_version && @wp_item.outdated? -%>
|
|
15
12
|
| <%= warning_icon %> The version is out of date, the latest version is <%= @wp_item.latest_version %>
|
|
16
13
|
<% end -%>
|