HELLO v3!!!

This commit is contained in:
Ryan Dewhurst
2018-09-26 21:12:01 +02:00
parent 28b9c15256
commit d268a86795
1871 changed files with 988118 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
module WPScan
module Controller
# Enumeration CLI Options
class Enumeration < CMSScanner::Controller::Base
def cli_options
cli_enum_choices + cli_plugins_opts + cli_themes_opts +
cli_timthumbs_opts + cli_config_backups_opts + cli_db_exports_opts +
cli_medias_opts + cli_users_opts
end
# @return [ Array<OptParseValidator::OptBase> ]
# rubocop:disable Metrics/MethodLength
def cli_enum_choices
[
OptMultiChoices.new(
['--enumerate [OPTS]', '-e', 'Enumeration Process'],
choices: {
vp: OptBoolean.new(['--vulnerable-plugins']),
ap: OptBoolean.new(['--all-plugins']),
p: OptBoolean.new(['--plugins']),
vt: OptBoolean.new(['--vulnerable-themes']),
at: OptBoolean.new(['--all-themes']),
t: OptBoolean.new(['--themes']),
tt: OptBoolean.new(['--timthumbs']),
cb: OptBoolean.new(['--config-backups']),
dbe: OptBoolean.new(['--db-exports']),
u: OptIntegerRange.new(['--users', 'User IDs range. e.g: u1-5'], value_if_empty: '1-10'),
m: OptIntegerRange.new(['--medias', 'Media IDs range. e.g m1-15'], value_if_empty: '1-100')
},
value_if_empty: 'vp,vt,tt,cb,dbe,u,m',
incompatible: [%i[vp ap p], %i[vt at t]],
default: { all_plugins: true, config_backups: true }
),
OptRegexp.new(
[
'--exclude-content-based REGEXP_OR_STRING',
'Exclude all responses matching the Regexp (case insensitive) during parts of the enumeration.',
'Both the headers and body are checked. Regexp delimiters are not required.'
], options: Regexp::IGNORECASE
)
]
end
# rubocop:enable Metrics/MethodLength
# @return [ Array<OptParseValidator::OptBase> ]
def cli_plugins_opts
[
OptSmartList.new(['--plugins-list LIST', 'List of plugins to enumerate']),
OptChoice.new(
['--plugins-detection MODE',
'Use the supplied mode to enumerate Plugins, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym, default: :passive
),
OptBoolean.new(
['--plugins-version-all',
'Check all the plugins version locations according to the choosen mode (--detection-mode, ' \
'--plugins-detection and --plugins-version-detection)']
),
OptChoice.new(
['--plugins-version-detection MODE',
'Use the supplied mode to check plugins versions instead of the --detection-mode ' \
'or --plugins-detection modes.'],
choices: %w[mixed passive aggressive], normalize: :to_sym, default: :mixed
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_themes_opts
[
OptSmartList.new(['--themes-list LIST', 'List of themes to enumerate']),
OptChoice.new(
['--themes-detection MODE',
'Use the supplied mode to enumerate Themes, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
),
OptBoolean.new(
['--themes-version-all',
'Check all the themes version locations according to the choosen mode (--detection-mode, ' \
'--themes-detection and --themes-version-detection)']
),
OptChoice.new(
['--themes-version-detection MODE',
'Use the supplied mode to check themes versions instead of the --detection-mode ' \
'or --themes-detection modes.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_timthumbs_opts
[
OptFilePath.new(
['--timthumbs-list FILE-PATH', 'List of timthumbs\' location to use'],
exists: true, default: File.join(DB_DIR, 'timthumbs-v3.txt')
),
OptChoice.new(
['--timthumbs-detection MODE',
'Use the supplied mode to enumerate Timthumbs, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_config_backups_opts
[
OptFilePath.new(
['--config-backups-list FILE-PATH', 'List of config backups\' filenames to use'],
exists: true, default: File.join(DB_DIR, 'config_backups.txt')
),
OptChoice.new(
['--config-backups-detection MODE',
'Use the supplied mode to enumerate Config Backups, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_db_exports_opts
[
OptFilePath.new(
['--db-exports-list FILE-PATH', 'List of DB exports\' paths to use'],
exists: true, default: File.join(DB_DIR, 'db_exports.txt')
),
OptChoice.new(
['--db-exports-detection MODE',
'Use the supplied mode to enumerate DB Exports, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_medias_opts
[
OptChoice.new(
['--medias-detection MODE',
'Use the supplied mode to enumerate Medias, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
# @return [ Array<OptParseValidator::OptBase> ]
def cli_users_opts
[
OptSmartList.new(
['--users-list LIST',
'List of users to check during the users enumeration from the Login Error Messages']
),
OptChoice.new(
['--users-detection MODE',
'Use the supplied mode to enumerate Users, instead of the global (--detection-mode) mode.'],
choices: %w[mixed passive aggressive], normalize: :to_sym
)
]
end
end
end
end

View File

@@ -0,0 +1,178 @@
module WPScan
module Controller
# Enumeration Methods
class Enumeration < CMSScanner::Controller::Base
# @param [ String ] type (plugins or themes)
#
# @return [ String ] The related enumration message depending on the parsed_options and type supplied
def enum_message(type)
return unless %w[plugins themes].include?(type)
details = if parsed_options[:enumerate][:"vulnerable_#{type}"]
'Vulnerable'
elsif parsed_options[:enumerate][:"all_#{type}"]
'All'
else
'Most Popular'
end
"Enumerating #{details} #{type.capitalize}"
end
# @param [ String ] type (plugins, themes etc)
#
# @return [ Hash ]
def default_opts(type)
mode = parsed_options[:"#{type}_detection"] || parsed_options[:detection_mode]
{
mode: mode,
exclude_content: parsed_options[:exclude_content_based],
show_progression: user_interaction?,
version_detection: {
mode: parsed_options[:"#{type}_version_detection"] || mode,
confidence_threshold: parsed_options[:"#{type}_version_all"] ? 0 : 100
}
}
end
# @param [ Hash ] opts
#
# @return [ Boolean ] Wether or not to enumerate the plugins
def enum_plugins?(opts)
opts[:plugins] || opts[:all_plugins] || opts[:vulnerable_plugins]
end
def enum_plugins
opts = default_opts('plugins').merge(
list: plugins_list_from_opts(parsed_options),
sort: true
)
output('@info', msg: enum_message('plugins')) if user_interaction?
# Enumerate the plugins & find their versions to avoid doing that when #version
# is called in the view
plugins = target.plugins(opts)
output('@info', msg: 'Checking Plugin Versions') if user_interaction? && !plugins.empty?
plugins.each(&:version)
plugins.select!(&:vulnerable?) if parsed_options[:enumerate][:vulnerable_plugins]
output('plugins', plugins: plugins)
end
# @param [ Hash ] opts
#
# @return [ Array<String> ] The plugins list associated to the cli options
def plugins_list_from_opts(opts)
# List file provided by the user via the cli
return opts[:plugins_list] if opts[:plugins_list]
if opts[:enumerate][:all_plugins]
DB::Plugins.all_slugs
elsif opts[:enumerate][:plugins]
DB::Plugins.popular_slugs
else
DB::Plugins.vulnerable_slugs
end
end
# @param [ Hash ] opts
#
# @return [ Boolean ] Wether or not to enumerate the themes
def enum_themes?(opts)
opts[:themes] || opts[:all_themes] || opts[:vulnerable_themes]
end
def enum_themes
opts = default_opts('themes').merge(
list: themes_list_from_opts(parsed_options),
sort: true
)
output('@info', msg: enum_message('themes')) if user_interaction?
# Enumerate the themes & find their versions to avoid doing that when #version
# is called in the view
themes = target.themes(opts)
output('@info', msg: 'Checking Theme Versions') if user_interaction? && !themes.empty?
themes.each(&:version)
themes.select!(&:vulnerable?) if parsed_options[:enumerate][:vulnerable_themes]
output('themes', themes: themes)
end
# @param [ Hash ] opts
#
# @return [ Array<String> ] The themes list associated to the cli options
def themes_list_from_opts(opts)
# List file provided by the user via the cli
return opts[:themes_list] if opts[:themes_list]
if opts[:enumerate][:all_themes]
DB::Themes.all_slugs
elsif opts[:enumerate][:themes]
DB::Themes.popular_slugs
else
DB::Themes.vulnerable_slugs
end
end
def enum_timthumbs
opts = default_opts('timthumbs').merge(list: parsed_options[:timthumbs_list])
output('@info', msg: 'Enumerating Timthumbs') if user_interaction?
output('timthumbs', timthumbs: target.timthumbs(opts))
end
def enum_config_backups
opts = default_opts('config_backups').merge(list: parsed_options[:config_backups_list])
output('@info', msg: 'Enumerating Config Backups') if user_interaction?
output('config_backups', config_backups: target.config_backups(opts))
end
def enum_db_exports
opts = default_opts('db_exports').merge(list: parsed_options[:db_exports_list])
output('@info', msg: 'Enumerating DB Exports') if user_interaction?
output('db_exports', db_exports: target.db_exports(opts))
end
def enum_medias
opts = default_opts('medias').merge(range: parsed_options[:enumerate][:medias])
output('@info', msg: 'Enumerating Medias') if user_interaction?
output('medias', medias: target.medias(opts))
end
# @param [ Hash ] opts
#
# @return [ Boolean ] Wether or not to enumerate the users
def enum_users?(opts)
opts[:users] || (parsed_options[:passwords] && !parsed_options[:username] && !parsed_options[:usernames])
end
def enum_users
opts = default_opts('users').merge(
range: enum_users_range,
list: parsed_options[:users_list]
)
output('@info', msg: 'Enumerating Users') if user_interaction?
output('users', users: target.users(opts))
end
# @return [ Range ] The user ids range to enumerate
# If the --enumerate is used, the default value is handled by the Option
# However, when using --passwords alone, the default has to be set by the code below
def enum_users_range
parsed_options[:enumerate][:users] || cli_enum_choices[0].choices[:u].validate(nil)
end
end
end
end