mirror of
https://github.com/rapid7/metasploit-framework
synced 2024-10-29 18:07:27 +01:00
Update TLS certificate generation routines
Msf relies on Rex::Socket to create TLS certificates for services hosted in the framework and used by some payloads. These certs are flagged by NIDS - snort sid 1-34864 and such. Now that Rex::Socket can accept a @@cert_provider from the Msf namespace, a more robust generation routine can be used by all TLS socket services, provided down from Msf to Rex, using dependencies which Rex does not include. This work adds the faker gem into runtime dependencies, creates an Msf::Exploit::Remote::Ssl::CertProvider namespace, and provides API compatible method invocations with the Rex version, but able to generate higher entropy certs with more variables, options, etc. This should reduce the hit rate against NIDS on the wire, reducing pesky blue team interference until we slip up some other way. Also, with the ability to generate different cert types, we may want to look at extending this effort to probide a more comprehensive key oracle to Framework and consumers. Testing: None yet, internal tests pending. Travis should fail as this requires rex-socket #8.
This commit is contained in:
parent
8c2c30c230
commit
18f3815147
99
lib/msf/core/exploit/ssl.rb
Normal file
99
lib/msf/core/exploit/ssl.rb
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
module Msf
|
||||||
|
module Exploit::Remote::Ssl
|
||||||
|
require 'rex/socket/ssl'
|
||||||
|
require 'faker'
|
||||||
|
module CertProvider
|
||||||
|
|
||||||
|
def self.rand_vars(opts = {})
|
||||||
|
opts ||= {}
|
||||||
|
opts[:cc] ||= 'US'
|
||||||
|
opts[:st] ||= Faker::Address.state_abbr
|
||||||
|
opts[:loc] ||= Faker::Address.city
|
||||||
|
opts[:org] ||= Faker::Company.name
|
||||||
|
opts[:ou] ||= Faker::Hacker.send(%w{noun verb adjective}.sample.to_sym).gsub(/\W+/,'.')
|
||||||
|
opts[:cn] ||= opts[:org].downcase.gsub(/and/,'').gsub(/\W+/,'.') + '.' + Faker::Internet.domain_suffix
|
||||||
|
opts[:email] ||= "#{opts[:ou]}@#{opts[:cn]}"
|
||||||
|
opts
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.ssl_generate_subject(opts = {})
|
||||||
|
opts = self.rand_vars(opts)
|
||||||
|
subject = ""
|
||||||
|
subject << "/C=#{opts[:cc]}" if opts[:cc]
|
||||||
|
subject << "/ST=#{opts[:st]}" if opts[:st]
|
||||||
|
subject << "/O=#{opts[:org]}" if opts[:org]
|
||||||
|
subject << "/OU=#{opts[:ou]}" if opts[:ou]
|
||||||
|
subject << "/CN=#{opts[:cn]}" if opts[:cn]
|
||||||
|
subject << "/emailAddress=#{opts[:email]}" if opts[:email]
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
# Not used, for API compatibility
|
||||||
|
def self.ssl_generate_issuer(
|
||||||
|
cc: 'US',
|
||||||
|
org: Faker::Company.name,
|
||||||
|
cn: Faker::Internet.domain_name
|
||||||
|
)
|
||||||
|
"#{cc}/O=#{org}/CN=#{cn}"
|
||||||
|
end
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate a realistic-looking but obstensibly fake SSL
|
||||||
|
# certificate. Use Faker gem to mimic other self-signed
|
||||||
|
# certificates on the web to reduce the chance of sig
|
||||||
|
# identification by NIDS and the like.
|
||||||
|
#
|
||||||
|
# @return [String, String, Array]
|
||||||
|
def self.ssl_generate_certificate(opts = {}, ksize = 2048)
|
||||||
|
yr = 24*3600*365
|
||||||
|
vf = opts[:not_before] || Time.at(Time.now.to_i - rand(yr * 3) - yr)
|
||||||
|
vt = opts[:not_after] || Time.at(vf.to_i + (rand(9)+1) * yr)
|
||||||
|
cvars = opts[:cert_vars] || self.rand_vars
|
||||||
|
subject = opts[:subject] || ssl_generate_subject(cvars)
|
||||||
|
ctype = opts[:cert_type] || opts[:ca_cert].nil? ? :ca : :server
|
||||||
|
key = opts[:key] || OpenSSL::PKey::RSA.new(ksize){ }
|
||||||
|
cert = OpenSSL::X509::Certificate.new
|
||||||
|
|
||||||
|
cert.version = opts[:version] || 2
|
||||||
|
cert.serial = opts[:serial] || (rand(0xFFFFFFFF) << 32) + rand(0xFFFFFFFF)
|
||||||
|
cert.subject = OpenSSL::X509::Name.new([["C", subject]])
|
||||||
|
cert.issuer = opts[:ca_cert] || cert.subject
|
||||||
|
cert.not_before = vf
|
||||||
|
cert.not_after = vt
|
||||||
|
cert.public_key = key.public_key
|
||||||
|
|
||||||
|
bconst, kuse, ekuse = case ctype
|
||||||
|
when :ca
|
||||||
|
['CA:TRUE', 'cRLSign,keyCertSign']
|
||||||
|
when :server
|
||||||
|
['CA:FALSE', 'digitalSignature,keyEncipherment', 'serverAuth']
|
||||||
|
when :client
|
||||||
|
['CA:FALSE', 'nonRepudiation,digitalSignature,keyEncipherment', 'clientAuth,emailProtection']
|
||||||
|
when :ocsp
|
||||||
|
['CA:FALSE', 'nonRepudiation,digitalSignature', 'serverAuth,OCSPSigning']
|
||||||
|
when :tsca
|
||||||
|
['CA:TRUE,pathlen:0', 'cRLSign,keyCertSign']
|
||||||
|
end
|
||||||
|
|
||||||
|
ef = OpenSSL::X509::ExtensionFactory.new
|
||||||
|
ef.subject_certificate = cert
|
||||||
|
ef.issuer_certificate = cert
|
||||||
|
cert.extensions = [
|
||||||
|
ef.create_extension("basicConstraints", bconst, true),
|
||||||
|
ef.create_extension("subjectKeyIdentifier", "hash")
|
||||||
|
]
|
||||||
|
if kuse and !kuse.empty?
|
||||||
|
cert.extensions << ef.create_extension("keyUsage", kuse)
|
||||||
|
end
|
||||||
|
|
||||||
|
if ekuse and !ekuse.empty?
|
||||||
|
cert.extensions << ef.create_extension("extendedKeyUsage", ekuse)
|
||||||
|
end
|
||||||
|
|
||||||
|
cert.sign(key, OpenSSL::Digest::SHA256.new)
|
||||||
|
|
||||||
|
[key, cert, nil]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -84,6 +84,9 @@ class Framework
|
|||||||
# Configure the thread factory
|
# Configure the thread factory
|
||||||
Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)
|
Rex::ThreadFactory.provider = Metasploit::Framework::ThreadFactoryProvider.new(framework: self)
|
||||||
|
|
||||||
|
# Configure the SSL certificate generator
|
||||||
|
Rex::Socket::Ssl.cert_provider = Msf::Exploit::Remote::Ssl::CertProvider
|
||||||
|
|
||||||
subscriber = FrameworkEventSubscriber.new(self)
|
subscriber = FrameworkEventSubscriber.new(self)
|
||||||
events.add_exploit_subscriber(subscriber)
|
events.add_exploit_subscriber(subscriber)
|
||||||
events.add_session_subscriber(subscriber)
|
events.add_session_subscriber(subscriber)
|
||||||
|
@ -187,4 +187,6 @@ Gem::Specification.new do |spec|
|
|||||||
spec.add_runtime_dependency 'nexpose'
|
spec.add_runtime_dependency 'nexpose'
|
||||||
# Needed for NDMP sockets
|
# Needed for NDMP sockets
|
||||||
spec.add_runtime_dependency 'xdr'
|
spec.add_runtime_dependency 'xdr'
|
||||||
|
# Needed for ::Msf...CertProvider
|
||||||
|
spec.add_runtime_dependency 'faker'
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user