Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wpscanteam
GitHub Repository: wpscanteam/wpscan
Path: blob/master/app/controllers/enumeration/enum_methods.rb
485 views
1
# frozen_string_literal: true
2
3
module WPScan
4
module Controller
5
# Enumeration Methods
6
class Enumeration < CMSScanner::Controller::Base
7
# @param [ String ] type (plugins or themes)
8
# @param [ Symbol ] detection_mode
9
#
10
# @return [ String ] The related enumration message depending on the ParsedCli and type supplied
11
def enum_message(type, detection_mode)
12
return unless %w[plugins themes].include?(type)
13
14
details = if ParsedCli.enumerate[:"vulnerable_#{type}"]
15
'Vulnerable'
16
elsif ParsedCli.enumerate[:"all_#{type}"]
17
'All'
18
else
19
'Most Popular'
20
end
21
22
"Enumerating #{details} #{type.capitalize} #{enum_detection_message(detection_mode)}"
23
end
24
25
# @param [ Symbol ] detection_mode
26
#
27
# @return [ String ]
28
def enum_detection_message(detection_mode)
29
detection_method = if detection_mode == :mixed
30
'Passive and Aggressive'
31
else
32
detection_mode.to_s.capitalize
33
end
34
35
"(via #{detection_method} Methods)"
36
end
37
38
# @param [ String ] type (plugins, themes etc)
39
#
40
# @return [ Hash ]
41
def default_opts(type)
42
mode = ParsedCli.options[:"#{type}_detection"] || ParsedCli.detection_mode
43
44
{
45
mode: mode,
46
exclude_content: ParsedCli.exclude_content_based,
47
show_progression: user_interaction?,
48
version_detection: {
49
mode: ParsedCli.options[:"#{type}_version_detection"] || mode,
50
confidence_threshold: ParsedCli.options[:"#{type}_version_all"] ? 0 : 100
51
}
52
}
53
end
54
55
# @param [ Hash ] opts
56
#
57
# @return [ Boolean ] Wether or not to enumerate the plugins
58
def enum_plugins?(opts)
59
opts[:popular_plugins] || opts[:all_plugins] || opts[:vulnerable_plugins]
60
end
61
62
def enum_plugins
63
opts = default_opts('plugins').merge(
64
list: plugins_list_from_opts(ParsedCli.options),
65
threshold: ParsedCli.plugins_threshold,
66
sort: true
67
)
68
69
output('@info', msg: enum_message('plugins', opts[:mode])) if user_interaction?
70
# Enumerate the plugins & find their versions to avoid doing that when #version
71
# is called in the view
72
plugins = target.plugins(opts)
73
74
if user_interaction? && !plugins.empty?
75
output('@info',
76
msg: "Checking Plugin Versions #{enum_detection_message(opts[:version_detection][:mode])}")
77
end
78
79
plugins.each(&:version)
80
81
plugins.select!(&:vulnerable?) if ParsedCli.enumerate[:vulnerable_plugins]
82
83
output('plugins', plugins: plugins)
84
end
85
86
# @param [ Hash ] opts
87
#
88
# @return [ Array<String> ] The plugins list associated to the cli options
89
def plugins_list_from_opts(opts)
90
# List file provided by the user via the cli
91
return opts[:plugins_list] if opts[:plugins_list]
92
93
if opts[:enumerate][:all_plugins]
94
DB::Plugins.all_slugs
95
elsif opts[:enumerate][:popular_plugins]
96
DB::Plugins.popular_slugs
97
else
98
DB::Plugins.vulnerable_slugs
99
end
100
end
101
102
# @param [ Hash ] opts
103
#
104
# @return [ Boolean ] Wether or not to enumerate the themes
105
def enum_themes?(opts)
106
opts[:popular_themes] || opts[:all_themes] || opts[:vulnerable_themes]
107
end
108
109
def enum_themes
110
opts = default_opts('themes').merge(
111
list: themes_list_from_opts(ParsedCli.options),
112
threshold: ParsedCli.themes_threshold,
113
sort: true
114
)
115
116
output('@info', msg: enum_message('themes', opts[:mode])) if user_interaction?
117
# Enumerate the themes & find their versions to avoid doing that when #version
118
# is called in the view
119
themes = target.themes(opts)
120
121
if user_interaction? && !themes.empty?
122
output('@info',
123
msg: "Checking Theme Versions #{enum_detection_message(opts[:version_detection][:mode])}")
124
end
125
126
themes.each(&:version)
127
128
themes.select!(&:vulnerable?) if ParsedCli.enumerate[:vulnerable_themes]
129
130
output('themes', themes: themes)
131
end
132
133
# @param [ Hash ] opts
134
#
135
# @return [ Array<String> ] The themes list associated to the cli options
136
def themes_list_from_opts(opts)
137
# List file provided by the user via the cli
138
return opts[:themes_list] if opts[:themes_list]
139
140
if opts[:enumerate][:all_themes]
141
DB::Themes.all_slugs
142
elsif opts[:enumerate][:popular_themes]
143
DB::Themes.popular_slugs
144
else
145
DB::Themes.vulnerable_slugs
146
end
147
end
148
149
def enum_timthumbs
150
opts = default_opts('timthumbs').merge(list: ParsedCli.timthumbs_list)
151
152
output('@info', msg: "Enumerating Timthumbs #{enum_detection_message(opts[:mode])}") if user_interaction?
153
output('timthumbs', timthumbs: target.timthumbs(opts))
154
end
155
156
def enum_config_backups
157
opts = default_opts('config_backups').merge(list: ParsedCli.config_backups_list)
158
159
output('@info', msg: "Enumerating Config Backups #{enum_detection_message(opts[:mode])}") if user_interaction?
160
output('config_backups', config_backups: target.config_backups(opts))
161
end
162
163
def enum_db_exports
164
opts = default_opts('db_exports').merge(list: ParsedCli.db_exports_list)
165
166
output('@info', msg: "Enumerating DB Exports #{enum_detection_message(opts[:mode])}") if user_interaction?
167
output('db_exports', db_exports: target.db_exports(opts))
168
end
169
170
def enum_medias
171
opts = default_opts('medias').merge(range: ParsedCli.enumerate[:medias])
172
173
if user_interaction?
174
output('@info',
175
msg: "Enumerating Medias #{enum_detection_message(opts[:mode])} "\
176
'(Permalink setting must be set to "Plain" for those to be detected)')
177
end
178
179
output('medias', medias: target.medias(opts))
180
end
181
182
# @param [ Hash ] opts
183
#
184
# @return [ Boolean ] Wether or not to enumerate the users
185
def enum_users?(opts)
186
opts[:users] || (ParsedCli.passwords && !ParsedCli.username && !ParsedCli.usernames)
187
end
188
189
def enum_users
190
opts = default_opts('users').merge(
191
range: enum_users_range,
192
list: ParsedCli.users_list
193
)
194
195
output('@info', msg: "Enumerating Users #{enum_detection_message(opts[:mode])}") if user_interaction?
196
output('users', users: target.users(opts))
197
end
198
199
# @return [ Range ] The user ids range to enumerate
200
# If the --enumerate is used, the default value is handled by the Option
201
# However, when using --passwords alone, the default has to be set by the code below
202
def enum_users_range
203
ParsedCli.enumerate[:users] || cli_enum_choices[0].choices[:u].validate(nil)
204
end
205
end
206
end
207
end
208
209