add ability to use arbitrary certs with SSL server sockets.

git-svn-id: file:///home/svn/framework3/trunk@12675 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
James Lee 2011-05-20 23:12:35 +00:00
parent 9003622af3
commit d1e2f274f9
7 changed files with 84 additions and 46 deletions

View File

@ -31,7 +31,8 @@ module Exploit::Remote::HttpServer
OptBool.new('HTTP::header_folding', [false, 'Enable folding of HTTP headers', 'false']),
OptBool.new('HTTP::junk_headers', [false, 'Enable insertion of random junk HTTP headers', 'false']),
OptEnum.new('HTTP::compression', [false, 'Enable compression of HTTP responses via content encoding', 'none', ['none','gzip','deflate']]),
], Exploit::Remote::HttpServer)
], Exploit::Remote::HttpServer
)
@service_path = nil
end
@ -73,8 +74,8 @@ module Exploit::Remote::HttpServer
# Uri => The URI to handle and the associated procedure to call.
#
def start_service(opts = {})
check_dependencies
check_dependencies
comm = datastore['ListenerComm']
if (comm.to_s == "local")
@ -100,7 +101,8 @@ module Exploit::Remote::HttpServer
'Msf' => framework,
'MsfExploit' => self,
},
opts['Comm']
opts['Comm'],
datastore['SSLCert']
)
self.service.server_name = 'Apache'
@ -422,7 +424,7 @@ module Exploit::Remote::HttpServer
#
def send_not_found(cli)
resp_404 = create_response(404, 'Not Found')
resp_404.body = %Q{
resp_404.body = %Q{\
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>

View File

@ -286,6 +286,7 @@ module Exploit::Remote::TcpServer
[
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']]),
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' ]),
OptPort.new('SRVPORT', [ true, "The local port to listen on.", 8080 ]),
@ -372,6 +373,7 @@ module Exploit::Remote::TcpServer
'LocalHost' => srvhost,
'LocalPort' => srvport,
'SSL' => ssl,
'SSLCert' => ssl_cert,
'Comm' => comm,
'Context' =>
{
@ -450,6 +452,12 @@ module Exploit::Remote::TcpServer
datastore['SSL']
end
#
# Returns the SSLCert option
#
def ssl_cert
datastore['SSLCert']
end
#
# Re-generates the payload, substituting the current RHOST and RPORT with

View File

@ -163,7 +163,7 @@ module ReverseTcp
begin
handle_connection(client)
rescue ::Exception
elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}")
elog("Exception raised from handle_connection: #{$!.class}: #{$!}\n\n#{$@.join("\n")}")
end
end
}

View File

@ -38,7 +38,7 @@ class Handler::Proc < Handler
rescue Errno::EPIPE
elog("Proc::on_request: Client closed connection prematurely", LogSource)
rescue
elog("Proc::on_request: #{$!}\n\n#{$@.join("\n")}", LogSource)
elog("Proc::on_request: #{$!.class}: #{$!}\n\n#{$@.join("\n")}", LogSource)
if self.server and self.server.context
exploit = self.server.context['MsfExploit']
if exploit

View File

@ -99,15 +99,17 @@ class Server
# Initializes an HTTP server as listening on the provided port and
# hostname.
#
def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil)
def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil)
self.listen_host = listen_host
self.listen_port = port
self.ssl = ssl
self.context = context
self.comm = comm
self.ssl_cert = ssl_cert
self.listener = nil
self.resources = {}
self.server_name = DefaultServer
self.ssl = ssl
self.comm = comm
end
#
@ -134,6 +136,7 @@ class Server
'LocalPort' => self.listen_port,
'Context' => self.context,
'SSL' => self.ssl,
'SSLCert' => self.ssl_cert,
'Comm' => self.comm
)
@ -256,7 +259,7 @@ class Server
cli.send_response(resp)
end
attr_accessor :listen_port, :listen_host, :server_name, :context, :ssl, :comm
attr_accessor :listen_port, :listen_host, :server_name, :context, :ssl, :comm, :ssl_cert
attr_accessor :listener, :resources
protected

View File

@ -63,6 +63,10 @@ class Rex::Socket::Parameters
#
# Specify SSL2, SSL3, or TLS1 (SSL3 is default)
#
# SSLCert
#
# A file containing an SSL certificate (for server sockets)
#
# Proxies
#
# List of proxies to use.
@ -139,6 +143,14 @@ class Rex::Socket::Parameters
self.ssl_version = hash['SSLVersion']
end
if (hash['SSLCert'] and ::File.file?(hash['SSLCert']))
begin
self.ssl_cert = ::File.read(hash['SSLCert'])
rescue ::Exception => e
elog("Failed to read cert: #{e.class}: #{e}", LogSource)
end
end
if hash['Proxies']
self.proxies = hash['Proxies'].split('-').map{|a| a.strip}.map{|a| a.split(':').map{|b| b.strip}}
end
@ -325,6 +337,10 @@ class Rex::Socket::Parameters
#
attr_accessor :ssl_version
#
# The SSL certificate, in pem format, stored as a string. See +SslTcpServer#make_ssl+
#
attr_accessor :ssl_cert
#
# Whether we should use IPv6
#
attr_accessor :v6

View File

@ -47,7 +47,7 @@ module Rex::Socket::SslTcpServer
def initsock(params = nil)
raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
self.sslctx = makessl()
self.sslctx = makessl(params.ssl_cert)
super
end
@ -99,43 +99,52 @@ module Rex::Socket::SslTcpServer
end
def makessl
key = OpenSSL::PKey::RSA.new(1024){ }
#
# Create a new ssl context. If +ssl_cert+ is not given, generates a new
# key and a leaf certificate with random values.
#
def makessl(ssl_cert=nil)
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand(0xFFFFFFFF)
# name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
subject = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", Rex::Text.rand_hostname],
])
issuer = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", Rex::Text.rand_hostname],
])
if ssl_cert
cert = OpenSSL::X509::Certificate.new(ssl_cert)
key = OpenSSL::PKey::RSA.new(ssl_cert)
else
key = OpenSSL::PKey::RSA.new(1024){ }
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand(0xFFFFFFFF)
# name = OpenSSL::X509::Name.new([["C","JP"],["O","TEST"],["CN","localhost"]])
subject = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", Rex::Text.rand_hostname],
])
issuer = OpenSSL::X509::Name.new([
["C","US"],
['ST', Rex::Text.rand_state()],
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
["CN", Rex::Text.rand_hostname],
])
cert.subject = subject
cert.issuer = issuer
cert.not_before = Time.now - (3600 * 365)
cert.not_after = Time.now + (3600 * 365)
cert.public_key = key.public_key
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
cert.extensions = [
ef.create_extension("basicConstraints","CA:FALSE"),
ef.create_extension("subjectKeyIdentifier","hash"),
ef.create_extension("extendedKeyUsage","serverAuth"),
ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
]
ef.issuer_certificate = cert
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
cert.sign(key, OpenSSL::Digest::SHA1.new)
cert.subject = subject
cert.issuer = issuer
cert.not_before = Time.now - (3600 * 365)
cert.not_after = Time.now + (3600 * 365)
cert.public_key = key.public_key
ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
cert.extensions = [
ef.create_extension("basicConstraints","CA:FALSE"),
ef.create_extension("subjectKeyIdentifier","hash"),
ef.create_extension("extendedKeyUsage","serverAuth"),
ef.create_extension("keyUsage","keyEncipherment,dataEncipherment,digitalSignature")
]
ef.issuer_certificate = cert
cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
cert.sign(key, OpenSSL::Digest::SHA1.new)
end
ctx = OpenSSL::SSL::SSLContext.new()
ctx.key = key