Merge branch 'staging/electro-release' of github.com:rapid7/metasploit-framework into staging/electro-release

bug/bundler_fix
Samuel Huckins 2014-07-31 12:31:27 -05:00
commit 735687e6a1
19 changed files with 624 additions and 183 deletions

View File

@ -7,7 +7,7 @@ group :db do
# Needed for Msf::DbManager
gem 'activerecord', '>= 3.0.0', '< 4.0.0'
# Metasploit::Credential database models
gem 'metasploit-credential', '~> 0.7.14', '< 0.8'
gem 'metasploit-credential', '~>0.8.2'
# Database models shared between framework and Pro.
gem 'metasploit_data_models', '~> 0.19'
# Needed for module caching in Mdm::ModuleDetails

View File

@ -61,10 +61,10 @@ GEM
json (1.8.1)
metasploit-concern (0.1.1)
activesupport (~> 3.0, >= 3.0.0)
metasploit-credential (0.7.16)
metasploit-credential (0.8.3)
metasploit-concern (~> 0.1.0)
metasploit-model (>= 0.25.6)
metasploit_data_models (~> 0.19)
metasploit-model (~> 0.26.1)
metasploit_data_models (~> 0.19.4)
pg
rubyntlm
rubyzip (~> 1.1)
@ -160,7 +160,7 @@ DEPENDENCIES
factory_girl (>= 4.1.0)
factory_girl_rails
fivemat (= 1.2.1)
metasploit-credential (~> 0.7.14, < 0.8)
metasploit-credential (~> 0.8.2)
metasploit-framework!
metasploit_data_models (~> 0.19)
network_interface (~> 0.0.1)

View File

@ -1,4 +1,11 @@
#!/usr/bin/env rake
require File.expand_path('../config/application', __FILE__)
require 'metasploit/framework/require'
# @note must be before `Metasploit::Framework::Application.load_tasks`
#
# define db rake tasks from activerecord if activerecord is in the bundle. activerecord could be not in the bundle if
# the user installs with `bundle install --without db`
Metasploit::Framework::Require.optionally_active_record_railtie
Metasploit::Framework::Application.load_tasks

View File

@ -1,18 +1,6 @@
require 'rails'
require File.expand_path('../boot', __FILE__)
# only the parts of 'rails/all' that metasploit-framework actually uses
begin
require 'active_record/railtie'
rescue LoadError
warn "activerecord not in the bundle, so database support will be disabled."
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
warn "To clear the without option do `bundle install --without ''` " \
"(the --without flag with an empty string) or " \
"`rm -rf .bundle` to remove the .bundle/config manually and " \
"then `bundle install`"
end
all_environments = [
:development,
:production,

View File

@ -0,0 +1,26 @@
#
# Gems
#
# have to be exact so minimum is loaded prior to parsing arguments which could
# influence loading.
require 'active_support/dependencies/autoload'
# @note Must use the nested declaration of the
# {Metasploit::Framework::Command} namespace because commands need to be able
# to be required directly without any other part of metasploit-framework
# besides config/boot so that the commands can parse arguments, setup
# RAILS_ENV, and load config/application.rb correctly.
module Metasploit
module Framework
module Command
# Namespace for commands for metasploit-framework. There are
# corresponding classes in the {Metasploit::Framework::ParsedOptions}
# namespace, which handle for parsing the options for each command.
extend ActiveSupport::Autoload
autoload :Base
autoload :Console
end
end
end

View File

@ -0,0 +1,110 @@
#
# Gems
#
require 'active_support/core_ext/module/introspection'
#
# Project
#
require 'metasploit/framework/command'
require 'metasploit/framework/parsed_options'
require 'metasploit/framework/require'
# Based on pattern used for lib/rails/commands in the railties gem.
class Metasploit::Framework::Command::Base
#
# Attributes
#
# @!attribute [r] application
# The Rails application for metasploit-framework.
#
# @return [Metasploit::Framework::Application]
attr_reader :application
# @!attribute [r] parsed_options
# The parsed options from the command line.
#
# @return (see parsed_options)
attr_reader :parsed_options
#
# Class Methods
#
# @note {require_environment!} should be called to load
# `config/application.rb` to so that the RAILS_ENV can be set from the
# command line options in `ARGV` prior to `Rails.env` being set.
# @note After returning, `Rails.application` will be defined and configured.
#
# Parses `ARGV` for command line arguments to configure the
# `Rails.application`.
#
# @return (see parsed_options)
def self.require_environment!
parsed_options = self.parsed_options
# RAILS_ENV must be set before requiring 'config/application.rb'
parsed_options.environment!
ARGV.replace(parsed_options.positional)
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/commands.rb#L39-L40
require Pathname.new(__FILE__).parent.parent.parent.parent.parent.join('config', 'application')
# have to configure before requiring environment because
# config/environment.rb calls initialize! and the initializers will use
# the configuration from the parsed options.
parsed_options.configure(Rails.application)
# support disabling the database
unless parsed_options.options.database.disable
Metasploit::Framework::Require.optionally_active_record_railtie
end
Rails.application.require_environment!
parsed_options
end
def self.parsed_options
parsed_options_class.new
end
def self.parsed_options_class
@parsed_options_class ||= parsed_options_class_name.constantize
end
def self.parsed_options_class_name
@parsed_options_class_name ||= "#{parent.parent}::ParsedOptions::#{name.demodulize}"
end
def self.start
parsed_options = require_environment!
new(application: Rails.application, parsed_options: parsed_options).start
end
#
# Instance Methods
#
# @param attributes [Hash{Symbol => ActiveSupport::OrderedOptions,Rails::Application}]
# @option attributes [Rails::Application] :application
# @option attributes [ActiveSupport::OrderedOptions] :parsed_options
# @raise [KeyError] if :application is not given
# @raise [KeyError] if :parsed_options is not given
def initialize(attributes={})
@application = attributes.fetch(:application)
@parsed_options = attributes.fetch(:parsed_options)
end
# @abstract Use {#application} to start this command.
#
# Starts this command.
#
# @return [void]
# @raise [NotImplementedError]
def start
raise NotImplementedError
end
end

View File

@ -0,0 +1,58 @@
#
# Project
#
require 'metasploit/framework/command'
require 'metasploit/framework/command/base'
# Based on pattern used for lib/rails/commands in the railties gem.
class Metasploit::Framework::Command::Console < Metasploit::Framework::Command::Base
def start
driver.run
end
private
# The console UI driver.
#
# @return [Msf::Ui::Console::Driver]
def driver
unless @driver
# require here so minimum loading is done before {start} is called.
require 'msf/ui'
@driver = Msf::Ui::Console::Driver.new(
Msf::Ui::Console::Driver::DefaultPrompt,
Msf::Ui::Console::Driver::DefaultPromptChar,
driver_options
)
end
@driver
end
def driver_options
unless @driver_options
options = parsed_options.options
driver_options = {}
driver_options['Config'] = options.framework.config
driver_options['DatabaseEnv'] = options.environment
driver_options['DatabaseMigrationPaths'] = options.database.migrations_paths
driver_options['DatabaseYAML'] = options.database.config
driver_options['Defanged'] = options.console.defanged
driver_options['DisableBanner'] = options.console.quiet
driver_options['DisableDatabase'] = options.database.disable
driver_options['LocalOutput'] = options.console.local_output
driver_options['ModulePath'] = options.modules.path
driver_options['Plugins'] = options.console.plugins
driver_options['RealReadline'] = options.console.real_readline
driver_options['Resource'] = options.console.resource
driver_options['XCommands'] = options.console.commands
@driver_options = driver_options
end
@driver_options
end
end

View File

@ -0,0 +1,27 @@
#
# Gems
#
require 'active_support/dependencies/autoload'
# @note Must use the nested declaration of the
# {Metasploit::Framework::ParsedOptions} namespace because commands, which
# use parsed options, need to be able to be required directly without any
# other part of metasploit-framework besides config/boot so that the
# commands can parse arguments, setup RAILS_ENV, and load
# config/application.rb correctly.
module Metasploit
module Framework
# Namespace for parsed options for {Metasploit::Framework::Command
# commands}. The names of `Class`es in this namespace correspond to the
# name of the `Class` in the {Metasploit::Framework::Command} namespace
# for which this namespace's `Class` parses options.
module ParsedOptions
extend ActiveSupport::Autoload
autoload :Base
autoload :Console
end
end
end

View File

@ -0,0 +1,183 @@
#
# Standard Library
#
require 'optparse'
#
# Gems
#
require 'active_support/ordered_options'
#
# Project
#
require 'metasploit/framework/parsed_options'
require 'msf/base/config'
# Options parsed from the command line that can be used to change the
# `Metasploit::Framework::Application.config` and `Rails.env`
class Metasploit::Framework::ParsedOptions::Base
#
# CONSTANTS
#
# msfconsole boots in production mode instead of the normal rails default of
# development.
DEFAULT_ENVIRONMENT = 'production'
#
# Attributes
#
attr_reader :positional
#
# Instance Methods
#
def initialize(arguments=ARGV)
@positional = option_parser.parse(arguments)
end
# Translates {#options} to the `application`'s config
#
# @param application [Rails::Application]
# @return [void]
def configure(application)
application.config['config/database'] = options.database.config
end
# Sets the `RAILS_ENV` environment variable.
#
# 1. If the -E/--environment option is given, then its value is used.
# 2. The default value, 'production', is used.
#
# @return [void]
def environment!
if defined?(Rails) && Rails.instance_variable_defined?(:@_env)
raise "#{self.class}##{__method__} called too late to set RAILS_ENV: Rails.env already memoized"
end
ENV['RAILS_ENV'] = options.environment
end
# Options parsed from
#
# @return [ActiveSupport::OrderedOptions]
def options
unless @options
options = ActiveSupport::OrderedOptions.new
options.database = ActiveSupport::OrderedOptions.new
user_config_root = Pathname.new(Msf::Config.get_config_root)
user_database_yaml = user_config_root.join('database.yml')
if user_database_yaml.exist?
options.database.config = user_database_yaml.to_path
else
options.database.config = 'config/database.yml'
end
options.database.disable = false
options.database.migrations_paths = []
options.framework = ActiveSupport::OrderedOptions.new
options.framework.config = nil
options.modules = ActiveSupport::OrderedOptions.new
options.modules.path = nil
options.environment = DEFAULT_ENVIRONMENT
@options = options
end
@options
end
private
# Parses arguments into {#options}.
#
# @return [OptionParser]
def option_parser
@option_parser ||= OptionParser.new { |option_parser|
option_parser.separator ''
option_parser.separator 'Common options'
option_parser.on(
'-E',
'--environment ENVIRONMENT',
%w{development production test},
"The Rails environment. Will use RAIL_ENV environment variable if that is set. " \
"Defaults to production if neither option not RAILS_ENV environment variable is set."
) do |environment|
options.environment = environment
end
option_parser.separator ''
option_parser.separator 'Database options'
option_parser.on(
'-M',
'--migration-path DIRECTORY',
'Specify a directory containing additional DB migrations'
) do |directory|
options.database.migrations_paths << directory
end
option_parser.on('-n', '--no-database', 'Disable database support') do
options.database.disable = true
end
option_parser.on(
'-y',
'--yaml PATH',
'Specify a YAML file containing database settings'
) do |path|
options.database.config = path
end
option_parser.separator ''
option_parser.separator 'Framework options'
option_parser.on('-c', '-c FILE', 'Load the specified configuration file') do |file|
options.framework.config = file
end
option_parser.on(
'-v',
'--version',
'Show version'
) do
options.subcommand = :version
end
option_parser.separator ''
option_parser.separator 'Module options'
option_parser.on(
'-m',
'--module-path DIRECTORY',
'An additional module path'
) do |directory|
options.modules.path = directory
end
#
# Tail
#
option_parser.separator ''
option_parser.on_tail('-h', '--help', 'Show this message') do
puts option_parser
exit
end
}
end
end

View File

@ -0,0 +1,73 @@
# Parsed options for {Metasploit::Framework::Command::Console}
class Metasploit::Framework::ParsedOptions::Console < Metasploit::Framework::ParsedOptions::Base
# Options parsed from msfconsole command-line.
#
# @return [ActiveSupport::OrderedOptions]
def options
unless @options
super.tap { |options|
options.console = ActiveSupport::OrderedOptions.new
options.console.commands = []
options.console.defanged = false
options.console.local_output = nil
options.console.plugins = []
options.console.quiet = false
options.console.real_readline = false
options.console.resources = []
}
end
@options
end
private
# Parses msfconsole arguments into {#options}.
#
# @return [OptionParser]
def option_parser
unless @option_parser
super.tap { |option_parser|
option_parser.banner = "Usage: #{option_parser.program_name} [options]"
option_parser.separator ''
option_parser.separator 'Console options:'
option_parser.on('-d', '--defanged', 'Execute the console as defanged') do
options.console.defanged = true
end
option_parser.on('-L', '--real-readline', 'Use the system Readline library instead of RbReadline') do
options.console.real_readline = true
end
option_parser.on('-o', '--output FILE', 'Output to the specified file') do |file|
options.console.local_output = file
end
option_parser.on('-p', '--plugin PLUGIN', 'Load a plugin on startup') do |plugin|
options.console.plugins << plugin
end
option_parser.on('-q', '--quiet', 'Do not print the banner on start up') do
options.console.quiet = true
end
option_parser.on('-r', '--resource FILE', 'Execute the specified resource file') do |file|
options.console.resources << file
end
option_parser.on(
'-x',
'--execute-command COMMAND',
'Execute the specified string as console commands (use ; for multiples)'
) do |commands|
options.console.commands += commands.split(/\s*;\s*/)
end
}
end
@option_parser
end
end

View File

@ -0,0 +1,92 @@
# @note needs to use explicit nesting. so this file can be loaded directly without loading 'metasploit/framework', this
# file can be used prior to Bundler.require.
module Metasploit
module Framework
# Extension to `Kernel#require` behavior.
module Require
#
# Module Methods
#
# Tries to require `name`. If a `LoadError` occurs, then `without_warning` is printed to standard error using
# `Kernel#warn`, along with instructions for reinstalling the bundle. If a `LoadError` does not occur, then
# `with_block` is called.
#
# @param name [String] the name of the library to `Kernel#require`.
# @param without_warning [String] warning to print if `name` cannot be required.
# @yield block to run when `name` requires successfully
# @yieldreturn [void]
# @return [void]
def self.optionally(name, without_warning)
begin
require name
rescue LoadError
warn without_warning
warn "Bundle installed '--without #{Bundler.settings.without.join(' ')}'"
warn "To clear the without option do `bundle install --without ''` " \
"(the --without flag with an empty string) or " \
"`rm -rf .bundle` to remove the .bundle/config manually and " \
"then `bundle install`"
else
if block_given?
yield
end
end
end
# Tries to `require 'active_record/railtie'` to define the activerecord Rails initializers and rake tasks.
#
# @example Optionally requiring 'active_record/railtie'
# require 'metasploit/framework/require'
#
# class MyClass
# def setup
# if database_enabled
# Metasploit::Framework::Require.optionally_active_record_railtie
# end
# end
# end
#
# @return [void]
def self.optionally_active_record_railtie
optionally(
'active_record/railtie',
'activerecord not in the bundle, so database support will be disabled.'
)
end
# Tries to `require 'metasploit/credential/creation'` and include it in the `including_module`.
#
# @param including_module [Module] `Class` or `Module` that wants to `include Metasploit::Credential::Creation`.
# @return [void]
def self.optionally_include_metasploit_credential_creation(including_module)
optionally(
'metasploit/credential/creation',
"metasploit-credential not in the bundle, so Metasploit::Credential creation will fail for #{including_module.name}",
) do
including_module.send(:include, Metasploit::Credential::Creation)
end
end
#
# Instance Methods
#
# Tries to `require 'metasploit/credential/creation'` and include it in this `Class` or `Module`.
#
# @example Using in a `Module`
# require 'metasploit/framework/require'
#
# module MyModule
# extend Metasploit::Framework::Require
#
# optionally_include_metasploit_credential_creation
# end
#
# @return [void]
def optionally_include_metasploit_credential_creation
Metasploit::Framework::Require.optionally_include_metasploit_credential_creation(self)
end
end
end
end

View File

@ -10,7 +10,6 @@ require 'fileutils'
# Project
#
require 'msf/core'
require 'rex/compat'
module Msf
@ -37,16 +36,16 @@ class Config < Hash
['HOME', 'LOCALAPPDATA', 'APPDATA', 'USERPROFILE'].each do |dir|
val = Rex::Compat.getenv(dir)
if (val and File.directory?(val))
return File.join(val, ".msf#{Msf::Framework::Major}")
return File.join(val, ".msf#{Metasploit::Framework::Version::MAJOR}")
end
end
begin
# First we try $HOME/.msfx
File.expand_path("~#{FileSep}.msf#{Msf::Framework::Major}")
File.expand_path("~#{FileSep}.msf#{Metasploit::Framework::Version::MAJOR}")
rescue ::ArgumentError
# Give up and install root + ".msfx"
InstallRoot + ".msf#{Msf::Framework::Major}"
InstallRoot + ".msf#{Metasploit::Framework::Version::MAJOR}"
end
end

View File

@ -1,4 +1,3 @@
require 'metasploit/credential/creation'
# -*- coding: binary -*-
module Msf
@ -9,8 +8,9 @@ module Msf
###
module Auxiliary::Report
extend Metasploit::Framework::Require
include Metasploit::Credential::Creation
optionally_include_metasploit_credential_creation
# This method overrides the method from Metasploit::Credential to check for an active db
def active_db?

View File

@ -55,8 +55,8 @@ require 'rex/parser/retina_xml'
# Project
#
require 'metasploit/framework/require'
require 'msf/core/db_manager/import_msf_xml'
require 'metasploit/credential/creation'
module Msf
@ -156,8 +156,10 @@ end
#
###
class DBManager
extend Metasploit::Framework::Require
include Msf::DBManager::ImportMsfXml
include Metasploit::Credential::Creation
optionally_include_metasploit_credential_creation
def rfc3330_reserved(ip)
case ip.class.to_s
@ -2897,18 +2899,16 @@ class DBManager
data = ""
::File.open(filename, 'rb') do |f|
data = f.read(4)
# This check is the largest (byte-wise) that we need to do
# since the other 4-byte checks will be subsets of this larger one.
data = f.read(Metasploit::Credential::Exporter::Pwdump::FILE_ID_STRING.size)
end
if data.nil?
raise DBImportError.new("Zero-length file")
end
io = File.open(filename)
first_line = io.gets
io.rewind
if first_line.index("# Metasploit PWDump Export")
data = io
if data.index(Metasploit::Credential::Exporter::Pwdump::FILE_ID_STRING)
data = ::File.open(filename, 'rb')
else
case data[0,4]
when "PK\x03\x04"
@ -2929,7 +2929,6 @@ class DBManager
else
import(args.merge(:data => data))
end
end
# A dispatcher method that figures out the data's file type,
@ -3539,6 +3538,7 @@ class DBManager
origin = Metasploit::Credential::Origin::Import.create!(filename: filename)
importer = Metasploit::Credential::Importer::Pwdump.new(input: args[:data], workspace: wspace, filename: filename, origin:origin)
importer.import!
importer.input.close unless importer.input.closed?
end
# If hex notation is present, turn them into a character.

View File

@ -1,5 +1,3 @@
require 'metasploit/credential/creation'
module Msf
class DBManager
# Handles importing of the xml format exported by Pro. The methods are in a
@ -8,7 +6,6 @@ module Msf
# methods defined in a class cannot be overridden by including a module
# (unless you're running Ruby 2.0 and can use prepend)
module ImportMsfXml
include Metasploit::Credential::Creation
#
# CONSTANTS
#

View File

@ -2,6 +2,7 @@
require 'rex/exploitation/cmdstager'
require 'msf/core/exploit/exe'
require 'msf/base/config'
module Msf

View File

@ -690,6 +690,8 @@ class Db
print_line " creds add-ntlm alice 5cfe4c82d9ab8c66590f5b47cd6690f1:978a2e2e1dec9804c6b936f254727f9a"
print_line " # Add a user with a blank password and a domain"
print_line " creds add-password bob '' contosso"
print_line " # Add a user with an SSH key"
print_line " creds add-ssh-key root /root/.ssh/id_rsa"
print_line
end

View File

@ -9,146 +9,18 @@
# $Revision$
#
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
@msfbase_dir = File.expand_path(File.dirname(msfbase))
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'fastlib'
require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'optparse'
if(RUBY_PLATFORM =~ /mswin32/)
$stderr.puts "[*] The msfconsole interface is not supported on the native Windows Ruby\n"
$stderr.puts " interpreter. Things will break, exploits will fail, payloads will not\n"
$stderr.puts " be handled correctly. Please install Cygwin or use Linux in VMWare.\n\n"
end
class OptsConsole
#
# Return a hash describing the options.
#
def self.parse(args)
options = {
'DeferModuleLoads' => true
}
opts = OptionParser.new do |opts|
opts.banner = "Usage: msfconsole [options]"
opts.separator ""
opts.separator "Specific options:"
opts.on("-d", "-d", "Execute the console as defanged") do
options['Defanged'] = true
end
opts.on("-r", "-r <filename>", "Execute the specified resource file") do |r|
options['Resource'] ||= []
options['Resource'] << r
end
opts.on("-o", "-o <filename>", "Output to the specified file") do |o|
options['LocalOutput'] = o
end
opts.on("-c", "-c <filename>", "Load the specified configuration file") do |c|
options['Config'] = c
end
opts.on("-m", "-m <directory>", "Specifies an additional module search path") do |m|
options['ModulePath'] = m
end
opts.on("-p", "-p <plugin>", "Load a plugin on startup") do |p|
options['Plugins'] ||= []
options['Plugins'] << p
end
opts.on("-y", "--yaml <database.yml>", "Specify a YAML file containing database settings") do |m|
options['DatabaseYAML'] = m
end
opts.on("-M", "--migration-path <dir>", "Specify a directory containing additional DB migrations") do |m|
options['DatabaseMigrationPaths'] ||= []
options['DatabaseMigrationPaths'] << m
end
opts.on("-e", "--environment <production|development>", "Specify the database environment to load from the YAML") do |m|
options['DatabaseEnv'] = m
end
# Boolean switches
opts.on("-v", "--version", "Show version") do |v|
options['Version'] = true
end
opts.on("-L", "--real-readline", "Use the system Readline library instead of RbReadline") do |v|
options['RealReadline'] = true
end
opts.on("-n", "--no-database", "Disable database support") do |v|
options['DisableDatabase'] = true
end
opts.on("-q", "--quiet", "Do not print the banner on start up") do |v|
options['DisableBanner'] = true
end
opts.on("-x", "-x <command>", "Execute the specified string as console commands (use ; for multiples)") do |s|
options['XCommands'] ||= []
options['XCommands'] += s.split(/\s*;\s*/)
end
opts.separator ""
opts.separator "Common options:"
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
end
begin
opts.parse!(args)
rescue OptionParser::InvalidOption
puts "Invalid option, try -h for usage"
exit
end
options
end
end
options = OptsConsole.parse(ARGV)
#
# NOTE: we don't require this until down here since we may not need it
# when processing certain options (currently only -h)
#
require 'rex'
require 'msf/ui'
#
# Everything below this line requires the framework.
# Standard Library
#
if (options['Version'])
$stderr.puts 'Framework Version: ' + Msf::Framework::Version
exit
end
require 'pathname'
begin
Msf::Ui::Console::Driver.new(
Msf::Ui::Console::Driver::DefaultPrompt,
Msf::Ui::Console::Driver::DefaultPromptChar,
options
).run
rescue Interrupt
end
#
# Project
#
# @see https://github.com/rails/rails/blob/v3.2.17/railties/lib/rails/generators/rails/app/templates/script/rails#L3-L5
require Pathname.new(__FILE__).expand_path.parent.join('config', 'boot')
require 'metasploit/framework/command/console'
Metasploit::Framework::Command::Console.start

View File

@ -3,6 +3,12 @@ ENV['RAILS_ENV'] = 'test'
require 'simplecov'
# @note must be before loading config/environment because railtie needs to be loaded before
# `Metasploit::Framework::Application.initialize!` is called.
#
# Must be explicit as activerecord is optional dependency
require 'active_record/railtie'
require File.expand_path('../../config/environment', __FILE__)
# Don't `require 'rspec/rails'` as it includes support for pieces of rails that metasploit-framework doesn't use