Skip to content

Commit 4635bb8

Browse files
committed
Implement ssl verification toggling
Add support to meterpreter that allows for the querying and toggling of SSL certificate verification on the fly. In order to verify that the socket was SSL-enabled, some rejigging had to be done of the type? method in the ssl socket class.
1 parent aaeaa05 commit 4635bb8

File tree

4 files changed

+154
-13
lines changed

4 files changed

+154
-13
lines changed

lib/rex/post/meterpreter/client.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ def swap_sock_plain_to_ssl
194194
self.sock.extend(Rex::Socket::SslTcp)
195195
self.sock.sslsock = ssl
196196
self.sock.sslctx = ctx
197+
self.sock.sslhash = Rex::Text.sha1_raw(ctx.cert.to_der)
197198

198199
tag = self.sock.get_once(-1, 30)
199200
if(not tag or tag !~ /^GET \//)
@@ -206,6 +207,7 @@ def swap_sock_ssl_to_plain
206207
self.sock.sslsock.close
207208
self.sock.sslsock = nil
208209
self.sock.sslctx = nil
210+
self.sock.sslhash = nil
209211
self.sock = self.sock.fd
210212
self.sock.extend(::Rex::Socket::Tcp)
211213
end

lib/rex/post/meterpreter/client_core.rb

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ def machine_id
258258
return Rex::Text.md5(id)
259259
end
260260

261-
def change_transport(opts={})
261+
def transport_change(opts={})
262262

263263
unless valid_transport?(opts[:transport]) && opts[:lport]
264264
return false
@@ -273,7 +273,7 @@ def change_transport(opts={})
273273

274274
transport = VALID_TRANSPORTS[opts[:transport]]
275275

276-
request = Packet.create_request('core_change_transport')
276+
request = Packet.create_request('core_transport_change')
277277

278278
scheme = opts[:transport].split('_')[1]
279279
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
@@ -322,6 +322,53 @@ def change_transport(opts={})
322322
return true
323323
end
324324

325+
#
326+
# Enable the SSL certificate has verificate
327+
#
328+
def enable_ssl_hash_verify
329+
# Not supported unless we have a socket with SSL enabled
330+
return nil unless self.client.sock.type? == 'tcp-ssl'
331+
332+
request = Packet.create_request('core_transport_setcerthash')
333+
334+
hash = Rex::Text.sha1_raw(self.client.sock.sslctx.cert.to_der)
335+
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
336+
337+
client.send_request(request)
338+
339+
return hash
340+
end
341+
342+
#
343+
# Disable the SSL certificate has verificate
344+
#
345+
def disable_ssl_hash_verify
346+
# Not supported unless we have a socket with SSL enabled
347+
return nil unless self.client.sock.type? == 'tcp-ssl'
348+
349+
request = Packet.create_request('core_transport_setcerthash')
350+
351+
# send an empty request to disable it
352+
client.send_request(request)
353+
354+
return true
355+
end
356+
357+
#
358+
# Attempt to get the SSL hash being used for verificaton (if any).
359+
#
360+
# @return 20-byte sha1 hash currently being used for verification.
361+
#
362+
def get_ssl_hash_verify
363+
# Not supported unless we have a socket with SSL enabled
364+
return nil unless self.client.sock.type? == 'tcp-ssl'
365+
366+
request = Packet.create_request('core_transport_getcerthash')
367+
response = client.send_request(request)
368+
369+
return response.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH)
370+
end
371+
325372
#
326373
# Migrates the meterpreter instance to the process specified
327374
# by pid. The connection to the server remains established.

lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb

Lines changed: 99 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ def initialize(shell)
2828
self.extensions = []
2929
self.bgjobs = []
3030
self.bgjob_id = 0
31-
3231
end
3332

3433
@@load_opts = Rex::Parser::Arguments.new(
@@ -50,7 +49,6 @@ def commands
5049
"irb" => "Drop into irb scripting mode",
5150
"use" => "Deprecated alias for 'load'",
5251
"load" => "Load one or more meterpreter extensions",
53-
"transport" => "Change the current transport mechanism",
5452
"machine_id" => "Get the MSF ID of the machine attached to the session",
5553
"quit" => "Terminate the meterpreter session",
5654
"resource" => "Run the commands stored in a file",
@@ -67,10 +65,17 @@ def commands
6765
if client.passive_service
6866
c["detach"] = "Detach the meterpreter session (for http/https)"
6967
end
70-
# The only meterp that implements this right now is native Windows and for
71-
# whatever reason it is not adding core_migrate to its list of commands.
72-
# Use a dumb platform til it gets sorted.
73-
#if client.commands.include? "core_migrate"
68+
69+
# Currently we have some windows-specific core commands`
70+
if client.platform =~ /win/
71+
# only support the SSL switching for HTTPS
72+
if client.passive_service && client.sock.type? == 'tcp-ssl'
73+
c["ssl_verify"] = "Modify the SSL certificate verification setting"
74+
end
75+
76+
c["transport"] = "Change the current transport mechanism"
77+
end
78+
7479
if client.platform =~ /win/ || client.platform =~ /linux/
7580
c["migrate"] = "Migrate the server to another process"
7681
end
@@ -329,6 +334,87 @@ def cmd_machine_id(*args)
329334
print_good("Machine ID: #{client.core.machine_id}")
330335
end
331336

337+
#
338+
# Arguments for ssl verification
339+
#
340+
@@ssl_verify_opts = Rex::Parser::Arguments.new(
341+
'-e' => [ false, 'Enable SSL certificate verification' ],
342+
'-d' => [ false, 'Disable SSL certificate verification' ],
343+
'-q' => [ false, 'Query the statis of SSL certificate verification' ],
344+
'-h' => [ false, 'Help menu' ])
345+
346+
#
347+
# Help for ssl verification
348+
#
349+
def cmd_ssl_verify_help
350+
print_line('Usage: ssl_verify [options]')
351+
print_line
352+
print_line('Change and query the current setting for SSL verification')
353+
print_line('Only one of the following options can be used at a time')
354+
print_line(@@ssl_verify_opts.usage)
355+
end
356+
357+
#
358+
# Handle the SSL verification querying and setting function.
359+
#
360+
def cmd_ssl_verify(*args)
361+
if ( args.length == 0 or args.include?("-h") )
362+
cmd_ssl_verify_help
363+
return
364+
end
365+
366+
query = false
367+
enable = false
368+
disable = false
369+
370+
settings = 0
371+
372+
@@ssl_verify_opts.parse(args) do |opt, idx, val|
373+
case opt
374+
when '-q'
375+
query = true
376+
settings += 1
377+
when '-e'
378+
enable = true
379+
settings += 1
380+
when '-d'
381+
disable = true
382+
settings += 1
383+
end
384+
end
385+
386+
# Make sure only one action has been chosen
387+
if settings != 1
388+
cmd_ssl_verify_help
389+
return
390+
end
391+
392+
if query
393+
hash = client.core.get_ssl_hash_verify
394+
if hash
395+
print_good("SSL verification is enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
396+
else
397+
print_good("SSL verification is disabled.")
398+
end
399+
400+
elsif enable
401+
hash = client.core.enable_ssl_hash_verify
402+
if hash
403+
print_good("SSL verification has been enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
404+
else
405+
print_error("Failed to enable SSL verification")
406+
end
407+
408+
else
409+
if client.core.disable_ssl_hash_verify
410+
print_good('SSL verification has been disabled')
411+
else
412+
print_error("Failed to disable SSL verification")
413+
end
414+
end
415+
416+
end
417+
332418
#
333419
# Arguments for transport switching
334420
#
@@ -347,13 +433,19 @@ def cmd_machine_id(*args)
347433
'-ex' => [ true, "Expiration timout (seconds) for http(s) transports (default: #{Rex::Post::Meterpreter::ClientCore::DEFAULT_SESSION_EXPIRATION})" ],
348434
'-h' => [ false, 'Help menu' ])
349435

436+
#
437+
# Display help for transport switching
438+
#
350439
def cmd_transport_help
351440
print_line('Usage: transport [options]')
352441
print_line
353442
print_line('Change the current Meterpreter transport mechanism')
354443
print_line(@@transport_opts.usage)
355444
end
356445

446+
#
447+
# Change the current transport setings.
448+
#
357449
def cmd_transport(*args)
358450
if ( args.length == 0 or args.include?("-h") )
359451
cmd_transport_help
@@ -409,7 +501,7 @@ def cmd_transport(*args)
409501
end
410502

411503
print_status("Swapping transport ...")
412-
if client.core.change_transport(opts)
504+
if client.core.transport_change(opts)
413505
client.shutdown_passive_dispatcher
414506
shell.stop
415507
else

lib/rex/socket/ssl_tcp.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ def allow_nonblock?
368368
attr_reader :ssl_negotiated_version # :nodoc:
369369
attr_accessor :sslsock, :sslctx # :nodoc:
370370

371+
def type?
372+
return 'tcp-ssl'
373+
end
374+
371375
protected
372376

373377
attr_writer :peer_verified # :nodoc:
@@ -377,9 +381,5 @@ def allow_nonblock?
377381
rescue LoadError
378382
end
379383

380-
def type?
381-
return 'tcp-ssl'
382-
end
383-
384384
end
385385

0 commit comments

Comments
 (0)