Land #4024, auto-negotiate SSL versions

Thanks @hmoore-r7!
bug/bundler_fix
Tod Beardsley 2014-10-15 16:04:38 -05:00
commit d5a0b81680
No known key found for this signature in database
GPG Key ID: 1EFFB682ADB9F193
5 changed files with 53 additions and 13 deletions

View File

@ -44,7 +44,7 @@ module Auxiliary::HttpCrawler
OptString.new('HTTPAdditionalHeaders', [false, "A list of additional headers to send (separated by \\x01)"]), OptString.new('HTTPAdditionalHeaders', [false, "A list of additional headers to send (separated by \\x01)"]),
OptString.new('HTTPCookie', [false, "A HTTP cookie header to send with each request"]), OptString.new('HTTPCookie', [false, "A HTTP cookie header to send with each request"]),
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]), OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL23', 'SSL3', 'TLS1']]), OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL23', 'SSL3', 'TLS1']]),
], self.class ], self.class
) )

View File

@ -50,7 +50,7 @@ module Exploit::Remote::HttpClient
OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']), OptString.new('PASSWORD', [false, 'The HTTP password to specify for authentication', '']),
OptBool.new('DigestAuthIIS', [false, 'Conform to IIS, should work for most servers. Only set to false for non-IIS servers', true]), OptBool.new('DigestAuthIIS', [false, 'Conform to IIS, should work for most servers. Only set to false for non-IIS servers', true]),
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]), OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]), OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]),
OptBool.new('FingerprintCheck', [ false, 'Conduct a pre-exploit fingerprint verification', true]), OptBool.new('FingerprintCheck', [ false, 'Conduct a pre-exploit fingerprint verification', true]),
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION']) OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION'])
], self.class ], self.class

View File

@ -62,7 +62,7 @@ module Exploit::Remote::Tcp
register_advanced_options( register_advanced_options(
[ [
OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]), OptBool.new('SSL', [ false, 'Negotiate SSL for outgoing connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]), OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]),
OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]), OptEnum.new('SSLVerifyMode', [ false, 'SSL verification method', 'PEER', %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}]),
OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']), OptString.new('SSLCipher', [ false, 'String for SSL cipher - "DHE-RSA-AES256-SHA" or "ADH"']),
Opt::Proxies, Opt::Proxies,
@ -290,7 +290,7 @@ module Exploit::Remote::TcpServer
register_options( register_options(
[ [
OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]), OptBool.new('SSL', [ false, 'Negotiate SSL for incoming connections', false]),
OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'SSL3', ['SSL2', 'SSL3', 'TLS1']]), OptEnum.new('SSLVersion', [ false, 'Specify the version of SSL that should be used', 'Auto', ['Auto', 'SSL2', 'SSL3', 'TLS1']]),
OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']), OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']),
OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]), OptAddress.new('SRVHOST', [ true, "The local host to listen on. This must be an address on the local machine or 0.0.0.0", '0.0.0.0' ]),
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]), OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),

View File

@ -56,7 +56,7 @@ class Rex::Socket::Parameters
# @option hash [Bool] 'Bool' Create a bare socket # @option hash [Bool] 'Bool' Create a bare socket
# @option hash [Bool] 'Server' Whether or not this should be a server # @option hash [Bool] 'Server' Whether or not this should be a server
# @option hash [Bool] 'SSL' Whether or not SSL should be used # @option hash [Bool] 'SSL' Whether or not SSL should be used
# @option hash [String] 'SSLVersion' Specify SSL2, SSL3, or TLS1 (SSL3 is # @option hash [String] 'SSLVersion' Specify Auto, SSL2, SSL3, or TLS1 (Auto is
# default) # default)
# @option hash [String] 'SSLCert' A file containing an SSL certificate (for # @option hash [String] 'SSLCert' A file containing an SSL certificate (for
# server sockets) # server sockets)
@ -117,7 +117,7 @@ class Rex::Socket::Parameters
self.ssl = false self.ssl = false
end end
supported_ssl_versions = ['SSL2', 'SSL23', 'TLS1', 'SSL3', :SSLv2, :SSLv3, :SSLv23, :TLSv1] supported_ssl_versions = ['Auto', 'SSL2', 'SSL23', 'TLS1', 'SSL3', :Auto, :SSLv2, :SSLv3, :SSLv23, :TLSv1]
if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion']) if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion'])
self.ssl_version = hash['SSLVersion'] self.ssl_version = hash['SSLVersion']
end end
@ -324,7 +324,7 @@ class Rex::Socket::Parameters
# @return [Bool] # @return [Bool]
attr_accessor :ssl attr_accessor :ssl
# What version of SSL to use (SSL2, SSL3, SSL23, TLS1) # What version of SSL to use (Auto, SSL2, SSL3, SSL23, TLS1)
# @return [String,Symbol] # @return [String,Symbol]
attr_accessor :ssl_version attr_accessor :ssl_version

View File

@ -56,18 +56,55 @@ begin
def initsock(params = nil) def initsock(params = nil)
super super
version = :SSLv3 # The autonegotiation preference for SSL/TLS versions
if(params) versions = [:TLSv1, :SSLv3, :SSLv23, :SSLv2]
# Limit this to a specific SSL/TLS version if specified
if params
case params.ssl_version case params.ssl_version
when 'SSL2', :SSLv2 when 'SSL2', :SSLv2
version = :SSLv2 versions = [:SSLv2]
when 'SSL23', :SSLv23 when 'SSL23', :SSLv23
version = :SSLv23 versions = [:SSLv23]
when 'SSL3', :SSLv3
versions = [:SSLv3]
when 'TLS1', :TLSv1 when 'TLS1', :TLSv1
version = :TLSv1 versions = [:TLSv1]
else
# Leave the version list as-is (Auto)
end end
end end
# Limit our versions to those supported by the linked OpenSSL library
versions = versions.select {|v| OpenSSL::SSL::SSLContext::METHODS.include? v }
# Raise an error if no selected versions are supported
if versions.length == 0
raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
end
last_error = nil
# Iterate through SSL/TLS versions until we successfully negotiate
versions.each do |version|
begin
# Try intializing the socket with this SSL/TLS version
# This will throw an exception if it fails
initsock_with_ssl_version(params, version)
# Success! Record what method was used and return
self.ssl_negotiated_version = version
return
rescue OpenSSL::SSL::SSLError => e
last_error = e
end
end
# No SSL/TLS versions succeeded, raise the last error
raise last_error
end
def initsock_with_ssl_version(params, version)
# Build the SSL connection # Build the SSL connection
self.sslctx = OpenSSL::SSL::SSLContext.new(version) self.sslctx = OpenSSL::SSL::SSLContext.new(version)
@ -84,7 +121,9 @@ begin
# Could also do this as graceful faildown in case a passed verify_mode is not supported # Could also do this as graceful faildown in case a passed verify_mode is not supported
self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
end end
self.sslctx.options = OpenSSL::SSL::OP_ALL self.sslctx.options = OpenSSL::SSL::OP_ALL
if params.ssl_cipher if params.ssl_cipher
self.sslctx.ciphers = params.ssl_cipher self.sslctx.ciphers = params.ssl_cipher
end end
@ -101,7 +140,6 @@ begin
# XXX - enabling this causes infinite recursion, so disable for now # XXX - enabling this causes infinite recursion, so disable for now
# self.sslsock.sync_close = true # self.sslsock.sync_close = true
# Force a negotiation timeout # Force a negotiation timeout
begin begin
Timeout.timeout(params.timeout) do Timeout.timeout(params.timeout) do
@ -327,11 +365,13 @@ begin
end end
attr_reader :peer_verified # :nodoc: attr_reader :peer_verified # :nodoc:
attr_reader :ssl_negotiated_version # :nodoc:
attr_accessor :sslsock, :sslctx # :nodoc: attr_accessor :sslsock, :sslctx # :nodoc:
protected protected
attr_writer :peer_verified # :nodoc: attr_writer :peer_verified # :nodoc:
attr_writer :ssl_negotiated_version # :nodoc:
rescue LoadError rescue LoadError