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.
This commit is contained in:
OJ
2015-04-06 12:46:23 +10:00
parent aaeaa0503d
commit 4635bb83c3
4 changed files with 154 additions and 13 deletions
+2
View File
@@ -194,6 +194,7 @@ class Client
self.sock.extend(Rex::Socket::SslTcp)
self.sock.sslsock = ssl
self.sock.sslctx = ctx
self.sock.sslhash = Rex::Text.sha1_raw(ctx.cert.to_der)
tag = self.sock.get_once(-1, 30)
if(not tag or tag !~ /^GET \//)
@@ -206,6 +207,7 @@ class Client
self.sock.sslsock.close
self.sock.sslsock = nil
self.sock.sslctx = nil
self.sock.sslhash = nil
self.sock = self.sock.fd
self.sock.extend(::Rex::Socket::Tcp)
end
+49 -2
View File
@@ -258,7 +258,7 @@ class ClientCore < Extension
return Rex::Text.md5(id)
end
def change_transport(opts={})
def transport_change(opts={})
unless valid_transport?(opts[:transport]) && opts[:lport]
return false
@@ -273,7 +273,7 @@ class ClientCore < Extension
transport = VALID_TRANSPORTS[opts[:transport]]
request = Packet.create_request('core_change_transport')
request = Packet.create_request('core_transport_change')
scheme = opts[:transport].split('_')[1]
url = "#{scheme}://#{opts[:lhost]}:#{opts[:lport]}"
@@ -322,6 +322,53 @@ class ClientCore < Extension
return true
end
#
# Enable the SSL certificate has verificate
#
def enable_ssl_hash_verify
# Not supported unless we have a socket with SSL enabled
return nil unless self.client.sock.type? == 'tcp-ssl'
request = Packet.create_request('core_transport_setcerthash')
hash = Rex::Text.sha1_raw(self.client.sock.sslctx.cert.to_der)
request.add_tlv(TLV_TYPE_TRANS_CERT_HASH, hash)
client.send_request(request)
return hash
end
#
# Disable the SSL certificate has verificate
#
def disable_ssl_hash_verify
# Not supported unless we have a socket with SSL enabled
return nil unless self.client.sock.type? == 'tcp-ssl'
request = Packet.create_request('core_transport_setcerthash')
# send an empty request to disable it
client.send_request(request)
return true
end
#
# Attempt to get the SSL hash being used for verificaton (if any).
#
# @return 20-byte sha1 hash currently being used for verification.
#
def get_ssl_hash_verify
# Not supported unless we have a socket with SSL enabled
return nil unless self.client.sock.type? == 'tcp-ssl'
request = Packet.create_request('core_transport_getcerthash')
response = client.send_request(request)
return response.get_tlv_value(TLV_TYPE_TRANS_CERT_HASH)
end
#
# Migrates the meterpreter instance to the process specified
# by pid. The connection to the server remains established.
@@ -28,7 +28,6 @@ class Console::CommandDispatcher::Core
self.extensions = []
self.bgjobs = []
self.bgjob_id = 0
end
@@load_opts = Rex::Parser::Arguments.new(
@@ -50,7 +49,6 @@ class Console::CommandDispatcher::Core
"irb" => "Drop into irb scripting mode",
"use" => "Deprecated alias for 'load'",
"load" => "Load one or more meterpreter extensions",
"transport" => "Change the current transport mechanism",
"machine_id" => "Get the MSF ID of the machine attached to the session",
"quit" => "Terminate the meterpreter session",
"resource" => "Run the commands stored in a file",
@@ -67,10 +65,17 @@ class Console::CommandDispatcher::Core
if client.passive_service
c["detach"] = "Detach the meterpreter session (for http/https)"
end
# The only meterp that implements this right now is native Windows and for
# whatever reason it is not adding core_migrate to its list of commands.
# Use a dumb platform til it gets sorted.
#if client.commands.include? "core_migrate"
# Currently we have some windows-specific core commands`
if client.platform =~ /win/
# only support the SSL switching for HTTPS
if client.passive_service && client.sock.type? == 'tcp-ssl'
c["ssl_verify"] = "Modify the SSL certificate verification setting"
end
c["transport"] = "Change the current transport mechanism"
end
if client.platform =~ /win/ || client.platform =~ /linux/
c["migrate"] = "Migrate the server to another process"
end
@@ -329,6 +334,87 @@ class Console::CommandDispatcher::Core
print_good("Machine ID: #{client.core.machine_id}")
end
#
# Arguments for ssl verification
#
@@ssl_verify_opts = Rex::Parser::Arguments.new(
'-e' => [ false, 'Enable SSL certificate verification' ],
'-d' => [ false, 'Disable SSL certificate verification' ],
'-q' => [ false, 'Query the statis of SSL certificate verification' ],
'-h' => [ false, 'Help menu' ])
#
# Help for ssl verification
#
def cmd_ssl_verify_help
print_line('Usage: ssl_verify [options]')
print_line
print_line('Change and query the current setting for SSL verification')
print_line('Only one of the following options can be used at a time')
print_line(@@ssl_verify_opts.usage)
end
#
# Handle the SSL verification querying and setting function.
#
def cmd_ssl_verify(*args)
if ( args.length == 0 or args.include?("-h") )
cmd_ssl_verify_help
return
end
query = false
enable = false
disable = false
settings = 0
@@ssl_verify_opts.parse(args) do |opt, idx, val|
case opt
when '-q'
query = true
settings += 1
when '-e'
enable = true
settings += 1
when '-d'
disable = true
settings += 1
end
end
# Make sure only one action has been chosen
if settings != 1
cmd_ssl_verify_help
return
end
if query
hash = client.core.get_ssl_hash_verify
if hash
print_good("SSL verification is enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
else
print_good("SSL verification is disabled.")
end
elsif enable
hash = client.core.enable_ssl_hash_verify
if hash
print_good("SSL verification has been enabled. SHA1 Hash: #{hash.unpack("H*")[0]}")
else
print_error("Failed to enable SSL verification")
end
else
if client.core.disable_ssl_hash_verify
print_good('SSL verification has been disabled')
else
print_error("Failed to disable SSL verification")
end
end
end
#
# Arguments for transport switching
#
@@ -347,6 +433,9 @@ class Console::CommandDispatcher::Core
'-ex' => [ true, "Expiration timout (seconds) for http(s) transports (default: #{Rex::Post::Meterpreter::ClientCore::DEFAULT_SESSION_EXPIRATION})" ],
'-h' => [ false, 'Help menu' ])
#
# Display help for transport switching
#
def cmd_transport_help
print_line('Usage: transport [options]')
print_line
@@ -354,6 +443,9 @@ class Console::CommandDispatcher::Core
print_line(@@transport_opts.usage)
end
#
# Change the current transport setings.
#
def cmd_transport(*args)
if ( args.length == 0 or args.include?("-h") )
cmd_transport_help
@@ -409,7 +501,7 @@ class Console::CommandDispatcher::Core
end
print_status("Swapping transport ...")
if client.core.change_transport(opts)
if client.core.transport_change(opts)
client.shutdown_passive_dispatcher
shell.stop
else
+4 -4
View File
@@ -368,6 +368,10 @@ begin
attr_reader :ssl_negotiated_version # :nodoc:
attr_accessor :sslsock, :sslctx # :nodoc:
def type?
return 'tcp-ssl'
end
protected
attr_writer :peer_verified # :nodoc:
@@ -377,9 +381,5 @@ protected
rescue LoadError
end
def type?
return 'tcp-ssl'
end
end