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/plugins/besecure.rb
Views: 11705
1
#
2
# This plugin provides integration with beSECURE. Written by Noam Rathaus.
3
#
4
# Distributed under MIT license:
5
# http://www.opensource.org/licenses/mit-license.php
6
#
7
# Version 10.5.17
8
9
require 'base64'
10
require 'zlib'
11
require 'tempfile'
12
require 'pathname'
13
14
module Msf
15
class Plugin::BeSECURE < Msf::Plugin
16
class BeSECURECommandDispatcher
17
include Msf::Ui::Console::CommandDispatcher
18
19
def name
20
'beSECURE'
21
end
22
23
def commands
24
{
25
'besecure_help' => 'Displays help',
26
'besecure_version' => 'Display the version of the beSECURE server',
27
'besecure_apikey' => 'Set the beSECURE API Key',
28
'besecure_hostname' => 'Set the beSECURE Hostname',
29
'besecure_debug' => 'Enable/Disable debugging',
30
'besecure_ssl_verify' => 'Enable/Disable SSL verification',
31
32
'besecure_report_list' => 'Display list of reports',
33
34
'besecure_report_download' => 'Save a report to disk',
35
'besecure_report_import' => 'Import report specified by ID into framework'
36
}
37
end
38
39
def cmd_besecure_help
40
print_status('besecure_help Display this help')
41
print_status('besecure_debug Enable/Disable debugging')
42
print_status('besecure_version Display the version of the beSECURE server')
43
print_status('besecure_apikey Set the beSECURE API Key')
44
print_status('besecure_ssl_verify Set whether to verify or not SSL')
45
print_status('besecure_hostname Set the beSECURE Hostname')
46
47
print_status
48
print_status('REPORTS')
49
print_status('=======')
50
print_status('besecure_report_list Lists reports')
51
print_status('besecure_report_download Downloads an beSECURE report specified by ID')
52
print_status('besecure_report_import Import report specified by ID into framework')
53
end
54
55
# Verify the database is connected and usable
56
def database?
57
if !(framework.db && framework.db.usable)
58
return false
59
else
60
return true
61
end
62
end
63
64
# Verify correct number of arguments and verify -h was not given. Return
65
# true if correct number of arguments and help was not requested.
66
def args?(args, min = 1, max = nil)
67
if !max then max = min end
68
if ((args.length < min) || (args.length > max) || (args[0] == '-h'))
69
return false
70
end
71
72
return true
73
end
74
75
#--------------------------
76
# Basic Functions
77
#--------------------------
78
def cmd_besecure_hostname(*args)
79
if args?(args)
80
@hostname = args[0]
81
print_good(@hostname)
82
else
83
print_status('Usage:')
84
print_status('besecure_hostname string')
85
end
86
end
87
88
def cmd_besecure_apikey(*args)
89
if args?(args)
90
@apikey = args[0]
91
print_good(@apikey)
92
else
93
print_status('Usage:')
94
print_status('besecure_apikey string')
95
end
96
end
97
98
def cmd_besecure_ssl_verify(*args)
99
if args?(args)
100
@ssl_verify = args[0]
101
if (@ssl_verify != 'yes') && (@ssl_verify != 'no')
102
@ssl_verify = 'yes'
103
end
104
print_good(@ssl_verify)
105
else
106
print_status('Usage:')
107
print_status("besecure_ssl_verify 'yes'/'no' (default is yes)")
108
end
109
end
110
111
def cmd_besecure_debug(*args)
112
if args?(args)
113
@debug = args[0].to_i
114
print_good(@debug)
115
else
116
print_status('Usage:')
117
print_status('besecure_debug integer')
118
end
119
end
120
121
def cmd_besecure_version
122
req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
123
req.set_form_data({ 'apikey' => @apikey, 'primary' => 'interface' })
124
125
if @debug
126
print_status(req.body)
127
end
128
129
http = Net::HTTP.new(@hostname, 443)
130
if @debug
131
http.set_debug_output($stdout) # Logger.new("foo.log") works too
132
end
133
134
http.use_ssl = true
135
if @ssl_verify == 'no'
136
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
137
end
138
139
res = http.start { |h| h.request(req) }
140
141
unless res
142
print_error("#{@hostname} - Connection timed out")
143
return ''
144
end
145
146
body = ''
147
begin
148
body = JSON.parse(res.body)
149
rescue JSON::ParserError
150
print_error("#{@hostname} - Unable to parse the response")
151
return ''
152
end
153
154
if body['error']
155
print_error("#{@hostname} - An error occurred:")
156
print_error(body)
157
return ''
158
end
159
160
print_good(body['version'])
161
end
162
163
#--------------------------
164
# Report Functions
165
#--------------------------
166
167
def cmd_besecure_report_list(*_args)
168
tbl = Rex::Text::Table.new(
169
'Columns' => ['ID', 'Name', 'Hosts']
170
)
171
172
if @hostname.empty?
173
print_error('Missing host value')
174
return ''
175
end
176
177
req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
178
req.set_form_data({ 'apikey' => @apikey, 'primary' => 'admin', 'secondary' => 'networks', 'action' => 'returnnetworks', 'search_limit' => 10000 })
179
180
if @debug
181
print_status(req.body)
182
end
183
184
http = Net::HTTP.new(@hostname, 443)
185
if @debug
186
http.set_debug_output($stdout) # Logger.new("foo.log") works too
187
end
188
189
http.use_ssl = true
190
if @ssl_verify == 'no'
191
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
192
end
193
194
res = http.start { |h| h.request(req) }
195
196
unless res
197
print_error("#{@hostname} - Connection timed out")
198
return ''
199
end
200
201
body = ''
202
begin
203
body = JSON.parse(res.body)
204
rescue JSON::ParserError
205
print_error("#{@hostname} - Unable to parse the response")
206
return ''
207
end
208
209
if body['error']
210
print_error("#{@hostname} - An error occurred:")
211
print_error(body)
212
return ''
213
end
214
215
data = body['data']
216
data.each do |item|
217
tbl << [ item['ID'], item['Name'], item['PrettyRange']]
218
end
219
220
# print_good(body)
221
222
print_good('beSECURE list of reports')
223
print_line
224
print_line tbl.to_s
225
print_line
226
end
227
228
def cmd_besecure_report_download(*args)
229
if args?(args, 4)
230
req = Net::HTTP::Post.new('/json.cgi', { 'Host' => @hostname })
231
format_file = args[1]
232
req.set_form_data({ 'apikey' => @apikey, 'primary' => 'vulnerabilities', 'secondary' => 'report', 'action' => 'getreport', 'network' => args[0], 'format' => format_file })
233
234
http = Net::HTTP.new(@hostname, 443)
235
if @debug
236
http.set_debug_output($stdout) # Logger.new("foo.log") works too
237
end
238
239
http.use_ssl = true
240
if @ssl_verify == 'no'
241
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
242
end
243
244
res = http.start { |h| h.request(req) }
245
246
unless res
247
print_error("#{@hostname} - Connection timed out")
248
return ''
249
end
250
251
body = ''
252
begin
253
body = JSON.parse(res.body)
254
rescue JSON::ParserError
255
print_error("#{@hostname} - Unable to parse the response")
256
return ''
257
end
258
259
if body['error']
260
print_error("#{@hostname} - An error occurred:")
261
print_error(body)
262
return ''
263
end
264
265
decompressed = ''
266
if format_file != 'json'
267
compressed_base64 = body['compresseddata']
268
compressed = Base64.decode64(compressed_base64)
269
decompressed = Zlib::Inflate.inflate(compressed)
270
else
271
decompressed = body
272
end
273
274
if @debug
275
print_status(decompressed)
276
end
277
278
::FileUtils.mkdir_p(args[2])
279
name = ::File.join(args[2], args[3])
280
print_status("Saving report to #{name}")
281
output = ::File.new(name, 'w')
282
output.puts(decompressed)
283
output.close
284
285
###
286
# Return the report
287
return decompressed
288
else
289
print_status('Usage: besecure_report_download <network_id> <format_name> <path> <report_name>')
290
end
291
292
return ''
293
end
294
295
def cmd_besecure_report_import(*args)
296
if args?(args, 2)
297
if !database?
298
print_error('Database not ready')
299
return ''
300
end
301
302
tempfile = Tempfile.new('results')
303
304
res = cmd_besecure_report_download(args[0], 'nbe', File.dirname(tempfile) + '/', File.basename(tempfile))
305
if res.empty?
306
print_error('An empty report has been received')
307
return ''
308
end
309
310
print_status('Importing report to database.')
311
framework.db.import_file({ filename: tempfile })
312
313
tempfile.unlink
314
else
315
print_status('Usage: besecure_report_import <network_id> <format_name>')
316
print_status('Only the NBE and XML formats are supported for importing.')
317
end
318
end
319
end
320
321
#------------------------------
322
# Plugin initialization
323
#------------------------------
324
325
def initialize(framework, opts)
326
super
327
add_console_dispatcher(BeSECURECommandDispatcher)
328
print_status('Welcome to beSECURE integration by Noam Rathaus.')
329
print_status
330
print_status('beSECURE integration requires a database connection. Once the ')
331
print_status('database is ready, connect to the beSECURE server using besecure_connect.')
332
print_status('For additional commands use besecure_help.')
333
print_status
334
335
@debug = nil
336
end
337
338
def cleanup
339
remove_console_dispatcher('beSECURE')
340
end
341
342
def name
343
'beSECURE'
344
end
345
346
def desc
347
'Integrates with the beSECURE - open source vulnerability management'
348
end
349
end
350
end
351
352