Land #4239 - Support SSL intermediate certs

bug/bundler_fix
sinn3r 2014-11-21 02:09:40 -06:00
commit f2add929d7
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
1 changed files with 92 additions and 40 deletions

View File

@ -99,6 +99,93 @@ module Rex::Socket::SslTcpServer
end
end
#
# Parse a certificate in unified PEM format that contains a private key and
# one or more certificates. The first certificate is the primary, while any
# additional certificates are treated as intermediary certificates. This emulates
# the behavior of web servers like nginx.
#
# @param [String] ssl_cert
# @return [String, String, Array]
def self.ssl_parse_pem(ssl_cert)
cert = nil
key = nil
chain = nil
certs = []
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
if pem =~ /PRIVATE KEY/
key = OpenSSL::PKey::RSA.new(pem)
elsif pem =~ /CERTIFICATE/
certs << OpenSSL::X509::Certificate.new(pem)
end
end
cert = certs.shift
if certs.length > 0
chain = certs
end
[key, cert, chain]
end
#
# Shim for the ssl_parse_pem module method
#
def ssl_parse_pem(ssl_cert)
Rex::Socket::SslTcpServer.ssl_parse_pem(ssl_cert)
end
#
# Generate a realistic-looking but obstensibly fake SSL
# certificate.
#
# @return [String, String, Array]
def self.ssl_generate_certificate
key = OpenSSL::PKey::RSA.new(1024){ }
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand(0xFFFFFFFF)
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)
[key, cert, nil]
end
#
# Shim for the ssl_generate_certificate module method
#
def ssl_generate_certificate
Rex::Socket::SslTcpServer.ssl_generate_certificate
end
#
# Create a new ssl context. If +ssl_cert+ is not given, generates a new
@ -107,54 +194,19 @@ module Rex::Socket::SslTcpServer
# @param [Rex::Socket::Parameters] params
# @return [::OpenSSL::SSL::SSLContext]
def makessl(params)
ssl_cert = params.ssl_cert
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)
if params.ssl_cert
key, cert, chain = ssl_parse_pem(params.ssl_cert)
else
key, cert, chain = ssl_generate_certificate
end
ctx = OpenSSL::SSL::SSLContext.new()
ctx.key = key
ctx.cert = cert
ctx.extra_chain_cert = chain
ctx.options = 0
# Older versions of OpenSSL do not export the OP_NO_COMPRESSION symbol
if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
# enable/disable the SSL/TLS-level compression