yawast 0.7.0.beta1 → 0.7.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +12 -0
- data/CHANGELOG.md +5 -1
- data/Gemfile +2 -2
- data/README.md +8 -1
- data/Rakefile +1 -1
- data/bin/yawast +8 -0
- data/lib/commands/cms.rb +2 -0
- data/lib/commands/dns.rb +3 -3
- data/lib/commands/head.rb +2 -0
- data/lib/commands/scan.rb +2 -0
- data/lib/commands/ssl.rb +2 -0
- data/lib/commands/utils.rb +5 -3
- data/lib/scanner/core.rb +34 -26
- data/lib/scanner/generic.rb +33 -130
- data/lib/scanner/plugins/applications/cms/generic.rb +20 -0
- data/lib/scanner/plugins/applications/generic/password_reset.rb +180 -0
- data/lib/scanner/plugins/dns/caa.rb +30 -12
- data/lib/scanner/plugins/dns/generic.rb +38 -1
- data/lib/scanner/plugins/http/directory_search.rb +14 -12
- data/lib/scanner/plugins/http/file_presence.rb +21 -13
- data/lib/scanner/plugins/http/generic.rb +95 -0
- data/lib/scanner/plugins/servers/apache.rb +23 -23
- data/lib/scanner/plugins/servers/generic.rb +25 -0
- data/lib/scanner/plugins/servers/iis.rb +6 -6
- data/lib/scanner/plugins/servers/nginx.rb +3 -1
- data/lib/scanner/plugins/servers/python.rb +3 -1
- data/lib/scanner/plugins/spider/spider.rb +7 -7
- data/lib/scanner/plugins/ssl/ssl.rb +14 -14
- data/lib/scanner/plugins/ssl/ssl_labs/analyze.rb +14 -13
- data/lib/scanner/plugins/ssl/ssl_labs/info.rb +6 -4
- data/lib/scanner/plugins/ssl/sweet32.rb +68 -63
- data/lib/scanner/ssl.rb +33 -36
- data/lib/scanner/ssl_labs.rb +373 -110
- data/lib/scanner/vuln_scan.rb +27 -0
- data/lib/shared/http.rb +31 -27
- data/lib/shared/output.rb +7 -15
- data/lib/shared/uri.rb +14 -14
- data/lib/string_ext.rb +10 -4
- data/lib/uri_ext.rb +1 -1
- data/lib/util.rb +28 -0
- data/lib/version.rb +3 -1
- data/lib/yawast.rb +12 -2
- data/test/data/ssl_labs_analyze_data_cam_hmhreservations_com.json +1933 -0
- data/test/test_scan_cms.rb +2 -2
- data/test/test_ssl_labs_analyze.rb +15 -0
- data/yawast.gemspec +8 -5
- metadata +75 -28
- data/lib/scanner/cms.rb +0 -14
- data/lib/scanner/php.rb +0 -19
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
|
3
5
|
module Yawast
|
@@ -19,14 +21,14 @@ module Yawast
|
|
19
21
|
results = Thread.new do
|
20
22
|
begin
|
21
23
|
while true
|
22
|
-
if @results.length
|
24
|
+
if @results.length.positive?
|
23
25
|
out = @results.pop(true)
|
24
26
|
Yawast::Utilities.puts_info out
|
25
27
|
Yawast::Shared::Output.log_append_value 'spider', 'get', out
|
26
28
|
end
|
27
29
|
end
|
28
|
-
rescue ThreadError
|
29
|
-
#do nothing
|
30
|
+
rescue ThreadError # rubocop:disable Lint/HandleExceptions
|
31
|
+
# do nothing
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -49,11 +51,9 @@ module Yawast
|
|
49
51
|
# check to see if we've already seen this one
|
50
52
|
unless @links.include? link.to_s
|
51
53
|
@links.push link.to_s
|
52
|
-
@results.push
|
54
|
+
@results.push link.to_s
|
53
55
|
|
54
|
-
@workers.push
|
55
|
-
get_links URI.parse(link)
|
56
|
-
}
|
56
|
+
@workers.push(Thread.new {get_links URI.parse(link)})
|
57
57
|
end
|
58
58
|
end
|
59
59
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Yawast
|
2
4
|
module Scanner
|
3
5
|
module Plugins
|
@@ -23,9 +25,7 @@ module Yawast
|
|
23
25
|
found = ''
|
24
26
|
|
25
27
|
head.each do |k, v|
|
26
|
-
if k.downcase.include? 'strict-transport-security'
|
27
|
-
found = "#{k}: #{v}"
|
28
|
-
end
|
28
|
+
found = "#{k}: #{v}" if k.downcase.include? 'strict-transport-security'
|
29
29
|
end
|
30
30
|
|
31
31
|
if found == ''
|
@@ -39,14 +39,14 @@ module Yawast
|
|
39
39
|
begin
|
40
40
|
info = Yawast::Shared::Http.get_json URI("https://hstspreload.com/api/v1/status/#{uri.host}")
|
41
41
|
|
42
|
-
chrome = info['chrome']
|
43
|
-
firefox = info['firefox']
|
44
|
-
tor = info['tor']
|
42
|
+
chrome = !info['chrome'].nil?
|
43
|
+
firefox = !info['firefox'].nil?
|
44
|
+
tor = !info['tor'].nil?
|
45
45
|
|
46
46
|
Yawast::Utilities.puts_info "HSTS Preload: Chrome - #{chrome}; Firefox - #{firefox}; Tor - #{tor}"
|
47
|
-
rescue => e
|
47
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
48
48
|
if e.message.include? 'unexpected token'
|
49
|
-
#this means we have a parsing error - don't need to include the entire message
|
49
|
+
# this means we have a parsing error - don't need to include the entire message
|
50
50
|
Yawast::Utilities.puts_error "Error getting HSTS preload information: #{e.message.truncate(30)}"
|
51
51
|
else
|
52
52
|
Yawast::Utilities.puts_error "Error getting HSTS preload information: #{e.message}"
|
@@ -67,7 +67,7 @@ module Yawast
|
|
67
67
|
if uri.scheme != 'https'
|
68
68
|
head = Yawast::Shared::Http.head(uri)
|
69
69
|
|
70
|
-
|
70
|
+
unless head['Location'].nil?
|
71
71
|
begin
|
72
72
|
location = URI.parse(head['Location'])
|
73
73
|
|
@@ -75,13 +75,13 @@ module Yawast
|
|
75
75
|
# we run this through extract_uri as it performs a few checks we need
|
76
76
|
return Yawast::Shared::Uri.extract_uri location.to_s
|
77
77
|
end
|
78
|
-
rescue
|
78
|
+
rescue # rubocop:disable Style/RescueStandardError, Lint/HandleExceptions
|
79
79
|
# we don't care if this fails
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
|
84
|
+
nil
|
85
85
|
end
|
86
86
|
|
87
87
|
def self.ssl_connection_info(uri)
|
@@ -107,13 +107,13 @@ module Yawast
|
|
107
107
|
|
108
108
|
puts
|
109
109
|
end
|
110
|
-
rescue => e
|
110
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
111
111
|
Yawast::Utilities.puts_error "SSL Information: Error Getting Details: #{e.message}"
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
def self.check_symantec_root(hash)
|
116
|
-
roots = ['08297a4047dba23680c731db6e317653ca7848e1bebd3a0b0179a707f92cf178',
|
116
|
+
roots = ['08297a4047dba23680c731db6e317653ca7848e1bebd3a0b0179a707f92cf178', # rubocop:disable Style/WordArray
|
117
117
|
'2399561127a57125de8cefea610ddf2fa078b5c8067f4e828290bfb860e84b3c',
|
118
118
|
'2834991cf677466d22baac3b0055e5b911d9a9e55f5b85ba02dc566782c30e8a',
|
119
119
|
'2930bd09a07126bdc17288d4f2ad84645ec948607907a97b5ed0b0b05879ef69',
|
@@ -171,7 +171,7 @@ module Yawast
|
|
171
171
|
'f59db3f45d57fcec94ccd516e6c8ccb20dd4363feb2c44d8656e95f50fdd8df8',
|
172
172
|
'fe863d0822fe7a2353fa484d5924e875656d3dc9fb58771f6f616f9d571bc592',
|
173
173
|
'ff856a2d251dcd88d36656f450126798cfabaade40799c722de4d2b5db36a73a']
|
174
|
-
|
174
|
+
roots.include? hash
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Yawast
|
@@ -17,27 +19,26 @@ module Yawast
|
|
17
19
|
uri = endpoint.copy
|
18
20
|
uri.path = '/api/v3/analyze'
|
19
21
|
|
20
|
-
if start_new
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
uri.query = if start_new
|
23
|
+
"host=#{target}&publish=off&startNew=on&all=done&ignoreMismatch=on"
|
24
|
+
else
|
25
|
+
"host=#{target}&publish=off&all=done&ignoreMismatch=on"
|
26
|
+
end
|
25
27
|
|
26
28
|
req = Yawast::Shared::Http.get_http(uri)
|
27
29
|
req.use_ssl = uri.scheme == 'https'
|
28
|
-
res = req.request_get(uri, {
|
30
|
+
res = req.request_get(uri, {'User-Agent' => "YAWAST/#{Yawast::VERSION}"})
|
29
31
|
body = res.read_body
|
30
32
|
code = res.code.to_i
|
31
33
|
|
32
34
|
# check for error in the response - if we don't, we'll wait forever for nothing
|
33
35
|
begin
|
34
36
|
json = JSON.parse body
|
35
|
-
rescue => e
|
37
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
36
38
|
raise StandardError, "Invalid response from SSL Labs: '#{e.message}'"
|
37
39
|
end
|
38
|
-
|
39
|
-
|
40
|
-
end
|
40
|
+
|
41
|
+
raise InvocationError, "API returned: #{json['errors']}" if json.key?('errors')
|
41
42
|
|
42
43
|
Yawast::Shared::Output.log_json 'ssl', 'ssl_labs', body
|
43
44
|
|
@@ -59,17 +60,17 @@ module Yawast
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
62
|
-
|
63
|
+
body
|
63
64
|
end
|
64
65
|
|
65
66
|
def self.extract_status(body)
|
66
67
|
begin
|
67
68
|
json = JSON.parse body
|
68
|
-
rescue => e
|
69
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
69
70
|
raise StandardError, "Invalid response from SSL Labs: '#{e.message}'"
|
70
71
|
end
|
71
72
|
|
72
|
-
|
73
|
+
json['status']
|
73
74
|
end
|
74
75
|
end
|
75
76
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module Yawast
|
@@ -12,15 +14,15 @@ module Yawast
|
|
12
14
|
|
13
15
|
body = Yawast::Shared::Http.get uri
|
14
16
|
|
15
|
-
|
17
|
+
body
|
16
18
|
end
|
17
19
|
|
18
20
|
def self.extract_msg(body)
|
19
|
-
ret =
|
21
|
+
ret = []
|
20
22
|
|
21
23
|
begin
|
22
24
|
json = JSON.parse body
|
23
|
-
rescue => e
|
25
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
24
26
|
raise Exception, "Invalid response from SSL Labs: '#{e.message}'"
|
25
27
|
end
|
26
28
|
|
@@ -30,7 +32,7 @@ module Yawast
|
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
|
35
|
+
ret
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Yawast
|
2
4
|
module Scanner
|
3
5
|
module Plugins
|
4
6
|
module SSL
|
5
7
|
class Sweet32
|
6
|
-
def self.get_tdes_session_msg_count(uri, limit =
|
8
|
+
def self.get_tdes_session_msg_count(uri, limit = 10_000)
|
7
9
|
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'limit', limit
|
8
10
|
|
9
11
|
# this method will send a number of HEAD requests to see
|
@@ -38,52 +40,52 @@ module Yawast
|
|
38
40
|
# attempt to find a version that supports 3DES
|
39
41
|
versions = OpenSSL::SSL::SSLContext::METHODS.find_all { |v| !v.to_s.include?('_client') && !v.to_s.include?('_server')}
|
40
42
|
versions.each do |version|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
begin
|
45
|
-
req.start do |http|
|
46
|
-
|
47
|
-
head = nil
|
48
|
-
begin
|
49
|
-
if use_head
|
50
|
-
head = http.head(uri.path, headers)
|
51
|
-
else
|
52
|
-
head = http.request_get(uri.path, headers)
|
53
|
-
end
|
54
|
-
|
55
|
-
cipher = http.instance_variable_get(:@socket).io.cipher[0]
|
56
|
-
rescue
|
57
|
-
# check if we are using HEAD or GET. If we've already switched to GET, no need to do this again.
|
58
|
-
if use_head
|
59
|
-
head = http.request_get(uri.path, headers)
|
43
|
+
next unless version.to_s != 'SSLv23'
|
44
|
+
req.ssl_version = version
|
60
45
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
46
|
+
begin
|
47
|
+
req.start do |http|
|
48
|
+
|
49
|
+
head = nil
|
50
|
+
begin
|
51
|
+
head = if use_head
|
52
|
+
http.head(uri.path, headers)
|
53
|
+
else
|
54
|
+
http.request_get(uri.path, headers)
|
55
|
+
end
|
56
|
+
|
57
|
+
cipher = http.instance_variable_get(:@socket).io.cipher[0]
|
58
|
+
rescue StandardError
|
59
|
+
# check if we are using HEAD or GET. If we've already switched to GET, no need to do this again.
|
60
|
+
if use_head
|
61
|
+
head = http.request_get(uri.path, headers)
|
62
|
+
|
63
|
+
# if we are here, that means that HEAD failed, but GET didn't, so we'll use GET from now on.
|
64
|
+
use_head = false
|
65
|
+
Yawast::Utilities.puts_error 'Error: HEAD request failed; using GET requests for SWEET32 check...'
|
65
66
|
end
|
67
|
+
end
|
66
68
|
|
67
|
-
|
69
|
+
# check to see if this is on Cloudflare - they break Keep-Alive limits, creating a false positive
|
70
|
+
unless head.nil?
|
68
71
|
head.each do |k, v|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
72
|
+
next unless k.casecmp('server').zero?
|
73
|
+
if v == 'cloudflare'
|
74
|
+
puts 'Cloudflare server found: SWEET32 mitigated: https://support.cloudflare.com/hc/en-us/articles/231510928'
|
73
75
|
end
|
74
76
|
end
|
75
77
|
end
|
78
|
+
end
|
76
79
|
|
77
|
-
|
80
|
+
print "Using #{version} (#{cipher})"
|
78
81
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
+
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'tls_version', version
|
83
|
+
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'tls_cipher', cipher
|
84
|
+
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'use_head_req', use_head
|
82
85
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
86
|
+
break
|
87
|
+
rescue StandardError # rubocop:disable Lint/HandleExceptions
|
88
|
+
# we don't care
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
@@ -109,12 +111,10 @@ module Yawast
|
|
109
111
|
|
110
112
|
count += 1
|
111
113
|
|
112
|
-
if i % 20
|
113
|
-
print '.'
|
114
|
-
end
|
114
|
+
print '.' if (i % 20).zero?
|
115
115
|
end
|
116
116
|
end
|
117
|
-
rescue => e
|
117
|
+
rescue StandardError => e
|
118
118
|
puts
|
119
119
|
|
120
120
|
if e.message.include?('alert handshake failure') || e.message.include?('no cipher match')
|
@@ -127,6 +127,10 @@ module Yawast
|
|
127
127
|
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'requests', count
|
128
128
|
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'exception', e.message
|
129
129
|
|
130
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
131
|
+
'tls_sweet32',
|
132
|
+
{vulnerable: false}
|
133
|
+
|
130
134
|
return
|
131
135
|
end
|
132
136
|
|
@@ -136,6 +140,10 @@ module Yawast
|
|
136
140
|
|
137
141
|
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'vulnerable', true
|
138
142
|
Yawast::Shared::Output.log_value 'ssl', 'sweet32', 'requests', count
|
143
|
+
|
144
|
+
Yawast::Shared::Output.log_hash 'vulnerabilities',
|
145
|
+
'tls_sweet32',
|
146
|
+
{vulnerable: true}
|
139
147
|
end
|
140
148
|
|
141
149
|
def self.check_tdes
|
@@ -147,31 +155,28 @@ module Yawast
|
|
147
155
|
|
148
156
|
versions.each do |version|
|
149
157
|
# ignore SSLv23, as it's an auto-negotiate, which just adds noise
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
158
|
+
next unless version.to_s != 'SSLv23' && version.to_s != 'SSLv2'
|
159
|
+
# try to get the list of ciphers supported for each version
|
160
|
+
Yawast::Shared::Output.log_append_value 'openssl', 'tls_versions', version.to_s
|
161
|
+
|
162
|
+
ciphers = nil
|
163
|
+
|
164
|
+
get_ciphers_failed = false
|
165
|
+
begin
|
166
|
+
ciphers = OpenSSL::SSL::SSLContext.new(version).ciphers
|
167
|
+
rescue StandardError => e
|
168
|
+
Yawast::Utilities.puts_error "\tError getting cipher suites for #{version}, skipping. (#{e.message})"
|
169
|
+
get_ciphers_failed = true
|
170
|
+
end
|
163
171
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
ret = true
|
168
|
-
end
|
172
|
+
if !ciphers.nil?
|
173
|
+
ciphers.each do |cipher|
|
174
|
+
ret = true if cipher[0].include?('3DES') || cipher[0].include?('CBC3')
|
169
175
|
|
170
|
-
|
171
|
-
end
|
172
|
-
elsif !get_ciphers_failed
|
173
|
-
Yawast::Utilities.puts_info "\t#{version}: No cipher suites available."
|
176
|
+
Yawast::Shared::Output.log_append_value 'openssl', 'tls_ciphers', version.to_s, cipher[0]
|
174
177
|
end
|
178
|
+
elsif !get_ciphers_failed
|
179
|
+
Yawast::Utilities.puts_info "\t#{version}: No cipher suites available."
|
175
180
|
end
|
176
181
|
end
|
177
182
|
|
data/lib/scanner/ssl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
require 'openssl-extensions/all'
|
3
5
|
require 'digest/sha1'
|
@@ -24,9 +26,7 @@ module Yawast
|
|
24
26
|
|
25
27
|
cert = ssl.peer_cert
|
26
28
|
|
27
|
-
unless cert.nil?
|
28
|
-
get_cert_info cert
|
29
|
-
end
|
29
|
+
get_cert_info cert unless cert.nil?
|
30
30
|
|
31
31
|
cert_chain = ssl.peer_cert_chain
|
32
32
|
get_cert_chain_info cert_chain, cert
|
@@ -34,14 +34,12 @@ module Yawast
|
|
34
34
|
puts "\t\tQualys SSL Labs: https://www.ssllabs.com/ssltest/analyze.html?d=#{uri.host}&hideResults=on"
|
35
35
|
puts ''
|
36
36
|
|
37
|
-
if check_ciphers
|
38
|
-
get_ciphers(uri)
|
39
|
-
end
|
37
|
+
get_ciphers(uri) if check_ciphers
|
40
38
|
|
41
39
|
ssl.sysclose
|
42
40
|
|
43
41
|
Yawast::Scanner::Plugins::SSL::Sweet32.get_tdes_session_msg_count(uri) if tdes_session_count
|
44
|
-
rescue => e
|
42
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
45
43
|
Yawast::Utilities.puts_error "SSL: Error Reading X509 Details: #{e.message}"
|
46
44
|
end
|
47
45
|
end
|
@@ -54,14 +52,14 @@ module Yawast
|
|
54
52
|
Yawast::Utilities.puts_info "\t\tSerial: #{cert.serial}"
|
55
53
|
Yawast::Utilities.puts_info "\t\tSubject: #{cert.subject}"
|
56
54
|
|
57
|
-
#check to see if cert is expired
|
55
|
+
# check to see if cert is expired
|
58
56
|
if cert.not_after > Time.now
|
59
57
|
Yawast::Utilities.puts_info "\t\tExpires: #{cert.not_after}"
|
60
58
|
else
|
61
59
|
Yawast::Utilities.puts_vuln "\t\tExpires: #{cert.not_after} (Expired)"
|
62
60
|
end
|
63
61
|
|
64
|
-
#check for SHA1 & MD5 certs
|
62
|
+
# check for SHA1 & MD5 certs
|
65
63
|
if cert.signature_algorithm.include?('md5') || cert.signature_algorithm.include?('sha1')
|
66
64
|
Yawast::Utilities.puts_vuln "\t\tSignature Algorithm: #{cert.signature_algorithm}"
|
67
65
|
else
|
@@ -76,7 +74,7 @@ module Yawast
|
|
76
74
|
# ct_precert_scts
|
77
75
|
Yawast::Scanner::Plugins::SSL::SSL.print_precert cert
|
78
76
|
|
79
|
-
#alt names
|
77
|
+
# alt names
|
80
78
|
alt_names = cert.extensions.find {|e| e.oid == 'subjectAltName'}
|
81
79
|
unless alt_names.nil?
|
82
80
|
Yawast::Utilities.puts_info "\t\tAlternate Names:"
|
@@ -90,8 +88,8 @@ module Yawast
|
|
90
88
|
|
91
89
|
def self.get_cert_chain_info(cert_chain, cert)
|
92
90
|
if cert_chain.count == 1
|
93
|
-
#HACK: This is an ugly way to guess if it's a missing intermediate, or self-signed
|
94
|
-
#It looks like a change to Ruby's OpenSSL wrapper is needed to actually fix this right.
|
91
|
+
# HACK: This is an ugly way to guess if it's a missing intermediate, or self-signed
|
92
|
+
# It looks like a change to Ruby's OpenSSL wrapper is needed to actually fix this right.
|
95
93
|
|
96
94
|
if cert.issuer == cert.subject
|
97
95
|
Yawast::Utilities.puts_vuln "\t\tCertificate Is Self-Signed"
|
@@ -123,34 +121,32 @@ module Yawast
|
|
123
121
|
|
124
122
|
dns = Resolv::DNS.new
|
125
123
|
|
126
|
-
if IPAddress.valid? uri.host
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
124
|
+
ip = if IPAddress.valid? uri.host
|
125
|
+
IPAddress.parse uri.host
|
126
|
+
else
|
127
|
+
dns.getaddresses(uri.host)[0]
|
128
|
+
end
|
131
129
|
|
132
|
-
protocols = %w
|
130
|
+
protocols = %w[ssl2 ssl3 tls1.0 tls1.1 tls1.2]
|
133
131
|
|
134
132
|
protocols.each do |protocol|
|
135
|
-
case protocol
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
133
|
+
ciphers = case protocol
|
134
|
+
when 'ssl2'
|
135
|
+
SSLShake::SSLv2::CIPHERS
|
136
|
+
when 'ssl3'
|
137
|
+
SSLShake::TLS::SSL3_CIPHERS
|
138
|
+
else
|
139
|
+
SSLShake::TLS::TLS_CIPHERS
|
140
|
+
end
|
143
141
|
|
144
142
|
puts "\tChecking for #{protocol} suites (#{ciphers.count} possible suites)"
|
145
143
|
|
146
144
|
ciphers.each_key do |cipher|
|
147
145
|
begin
|
148
|
-
res = SSLShake.hello(ip.to_s, port: uri.port, protocol: protocol, ciphers: cipher, servername: uri.host)
|
146
|
+
res = SSLShake.hello(ip.to_s, {port: uri.port, protocol: protocol, ciphers: cipher, servername: uri.host})
|
149
147
|
|
150
|
-
if res['error']
|
151
|
-
|
152
|
-
end
|
153
|
-
rescue => e
|
148
|
+
Yawast::Utilities.puts_info "\t\tCipher: #{res['cipher_suite']}" if res['error'].nil?
|
149
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
154
150
|
Yawast::Utilities.puts_error "SSL: Error Reading Cipher Details: #{e.message}"
|
155
151
|
end
|
156
152
|
end
|
@@ -161,20 +157,21 @@ module Yawast
|
|
161
157
|
|
162
158
|
def self.check_cipher_strength(cipher, ssl)
|
163
159
|
if cipher[2] < 112 || cipher[0].include?('RC4')
|
164
|
-
#less than 112 bits or RC4, flag as a vuln
|
160
|
+
# less than 112 bits or RC4, flag as a vuln
|
165
161
|
Yawast::Utilities.puts_vuln "\t\tVersion: #{ssl.ssl_version.ljust(7)}\tBits: #{cipher[2]}\tCipher: #{cipher[0]}"
|
166
162
|
elsif cipher[2] >= 128
|
167
|
-
#secure, probably safe
|
163
|
+
# secure, probably safe
|
168
164
|
Yawast::Utilities.puts_info "\t\tVersion: #{ssl.ssl_version.ljust(7)}\tBits: #{cipher[2]}\tCipher: #{cipher[0]}"
|
169
165
|
else
|
170
|
-
#weak, but not "omg!" weak.
|
166
|
+
# weak, but not "omg!" weak.
|
171
167
|
Yawast::Utilities.puts_warn "\t\tVersion: #{ssl.ssl_version.ljust(7)}\tBits: #{cipher[2]}\tCipher: #{cipher[0]}"
|
172
168
|
end
|
173
169
|
end
|
174
170
|
|
175
|
-
#private methods
|
171
|
+
# private methods
|
176
172
|
class << self
|
177
173
|
private
|
174
|
+
|
178
175
|
def get_x509_pub_key_strength(cert)
|
179
176
|
begin
|
180
177
|
if cert.public_key.class == OpenSSL::PKey::EC
|
@@ -182,7 +179,7 @@ module Yawast
|
|
182
179
|
else
|
183
180
|
cert.public_key.strength
|
184
181
|
end
|
185
|
-
rescue => e
|
182
|
+
rescue => e # rubocop:disable Style/RescueStandardError
|
186
183
|
"(Strength Unknown: #{e.message})"
|
187
184
|
end
|
188
185
|
end
|