Skip to content

Commit 77d99b7

Browse files
committed
Land rapid7#3586, fix msfconsole when running without db
Conflicts: Gemfile.lock metasploit-framework.gemspec
2 parents 1c35ec4 + e4f665f commit 77d99b7

File tree

17 files changed

+590
-160
lines changed

17 files changed

+590
-160
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ GEM
6161
json (1.8.1)
6262
metasploit-concern (0.1.1)
6363
activesupport (~> 3.0, >= 3.0.0)
64-
metasploit-credential (0.8.2)
64+
metasploit-credential (0.8.3)
6565
metasploit-concern (~> 0.1.0)
6666
metasploit-model (~> 0.26.1)
6767
metasploit_data_models (~> 0.19.4)

Rakefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
#!/usr/bin/env rake
22
require File.expand_path('../config/application', __FILE__)
3+
require 'metasploit/framework/require'
4+
5+
# @note must be before `Metasploit::Framework::Application.load_tasks`
6+
#
7+
# define db rake tasks from activerecord if activerecord is in the bundle. activerecord could be not in the bundle if
8+
# the user installs with `bundle install --without db`
9+
Metasploit::Framework::Require.optionally_active_record_railtie
310

411
Metasploit::Framework::Application.load_tasks

config/application.rb

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
require 'rails'
22
require File.expand_path('../boot', __FILE__)
33

4-
# only the parts of 'rails/all' that metasploit-framework actually uses
5-
begin
6-
require 'active_record/railtie'
7-
rescue LoadError
8-
warn "activerecord not in the bundle, so database support will be disabled."
9-
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
10-
warn "To clear the without option do `bundle install --without ''` " \
11-
"(the --without flag with an empty string) or " \
12-
"`rm -rf .bundle` to remove the .bundle/config manually and " \
13-
"then `bundle install`"
14-
end
15-
164
all_environments = [
175
:development,
186
:production,

lib/metasploit/framework/command.rb

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#
2+
# Gems
3+
#
4+
5+
# have to be exact so minimum is loaded prior to parsing arguments which could influence loading.
6+
require 'active_support/dependencies/autoload'
7+
8+
# @note Must use the nested declaration of the {Metasploit::Framework::Command} namespace because commands need to be
9+
# able to be required directly without any other part of metasploit-framework besides config/boot so that the commands
10+
# can parse arguments, setup RAILS_ENV, and load config/application.rb correctly.
11+
module Metasploit
12+
module Framework
13+
module Command
14+
# Namespace for commands for metasploit-framework. There are corresponding classes in the
15+
# {Metasploit::Framework::ParsedOptions} namespace, which handle for parsing the options for each command.
16+
extend ActiveSupport::Autoload
17+
18+
autoload :Base
19+
autoload :Console
20+
end
21+
end
22+
end
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
#
2+
# Gems
3+
#
4+
5+
require 'active_support/core_ext/module/introspection'
6+
7+
#
8+
# Project
9+
#
10+
11+
require 'metasploit/framework/command'
12+
require 'metasploit/framework/parsed_options'
13+
require 'metasploit/framework/require'
14+
15+
# Based on pattern used for lib/rails/commands in the railties gem.
16+
class Metasploit::Framework::Command::Base
17+
#
18+
# Attributes
19+
#
20+
21+
# @!attribute [r] application
22+
# The Rails application for metasploit-framework.
23+
#
24+
# @return [Metasploit::Framework::Application]
25+
attr_reader :application
26+
27+
# @!attribute [r] parsed_options
28+
# The parsed options from the command line.
29+
#
30+
# @return (see parsed_options)
31+
attr_reader :parsed_options
32+
33+
#
34+
# Class Methods
35+
#
36+
37+
# @note {require_environment!} should be called to load `config/application.rb` to so that the RAILS_ENV can be set
38+
# from the command line options in `ARGV` prior to `Rails.env` being set.
39+
# @note After returning, `Rails.application` will be defined and configured.
40+
#
41+
# Parses `ARGV` for command line arguments to configure the `Rails.application`.
42+
#
43+
# @return (see parsed_options)
44+
def self.require_environment!
45+
parsed_options = self.parsed_options
46+
# RAILS_ENV must be set before requiring 'config/application.rb'
47+
parsed_options.environment!
48+
ARGV.replace(parsed_options.positional)
49+
50+
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/commands.rb#L39-L40
51+
require Pathname.new(__FILE__).parent.parent.parent.parent.parent.join('config', 'application')
52+
53+
# have to configure before requiring environment because config/environment.rb calls initialize! and the initializers
54+
# will use the configuration from the parsed options.
55+
parsed_options.configure(Rails.application)
56+
57+
# support disabling the database
58+
unless parsed_options.options.database.disable
59+
Metasploit::Framework::Require.optionally_active_record_railtie
60+
end
61+
62+
Rails.application.require_environment!
63+
64+
parsed_options
65+
end
66+
67+
def self.parsed_options
68+
parsed_options_class.new
69+
end
70+
71+
def self.parsed_options_class
72+
@parsed_options_class ||= parsed_options_class_name.constantize
73+
end
74+
75+
def self.parsed_options_class_name
76+
@parsed_options_class_name ||= "#{parent.parent}::ParsedOptions::#{name.demodulize}"
77+
end
78+
79+
def self.start
80+
parsed_options = require_environment!
81+
new(application: Rails.application, parsed_options: parsed_options).start
82+
end
83+
84+
#
85+
# Instance Methods
86+
#
87+
88+
# @param attributes [Hash{Symbol => ActiveSupport::OrderedOptions,Rails::Application}]
89+
# @option attributes [Rails::Application] :application
90+
# @option attributes [ActiveSupport::OrderedOptions] :parsed_options
91+
# @raise [KeyError] if :application is not given
92+
# @raise [KeyError] if :parsed_options is not given
93+
def initialize(attributes={})
94+
@application = attributes.fetch(:application)
95+
@parsed_options = attributes.fetch(:parsed_options)
96+
end
97+
98+
# @abstract Use {#application} to start this command.
99+
#
100+
# Starts this command.
101+
#
102+
# @return [void]
103+
# @raise [NotImplementedError]
104+
def start
105+
raise NotImplementedError
106+
end
107+
end
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#
2+
# Project
3+
#
4+
5+
require 'metasploit/framework/command'
6+
require 'metasploit/framework/command/base'
7+
8+
# Based on pattern used for lib/rails/commands in the railties gem.
9+
class Metasploit::Framework::Command::Console < Metasploit::Framework::Command::Base
10+
def start
11+
driver.run
12+
end
13+
14+
private
15+
16+
# The console UI driver.
17+
#
18+
# @return [Msf::Ui::Console::Driver]
19+
def driver
20+
unless @driver
21+
# require here so minimum loading is done before {start} is called.
22+
require 'msf/ui'
23+
24+
@driver = Msf::Ui::Console::Driver.new(
25+
Msf::Ui::Console::Driver::DefaultPrompt,
26+
Msf::Ui::Console::Driver::DefaultPromptChar,
27+
driver_options
28+
)
29+
end
30+
31+
@driver
32+
end
33+
34+
def driver_options
35+
unless @driver_options
36+
options = parsed_options.options
37+
38+
driver_options = {}
39+
driver_options['Config'] = options.framework.config
40+
driver_options['DatabaseEnv'] = options.environment
41+
driver_options['DatabaseMigrationPaths'] = options.database.migrations_paths
42+
driver_options['DatabaseYAML'] = options.database.config
43+
driver_options['Defanged'] = options.console.defanged
44+
driver_options['DisableBanner'] = options.console.quiet
45+
driver_options['DisableDatabase'] = options.database.disable
46+
driver_options['LocalOutput'] = options.console.local_output
47+
driver_options['ModulePath'] = options.modules.path
48+
driver_options['Plugins'] = options.console.plugins
49+
driver_options['RealReadline'] = options.console.real_readline
50+
driver_options['Resource'] = options.console.resource
51+
driver_options['XCommands'] = options.console.commands
52+
53+
@driver_options = driver_options
54+
end
55+
56+
@driver_options
57+
end
58+
end
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#
2+
# Gems
3+
#
4+
5+
require 'active_support/dependencies/autoload'
6+
7+
# # @note Must use the nested declaration of the {Metasploit::Framework::ParsedOptions} namespace because commands,
8+
# which use parsed options, need to be able to be required directly without any other part of metasploit-framework
9+
# besides config/boot so that the commands can parse arguments, setup RAILS_ENV, and load config/application.rb
10+
# correctly.
11+
module Metasploit
12+
module Framework
13+
# Namespace for parsed options for {Metasploit::Framework::Command commands}. The names of `Class`es in this
14+
# namespace correspond to the name of the `Class` in the {Metasploit::Framework::Command} namespace for which this
15+
# namespace's `Class` parses options.
16+
module ParsedOptions
17+
extend ActiveSupport::Autoload
18+
19+
autoload :Base
20+
autoload :Console
21+
end
22+
end
23+
end
24+

0 commit comments

Comments
 (0)