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/module/external.rb
Views: 11784
1
2
module Msf::Module::External
3
include Msf::Auxiliary::Report
4
include Msf::Module::Auth
5
6
def execute_module(path, method: :run, args: datastore, fail_on_exit: true)
7
mod = Msf::Modules::External.new(path, framework: framework)
8
success = mod.exec(method: method, args: args) do |m|
9
begin
10
case m.method
11
when :message
12
log_output(m)
13
when :report
14
process_report(m, mod)
15
when :reply
16
return m.params['return']
17
end
18
rescue Interrupt => e
19
raise e
20
rescue Exception => e
21
elog('Unable to execute External Module', error: e)
22
fail_with Msf::Module::Failure::Unknown, e.message
23
end
24
end
25
26
fail_with Msf::Module::Failure::Unknown, "Module exited abnormally" if fail_on_exit && !success
27
end
28
29
def log_output(m)
30
message = m.params['message']
31
32
case m.params['level']
33
when 'error'
34
print_error message
35
when 'warning'
36
print_warning message
37
when 'good'
38
print_good message
39
when 'info'
40
print_status message
41
when 'debug'
42
vprint_status message
43
else
44
print_status message
45
end
46
end
47
48
def process_report(m, mod)
49
data = m.params['data']
50
51
case m.params['type']
52
when 'host'
53
# Required
54
host = {host: data['host']}
55
56
# Optional
57
host[:state] = data['state'] if data['state'] # TODO: validate -- one of the Msf::HostState constants (unknown, alive, dead)
58
host[:os_name] = data['os_name'] if data['os_name']
59
host[:os_flavor] = data['os_flavor'] if data['os_flavor']
60
host[:os_sp] = data['os_sp'] if data['os_sp']
61
host[:os_lang] = data['os_lang'] if data['os_lang']
62
host[:arch] = data['arch'] if data['arch'] # TODO: validate -- one of the ARCH_* constants
63
host[:mac] = data['mac'] if data['mac']
64
host[:scope] = data['scope'] if data['scope']
65
host[:virtual_host] = data['virtual_host'] if data['virtual_host']
66
67
report_host(host)
68
when 'service'
69
# Required
70
service = {host: data['host'], port: data['port'], proto: data['proto']}
71
72
# Optional
73
service[:name] = data['name'] || mod.meta['service_name'] if data['name'] || mod.meta['service_name']
74
75
report_service(service)
76
when 'vuln'
77
# Required
78
vuln = {host: data['host'], name: data['name']}
79
80
# Optional
81
vuln[:info] = data['info'] if data['info']
82
vuln[:refs] = data['refs'] if data['refs']
83
vuln[:port] = data['port'] if data['port']
84
vuln[:proto] = data['port'] if data['port']
85
86
# Metasploit magic
87
vuln[:refs] = self.references
88
89
report_vuln(vuln)
90
when 'correct_password'
91
# Required
92
cred = {user: data['username'], private: data['password']}
93
94
# Optional
95
cred[:proof] = data['proof'] if data['proof']
96
cred[:service_data] =
97
{
98
origin_type: :service,
99
protocol: data['protocol'] || 'tcp',
100
service_name: data['service_name'] || mod.meta['service_name'],
101
address: data['host'] || datastore['rhost'] || rhost,
102
port: data['port'] || datastore['rport'] || rport
103
}
104
105
cred[:private_type] = :password
106
107
# Optional
108
if data.has_key?('domain')
109
cred[:service_data][:realm_value] = data['domain']
110
cred[:service_data][:realm_key] = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
111
end
112
113
store_valid_credential(**cred)
114
when 'wrong_password'
115
# Required
116
cred = {public: data['username'], private: data['password']}
117
118
# Optional
119
cred.merge!({
120
address: data['host'] || datastore['rhost'] || rhost,
121
port: data['port'] || datastore['rport'] || rport,
122
protocol: data['protocol'] || 'tcp',
123
status: Metasploit::Model::Login::Status::INCORRECT
124
})
125
126
invalidate_login(**cred)
127
128
when 'credential_login'
129
handle_credential_login(data, mod)
130
else
131
print_warning "Skipping unrecognized report type #{m.params['type']}"
132
end
133
end
134
end
135
136
#
137
# Handles login report that does not necessarily need to include a password
138
#
139
def handle_credential_login(data, mod)
140
# Required
141
service_data = {
142
address: data['address'],
143
port: data['port'],
144
protocol: data['protocol'],
145
service_name: data['service_name'],
146
module_fullname: self.fullname,
147
workspace_id: myworkspace_id
148
}
149
# Optional
150
credential_data = {
151
origin_type: :service,
152
username: data['username']
153
}.merge(service_data)
154
155
if data.has_key?(:password)
156
credential_data[:private_data] = data['password']
157
credential_data[:private_type] = :password
158
end
159
160
if data.has_key?('domain')
161
credential_data[:realm_value] = data['domain']
162
credential_data[:realm_key] = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
163
end
164
165
login_data = {
166
core: create_credential(credential_data),
167
last_attempted_at: DateTime.now,
168
status: Metasploit::Model::Login::Status::SUCCESSFUL,
169
}.merge(service_data)
170
create_credential_login(login_data)
171
end
172
173