CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/feature_manager.rb
Views: 11623
1
# -*- coding: binary -*-
2
# frozen_string_literal: true
3
4
require 'rex/text'
5
6
module Msf
7
###
8
#
9
# The feature manager is responsible for managing feature flags that can change characteristics of framework.
10
# Each feature will have a default value. The user can choose to override this default value if they wish.
11
###
12
class FeatureManager
13
14
include Singleton
15
16
CONFIG_KEY = 'framework/features'
17
WRAPPED_TABLES = 'wrapped_tables'
18
DATASTORE_FALLBACKS = 'datastore_fallbacks'
19
FULLY_INTERACTIVE_SHELLS = 'fully_interactive_shells'
20
MANAGER_COMMANDS = 'manager_commands'
21
METASPLOIT_PAYLOAD_WARNINGS = 'metasploit_payload_warnings'
22
DEFER_MODULE_LOADS = 'defer_module_loads'
23
DNS = 'dns'
24
HIERARCHICAL_SEARCH_TABLE = 'hierarchical_search_table'
25
SMB_SESSION_TYPE = 'smb_session_type'
26
POSTGRESQL_SESSION_TYPE = 'postgresql_session_type'
27
MYSQL_SESSION_TYPE = 'mysql_session_type'
28
MSSQL_SESSION_TYPE = 'mssql_session_type'
29
LDAP_SESSION_TYPE = 'ldap_session_type'
30
SHOW_SUCCESSFUL_LOGINS = 'show_successful_logins'
31
32
DEFAULTS = [
33
{
34
name: WRAPPED_TABLES,
35
description: 'When enabled Metasploit will wordwrap all tables to fit into the available terminal width',
36
default_value: true,
37
developer_notes: 'This functionality is enabled by default now, and the feature flag can be removed now'
38
}.freeze,
39
{
40
name: FULLY_INTERACTIVE_SHELLS,
41
description: 'When enabled you will have the option to drop into a fully interactive shell from within meterpreter',
42
default_value: false,
43
developer_notes: 'Development paused as the interaction time feels clunky, especially for slow transport layers like HTTP on Mettle. Would require changes to the transport sleep/priority logic'
44
}.freeze,
45
{
46
name: MANAGER_COMMANDS,
47
description: 'When enabled you will have access to manager commands such as _servicemanager and _historymanager',
48
default_value: false,
49
developer_notes: 'Useful for developers, likely not to ever be useful for an average user'
50
}.freeze,
51
{
52
name: DATASTORE_FALLBACKS,
53
description: 'When enabled you can consistently set username across modules, instead of setting SMBUser/FTPUser/BIND_DN/etc',
54
requires_restart: true,
55
default_value: true,
56
developer_notes: 'This functionality is enabled by default now, and the feature flag can be removed now'
57
}.freeze,
58
{
59
name: METASPLOIT_PAYLOAD_WARNINGS,
60
description: 'When enabled Metasploit will output warnings about missing Metasploit payloads, for instance if they were removed by antivirus etc',
61
requires_restart: true,
62
default_value: true,
63
developer_notes: 'Enabled in Metasploit 6.4.x'
64
}.freeze,
65
{
66
name: DEFER_MODULE_LOADS,
67
description: 'When enabled will not eagerly load all modules',
68
requires_restart: true,
69
default_value: false,
70
developer_notes: 'Needs a final round of testing. Can be enabled after 6.4.0 is released.'
71
}.freeze,
72
{
73
name: SMB_SESSION_TYPE,
74
description: 'When enabled will allow for the creation/use of smb sessions',
75
requires_restart: true,
76
default_value: true,
77
developer_notes: 'Enabled in Metasploit 6.4.x'
78
}.freeze,
79
{
80
name: POSTGRESQL_SESSION_TYPE,
81
description: 'When enabled will allow for the creation/use of PostgreSQL sessions',
82
requires_restart: true,
83
default_value: true,
84
developer_notes: 'Enabled in Metasploit 6.4.x'
85
}.freeze,
86
{
87
name: MYSQL_SESSION_TYPE,
88
description: 'When enabled will allow for the creation/use of MySQL sessions',
89
requires_restart: true,
90
default_value: true,
91
developer_notes: 'Enabled in Metasploit 6.4.x'
92
}.freeze,
93
{
94
name: MSSQL_SESSION_TYPE,
95
description: 'When enabled will allow for the creation/use of mssql sessions',
96
requires_restart: true,
97
default_value: true,
98
developer_notes: 'Enabled in Metasploit 6.4.x'
99
}.freeze,
100
{
101
name: LDAP_SESSION_TYPE,
102
description: 'When enabled will allow for the creation/use of LDAP sessions',
103
requires_restart: true,
104
default_value: false,
105
developer_notes: 'To be enabled by default after appropriate testing'
106
}.freeze,
107
{
108
name: SHOW_SUCCESSFUL_LOGINS,
109
description: 'When enabled scanners/login modules will return a table off successful logins once the module completes',
110
requires_restart: false,
111
default_value: false,
112
developer_notes: 'To be enabled after appropriate testing'
113
}.freeze,
114
{
115
name: DNS,
116
description: 'When enabled allows configuration of DNS resolution behaviour in Metasploit',
117
requires_restart: true,
118
default_value: true,
119
developer_notes: 'Enabled in Metasploit 6.4.x'
120
}.freeze,
121
{
122
name: HIERARCHICAL_SEARCH_TABLE,
123
description: 'When enabled the search table is enhanced to show details on module actions and targets',
124
requires_restart: false,
125
default_value: true,
126
developer_notes: 'Enabled in Metasploit 6.4.x'
127
}.freeze
128
].freeze
129
130
#
131
# Initializes the feature manager.
132
#
133
def initialize
134
@flag_lookup = DEFAULTS.each_with_object({}) do |feature, acc|
135
if feature[:name] == WRAPPED_TABLES
136
if feature[:default_value] == true
137
Rex::Text::Table.wrap_tables!
138
else
139
Rex::Text::Table.unwrap_tables!
140
end
141
end
142
143
key = feature[:name]
144
acc[key] = feature.dup
145
end
146
end
147
148
def all
149
@flag_lookup.values.map do |feature|
150
feature.slice(:name, :description).merge(enabled: enabled?(feature[:name]))
151
end
152
end
153
154
# @param [String] name The feature name
155
# @return [TrueClass,FalseClass] True if the flag is be enabled, false otherwise
156
def enabled?(name)
157
return false unless @flag_lookup[name]
158
159
feature = @flag_lookup[name]
160
feature.key?(:user_preference) ? feature[:user_preference] : feature[:default_value]
161
end
162
163
# @param [String] name The feature name
164
# @return [TrueClass,FalseClass] True if the flag requires a console restart to work effectively
165
def requires_restart?(name)
166
return false unless @flag_lookup[name]
167
168
@flag_lookup[name][:requires_restart] == true
169
end
170
171
def exists?(name)
172
@flag_lookup.key?(name)
173
end
174
175
def names
176
all.map { |feature| feature[:name] }
177
end
178
179
def set(name, value)
180
return false unless @flag_lookup[name]
181
182
@flag_lookup[name][:user_preference] = value
183
184
if name == WRAPPED_TABLES
185
if value
186
Rex::Text::Table.wrap_tables!
187
else
188
Rex::Text::Table.unwrap_tables!
189
end
190
end
191
end
192
193
def load_config
194
conf = Msf::Config.load
195
conf.fetch(CONFIG_KEY, {}).each do |name, value|
196
set(name, value == 'true')
197
end
198
end
199
200
def save_config
201
# Note, we intentionally omit features that have not explicitly been set by the user.
202
config = Msf::Config.load
203
old_config = config.fetch(CONFIG_KEY, {})
204
new_config = @flag_lookup.values.each_with_object(old_config) do |feature, config|
205
next unless feature.key?(:user_preference)
206
207
config.merge!(feature[:name] => feature[:user_preference].to_s)
208
end
209
210
Msf::Config.save(CONFIG_KEY => new_config)
211
end
212
end
213
end
214
215