metasploit-framework/modules/auxiliary/scanner/http/ssl.rb

137 lines
3.8 KiB
Ruby
Raw Normal View History

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
2011-11-26 21:32:43 +00:00
class Metasploit4 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::WmapScanSSL
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
include Rex::Socket::Comm
def initialize
super(
'Name' => 'HTTP SSL Certificate Information',
'Description' => 'Parse the server SSL certificate to obtain the common name and signature algorithm',
2011-11-26 21:32:43 +00:00
'Author' =>
[
'et', #original module
'Chris John Riley', #additions
2012-12-14 09:38:22 +00:00
'Veit Hailperin <hailperv@gmail.com>', # checks for public key size, valid time
2011-11-26 21:32:43 +00:00
],
'License' => MSF_LICENSE
)
register_options([
Opt::RPORT(443)
], self.class)
end
# Fingerprint a single host
def run_host(ip)
begin
2011-11-26 21:32:43 +00:00
connect(true, {"SSL" => true}) #Force SSL
cert = OpenSSL::X509::Certificate.new(sock.peer_cert)
disconnect
if cert
2011-11-26 21:32:43 +00:00
print_status("#{ip}:#{rport} Subject: #{cert.subject}")
print_status("#{ip}:#{rport} Issuer: #{cert.issuer}")
print_status("#{ip}:#{rport} Signature Alg: #{cert.signature_algorithm}")
2013-01-08 15:39:27 +00:00
public_key_size = cert.public_key.n.num_bytes * 8
2012-12-13 13:58:33 +00:00
print_status("#{ip}:#{rport} Public Key Size: #{public_key_size} bits")
2012-12-13 13:40:43 +00:00
print_status("#{ip}:#{rport} Not Valid Before: #{cert.not_before}")
print_status("#{ip}:#{rport} Not Valid After: #{cert.not_after}")
2011-11-26 21:32:43 +00:00
# Checks for common properties of self signed certificates
caissuer = (/CA Issuers - URI:(.*?),/i).match(cert.extensions.to_s)
if caissuer.to_s.empty?
2012-10-08 20:23:26 +00:00
print_good("#{ip}:#{rport} Certificate contains no CA Issuers extension... possible self signed certificate")
2011-11-26 21:32:43 +00:00
else
print_status("#{ip}:#{rport} " +caissuer.to_s[0..-2])
end
if cert.issuer.to_s == cert.subject.to_s
2012-10-08 20:23:26 +00:00
print_good("#{ip}:#{rport} Certificate Subject and Issuer match... possible self signed certificate")
2011-11-26 21:32:43 +00:00
end
alg = cert.signature_algorithm
if alg.downcase.include? "md5"
print_status("#{ip}:#{rport} WARNING: Signature algorithm using MD5 (#{alg})")
end
vhostn = nil
cert.subject.to_a.each do |n|
vhostn = n[1] if n[0] == 'CN'
end
2012-12-13 13:42:16 +00:00
if public_key_size == 1024
2012-12-13 13:40:43 +00:00
print_status("#{ip}:#{rport} WARNING: Public Key only 1024 bits")
elsif public_key_size < 1024
print_status("#{ip}:#{rport} WARNING: Weak Public Key: #{public_key_size} bits")
end
if cert.not_after < Time.now
print_status("#{ip}:#{rport} WARNING: Certificate not valid anymore")
end
if cert.not_before > Time.now
print_status("#{ip}:#{rport} WARNING: Certificate not valid yet")
end
if vhostn
print_status("#{ip}:#{rport} has common name #{vhostn}")
# Store the virtual hostname for HTTP
report_note(
:host => ip,
:port => rport,
:proto => 'tcp',
:type => 'http.vhost',
:data => {:name => vhostn}
)
# Store the SSL certificate itself
report_note(
:host => ip,
:proto => 'tcp',
:port => rport,
:type => 'ssl.certificate',
:data => {
:cn => vhostn,
:subject => cert.subject.to_a,
2012-12-13 13:40:43 +00:00
:algorithm => alg,
:valid_from => cert.not_before,
:valid_after => cert.not_after,
:key_size => public_key_size
}
)
# Update the server hostname if necessary
if vhostn !~ /localhost|snakeoil/i
report_host(
:host => ip,
:name => vhostn
)
end
end
else
print_status("#{ip}:#{rport}] No certificate subject or common name found")
end
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
rescue ::Timeout::Error, ::Errno::EPIPE
end
end
2012-03-18 05:07:27 +00:00
end