CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/http/cert.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::Tcp
8
include Msf::Auxiliary::WmapScanSSL
9
include Msf::Auxiliary::Scanner
10
include Msf::Auxiliary::Report
11
12
def initialize
13
super(
14
'Name' => 'HTTP SSL Certificate Checker',
15
'Author' => 'nebulus',
16
'License' => MSF_LICENSE,
17
'Description' => %q{
18
This module will check the certificate of the specified web servers
19
to ensure the subject and issuer match the supplied pattern and that the certificate
20
is not expired.
21
}
22
)
23
24
register_options(
25
[
26
Opt::RPORT(443),
27
OptRegexp.new('ISSUER', [ true, "Show a warning if the Issuer doesn't match this regex", '.*']),
28
OptBool.new('SHOWALL', [ false, "Show all certificates (issuer,time) regardless of match", false]),
29
])
30
end
31
32
# Fingerprint a single host
33
def run_host(ip)
34
35
connect(true, {"SSL" => true}) #Force SSL
36
cert = OpenSSL::X509::Certificate.new(sock.peer_cert)
37
disconnect
38
39
if(not cert)
40
print_status("#{ip} No certificate subject or CN found")
41
return
42
end
43
sub = cert.subject.to_a
44
45
before = Time.parse("#{cert.not_before}")
46
after = Time.parse("#{cert.not_after}")
47
48
now = Time.now
49
a = now <=> before
50
b = now <=> after
51
52
vhostn = 'EMPTY'
53
sub.each do |n|
54
if n[0] == 'CN'
55
vhostn = n[1]
56
end
57
end
58
59
if cert.issuer.to_s !~ /#{datastore['ISSUER'].source}/n
60
print_good("#{ip} - '#{vhostn}' : #{cert.issuer} (BAD ISSUER)" )
61
elsif datastore['SHOWALL']
62
# show verbose as status
63
print_status("#{ip} - '#{vhostn}' : #{cert.issuer}")
64
end
65
66
if ( a < 1 or b > 0 )
67
print_good("#{ip} - '#{vhostn}' : '" + before.to_s + "' - '" + after.to_s + "' (EXPIRED)'")
68
elsif
69
# show verbose as status
70
print_status("#{ip} - '#{vhostn}' : '" + before.to_s + "' - '" + after.to_s + "'")
71
end
72
73
report_note(
74
:host => ip,
75
:port => rport,
76
:proto => 'tcp',
77
:type => 'http.vhost',
78
:data => {:name => vhostn}
79
) if vhostn
80
81
# Store the SSL certificate itself
82
report_note(
83
:host => ip,
84
:proto => 'tcp',
85
:port => rport,
86
:type => 'ssl.certificate',
87
:data => {
88
:cn => vhostn,
89
:subject => cert.subject.to_a,
90
:algorithm => cert.signature_algorithm
91
92
}
93
) if vhostn
94
95
# Update the server hostname if necessary
96
if vhostn !~ /localhost|snakeoil/i
97
report_host(
98
:host => ip,
99
:name => vhostn
100
)
101
end
102
103
104
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
105
rescue ::Timeout::Error, ::Errno::EPIPE
106
rescue ::OpenSSL::SSL::SSLError => e
107
return if(e.to_s.match(/^SSL_connect /) ) # strange errors / exception if SSL connection aborted
108
rescue ::Exception => e
109
return if(e.to_s =~ /execution expired/)
110
print_error("Error: '#{ip}' '#{e.class}' '#{e}' '#{e.backtrace}'")
111
end
112
end
113
114