Land #5914, prevent loading cached modules outside of the load path
commit
895b692b0d
|
@ -9,52 +9,62 @@ module Msf
|
|||
def init_module_paths(opts={})
|
||||
if @module_paths_inited
|
||||
fail "Module paths already initialized. To add more module paths call `modules.add_module_path`"
|
||||
else
|
||||
# Ensure the module cache is accurate
|
||||
self.modules.refresh_cache_from_database
|
||||
|
||||
add_engine_module_paths(Rails.application, opts)
|
||||
|
||||
Rails.application.railties.engines.each do |engine|
|
||||
add_engine_module_paths(engine, opts)
|
||||
end
|
||||
|
||||
# Initialize the user module search path
|
||||
if (Msf::Config.user_module_directory)
|
||||
self.modules.add_module_path(Msf::Config.user_module_directory, opts)
|
||||
end
|
||||
|
||||
# If additional module paths have been defined globally, then load them.
|
||||
# They should be separated by semi-colons.
|
||||
if self.datastore['MsfModulePaths']
|
||||
self.datastore['MsfModulePaths'].split(";").each { |path|
|
||||
self.modules.add_module_path(path, opts)
|
||||
}
|
||||
end
|
||||
|
||||
@module_paths_inited = true
|
||||
return
|
||||
end
|
||||
|
||||
allowed_module_paths = []
|
||||
extract_engine_module_paths(Rails.application).each do |path|
|
||||
allowed_module_paths << path
|
||||
end
|
||||
|
||||
if Msf::Config.user_module_directory
|
||||
allowed_module_paths << Msf::Config.user_module_directory
|
||||
end
|
||||
|
||||
Rails.application.railties.engines.each do |engine|
|
||||
extract_engine_module_paths(engine).each do |path|
|
||||
allowed_module_paths << path
|
||||
end
|
||||
end
|
||||
|
||||
# If additional module paths have been defined globally, then load them.
|
||||
# They should be separated by semi-colons.
|
||||
self.datastore['MsfModulePaths'].to_s.split(";").each do |path|
|
||||
allowed_module_paths << path
|
||||
end
|
||||
|
||||
# If the caller had additional paths to search, load them.
|
||||
# They should be separated by semi-colons.
|
||||
opts.delete(:module_paths).to_s.split(";").each do |path|
|
||||
allowed_module_paths << path
|
||||
end
|
||||
|
||||
# Remove any duplicate paths
|
||||
allowed_module_paths.uniq!
|
||||
|
||||
# Update the module cache from the database
|
||||
self.modules.refresh_cache_from_database(allowed_module_paths)
|
||||
|
||||
# Load each of the module paths
|
||||
allowed_module_paths.each do |path|
|
||||
self.modules.add_module_path(path, opts)
|
||||
end
|
||||
|
||||
@module_paths_inited = true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Add directories `engine.paths['modules']` from `engine`.
|
||||
# Extract directories `engine.paths['modules']` from `engine`.
|
||||
#
|
||||
# @param engine [Rails::Engine] a rails engine or application
|
||||
# @param options [Hash] options for {Msf::ModuleManager::ModulePaths#add_module_paths}
|
||||
# @return [void]
|
||||
def add_engine_module_paths(engine, options={})
|
||||
modules_paths = engine.paths['modules']
|
||||
|
||||
if modules_paths
|
||||
modules_directories = modules_paths.existent_directories
|
||||
|
||||
modules_directories.each do |modules_directory|
|
||||
modules.add_module_path(modules_directory, options)
|
||||
end
|
||||
end
|
||||
# @return [Array<String>] The list of module paths to load
|
||||
def extract_engine_module_paths(engine)
|
||||
engine.paths['modules'] ? engine.paths['modules'].existent_directories : []
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -113,15 +113,15 @@ module Msf::ModuleManager::Cache
|
|||
framework.db.update_all_module_details
|
||||
end
|
||||
|
||||
refresh_cache_from_database
|
||||
refresh_cache_from_database(self.module_paths)
|
||||
end
|
||||
end
|
||||
|
||||
# Refreshes the in-memory cache from the database cache.
|
||||
#
|
||||
# @return [void]
|
||||
def refresh_cache_from_database
|
||||
self.module_info_by_path_from_database!
|
||||
def refresh_cache_from_database(allowed_paths=[""])
|
||||
self.module_info_by_path_from_database!(allowed_paths)
|
||||
end
|
||||
|
||||
protected
|
||||
|
@ -149,10 +149,12 @@ module Msf::ModuleManager::Cache
|
|||
# @return [Hash{String => Hash{Symbol => Object}}] Maps path (Mdm::Module::Detail#file) to module information. Module
|
||||
# information is a Hash derived from Mdm::Module::Detail. It includes :modification_time, :parent_path, :type,
|
||||
# :reference_name.
|
||||
def module_info_by_path_from_database!
|
||||
def module_info_by_path_from_database!(allowed_paths=[""])
|
||||
self.module_info_by_path = {}
|
||||
|
||||
if framework_migrated?
|
||||
allowed_paths = allowed_paths.map{|x| x + "/"}
|
||||
|
||||
ActiveRecord::Base.connection_pool.with_connection do
|
||||
# TODO record module parent_path in Mdm::Module::Detail so it does not need to be derived from file.
|
||||
# Use find_each so Mdm::Module::Details are returned in batches, which will
|
||||
|
@ -162,6 +164,9 @@ module Msf::ModuleManager::Cache
|
|||
type = module_detail.mtype
|
||||
reference_name = module_detail.refname
|
||||
|
||||
# Skip cached modules that are not in our allowed load paths
|
||||
next if allowed_paths.select{|x| path.index(x) == 0}.empty?
|
||||
|
||||
typed_path = Msf::Modules::Loader::Base.typed_path(type, reference_name)
|
||||
# join to '' so that typed_path_prefix starts with file separator
|
||||
typed_path_suffix = File.join('', typed_path)
|
||||
|
|
|
@ -186,15 +186,7 @@ class Driver < Msf::Ui::Driver
|
|||
|
||||
# framework.db.active will be true if after_establish_connection ran directly when connection_established? was
|
||||
# already true or if framework.db.connect called after_establish_connection.
|
||||
if framework.db.active
|
||||
unless opts['DeferModuleLoads']
|
||||
self.framework.modules.refresh_cache_from_database
|
||||
|
||||
if self.framework.modules.cache_empty?
|
||||
print_status("The initial module cache will be built in the background, this can take 2-5 minutes...")
|
||||
end
|
||||
end
|
||||
elsif !framework.db.error.nil?
|
||||
if !! framework.db.error
|
||||
if framework.db.error.to_s =~ /RubyGem version.*pg.*0\.11/i
|
||||
print_error("***")
|
||||
print_error("*")
|
||||
|
@ -217,12 +209,15 @@ class Driver < Msf::Ui::Driver
|
|||
# Initialize the module paths only if we didn't get passed a Framework instance and 'DeferModuleLoads' is false
|
||||
unless opts['Framework'] || opts['DeferModuleLoads']
|
||||
# Configure the framework module paths
|
||||
self.framework.init_module_paths
|
||||
self.framework.modules.add_module_path(opts['ModulePath']) if opts['ModulePath']
|
||||
self.framework.init_module_paths(module_paths: opts['ModulePath'])
|
||||
end
|
||||
|
||||
# Rebuild the module cache in a background thread
|
||||
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||
self.framework.modules.refresh_cache_from_module_files
|
||||
if framework.db.active && !opts['DeferModuleLoads']
|
||||
if self.framework.modules.cache_empty?
|
||||
self.framework.threads.spawn("ModuleCacheRebuild", true) do
|
||||
self.framework.modules.refresh_cache_from_module_files
|
||||
end
|
||||
print_status("The initial module cache will be built in the background, this can take 2-5 minutes...")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue