yawast 0.6.0.beta3 → 0.6.0.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -12
- data/CHANGELOG.md +2 -0
- data/README.md +25 -524
- data/bin/yawast +0 -11
- data/lib/scanner/plugins/ssl/ssl_labs/analyze.rb +34 -0
- data/lib/scanner/plugins/ssl/ssl_labs/info.rb +33 -0
- data/lib/scanner/ssl_labs.rb +185 -163
- data/lib/shared/http.rb +5 -5
- data/lib/version.rb +1 -1
- data/test/data/ssl_labs_analyze_data.json +6458 -0
- data/test/data/ssl_labs_analyze_start.json +11 -0
- data/test/data/ssl_labs_info.json +10 -0
- data/test/test_internalssl.rb +2 -2
- data/test/test_shared_http.rb +1 -1
- data/test/test_ssl_labs_analyze.rb +48 -0
- data/test/test_ssl_labs_info.rb +20 -0
- data/yawast.gemspec +0 -1
- metadata +14 -18
- data/lib/commands/cert.rb +0 -10
- data/lib/scanner/cert.rb +0 -99
data/lib/scanner/ssl_labs.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'ssllabs'
|
2
1
|
require 'date'
|
3
2
|
require 'openssl'
|
4
3
|
require 'digest/sha1'
|
4
|
+
require 'json'
|
5
5
|
|
6
6
|
module Yawast
|
7
7
|
module Scanner
|
@@ -11,25 +11,24 @@ module Yawast
|
|
11
11
|
puts 'Beginning SSL Labs scan (this could take a minute or two)'
|
12
12
|
|
13
13
|
begin
|
14
|
-
|
14
|
+
endpoint = Yawast::Commands::Utils.extract_uri(['https://api.ssllabs.com'])
|
15
15
|
|
16
|
-
|
16
|
+
info_body = Yawast::Scanner::Plugins::SSL::SSLLabs::Info.call_info endpoint
|
17
17
|
|
18
|
-
|
18
|
+
Yawast::Scanner::Plugins::SSL::SSLLabs::Info.extract_msg(info_body).each do |msg|
|
19
19
|
puts "[SSL Labs] #{msg}"
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
Yawast::Scanner::Plugins::SSL::SSLLabs::Analyze.scan endpoint, uri.host, true
|
23
23
|
|
24
24
|
status = ''
|
25
|
-
host = nil
|
26
25
|
until status == 'READY' || status == 'ERROR' || status == 'DNS'
|
27
26
|
# poll for updates every 5 seconds
|
28
27
|
# don't want to poll faster, to avoid excess load / errors
|
29
28
|
sleep(5)
|
30
29
|
|
31
|
-
|
32
|
-
status =
|
30
|
+
data_body = Yawast::Scanner::Plugins::SSL::SSLLabs::Analyze.scan endpoint, uri.host, false
|
31
|
+
status = Yawast::Scanner::Plugins::SSL::SSLLabs::Analyze.extract_status data_body
|
33
32
|
|
34
33
|
print '.'
|
35
34
|
end
|
@@ -38,20 +37,29 @@ module Yawast
|
|
38
37
|
puts "\tSSL Labs: https://www.ssllabs.com/ssltest/analyze.html?d=#{uri.host}&hideResults=on"
|
39
38
|
puts
|
40
39
|
|
41
|
-
|
42
|
-
|
40
|
+
process_results uri, JSON.parse(data_body), tdes_session_count
|
41
|
+
rescue => e
|
42
|
+
puts
|
43
|
+
Yawast::Utilities.puts_error "SSL Labs Error: #{e.message}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.process_results(uri, body, tdes_session_count)
|
48
|
+
begin
|
49
|
+
body['endpoints'].each do |ep|
|
50
|
+
Yawast::Utilities.puts_info "IP: #{ep['ipAddress']} - Grade: #{ep['grade']}"
|
43
51
|
puts
|
44
52
|
|
45
53
|
begin
|
46
|
-
if ep
|
47
|
-
get_cert_info
|
48
|
-
get_config_info
|
49
|
-
get_proto_info
|
54
|
+
if ep['statusMessage'] == 'Ready'
|
55
|
+
get_cert_info ep, body
|
56
|
+
get_config_info ep
|
57
|
+
get_proto_info ep
|
50
58
|
else
|
51
|
-
Yawast::Utilities.puts_error "Error getting information for IP: #{ep
|
59
|
+
Yawast::Utilities.puts_error "Error getting information for IP: #{ep['ipAddress']}: #{ep['statusMessage']}"
|
52
60
|
end
|
53
61
|
rescue => e
|
54
|
-
Yawast::Utilities.puts_error "Error getting information for IP: #{ep
|
62
|
+
Yawast::Utilities.puts_error "Error getting information for IP: #{ep['ipAddress']}: #{e.message}"
|
55
63
|
end
|
56
64
|
|
57
65
|
Yawast::Scanner::Plugins::SSL::Sweet32.get_tdes_session_msg_count(uri) if tdes_session_count
|
@@ -64,77 +72,77 @@ module Yawast
|
|
64
72
|
end
|
65
73
|
end
|
66
74
|
|
67
|
-
def self.get_cert_info (ep)
|
75
|
+
def self.get_cert_info (ep, body)
|
68
76
|
# get the ChainCert info for the server cert - needed for extra details
|
69
77
|
cert = nil
|
70
78
|
ossl_cert = nil
|
71
|
-
|
72
|
-
if c
|
79
|
+
body['certs'].each do |c|
|
80
|
+
if c['id'] == ep['details']['certChains'][0]['certIds'][0]
|
73
81
|
cert = c
|
74
|
-
ossl_cert = OpenSSL::X509::Certificate.new cert
|
82
|
+
ossl_cert = OpenSSL::X509::Certificate.new cert['raw']
|
75
83
|
end
|
76
84
|
end
|
77
85
|
|
78
86
|
puts "\tCertificate Information:"
|
79
|
-
unless
|
87
|
+
unless cert['issues'] == 0
|
80
88
|
Yawast::Utilities.puts_vuln "\t\tCertificate Has Issues - Not Valid"
|
81
89
|
|
82
|
-
if
|
90
|
+
if cert['issues'] & 1 != 0
|
83
91
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: no chain of trust"
|
84
92
|
end
|
85
93
|
|
86
|
-
if
|
94
|
+
if cert['issues'] & (1<<1) != 0
|
87
95
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: certificate not yet valid"
|
88
96
|
end
|
89
97
|
|
90
|
-
if
|
98
|
+
if cert['issues'] & (1<<2) != 0
|
91
99
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: certificate expired"
|
92
100
|
end
|
93
101
|
|
94
|
-
if
|
102
|
+
if cert['issues'] & (1<<3) != 0
|
95
103
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: hostname mismatch"
|
96
104
|
end
|
97
105
|
|
98
|
-
if
|
106
|
+
if cert['issues'] & (1<<4) != 0
|
99
107
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: revoked"
|
100
108
|
end
|
101
109
|
|
102
|
-
if
|
110
|
+
if cert['issues'] & (1<<5) != 0
|
103
111
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: bad common name"
|
104
112
|
end
|
105
113
|
|
106
|
-
if
|
114
|
+
if cert['issues'] & (1<<6) != 0
|
107
115
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: self-signed"
|
108
116
|
end
|
109
117
|
|
110
|
-
if
|
118
|
+
if cert['issues'] & (1<<7) != 0
|
111
119
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: blacklisted"
|
112
120
|
end
|
113
121
|
|
114
|
-
if
|
122
|
+
if cert['issues'] & (1<<8) != 0
|
115
123
|
Yawast::Utilities.puts_vuln "\t\tCertificate Issue: insecure signature"
|
116
124
|
end
|
117
125
|
end
|
118
126
|
|
119
|
-
Yawast::Utilities.puts_info "\t\tSubject: #{
|
120
|
-
Yawast::Utilities.puts_info "\t\tCommon Names: #{
|
127
|
+
Yawast::Utilities.puts_info "\t\tSubject: #{cert['subject']}"
|
128
|
+
Yawast::Utilities.puts_info "\t\tCommon Names: #{cert['commonNames'].join(' ')}"
|
121
129
|
|
122
130
|
Yawast::Utilities.puts_info "\t\tAlternative names:"
|
123
|
-
|
131
|
+
cert['altNames'].each do |name|
|
124
132
|
Yawast::Utilities.puts_info "\t\t\t#{name}"
|
125
133
|
end
|
126
134
|
|
127
135
|
# here we divide the time by 1000 to strip the fractions of a second off.
|
128
|
-
Yawast::Utilities.puts_info "\t\tNot Before: #{Time.at(
|
129
|
-
Yawast::Utilities.puts_info "\t\tNot After: #{Time.at(
|
136
|
+
Yawast::Utilities.puts_info "\t\tNot Before: #{Time.at(cert['notBefore'] / 1000).utc.to_datetime}"
|
137
|
+
Yawast::Utilities.puts_info "\t\tNot After: #{Time.at(cert['notAfter'] / 1000).utc.to_datetime}"
|
130
138
|
|
131
|
-
if cert
|
132
|
-
Yawast::Utilities.puts_info "\t\tKey: #{cert
|
139
|
+
if cert['keyAlg'] == 'EC'
|
140
|
+
Yawast::Utilities.puts_info "\t\tKey: #{cert['keyAlg']} #{cert['keySize']} (RSA equivalent: #{cert['keyStrength']})"
|
133
141
|
else
|
134
|
-
if cert
|
135
|
-
Yawast::Utilities.puts_vuln "\t\tKey: #{cert
|
142
|
+
if cert['keySize'] < 2048
|
143
|
+
Yawast::Utilities.puts_vuln "\t\tKey: #{cert['keyAlg']} #{cert['keySize']}"
|
136
144
|
else
|
137
|
-
Yawast::Utilities.puts_info "\t\tKey: #{cert
|
145
|
+
Yawast::Utilities.puts_info "\t\tKey: #{cert['keyAlg']} #{cert['keySize']}"
|
138
146
|
end
|
139
147
|
end
|
140
148
|
|
@@ -144,61 +152,52 @@ module Yawast
|
|
144
152
|
|
145
153
|
Yawast::Utilities.puts_info "\t\tSerial: #{ossl_cert.serial}"
|
146
154
|
|
147
|
-
Yawast::Utilities.puts_info "\t\tIssuer: #{
|
155
|
+
Yawast::Utilities.puts_info "\t\tIssuer: #{cert['issuerSubject']}"
|
148
156
|
|
149
|
-
if
|
150
|
-
Yawast::Utilities.puts_vuln "\t\tSignature algorithm: #{
|
157
|
+
if cert['sigAlg'].include?('SHA1') || cert['sigAlg'].include?('MD5')
|
158
|
+
Yawast::Utilities.puts_vuln "\t\tSignature algorithm: #{cert['sigAlg']}"
|
151
159
|
else
|
152
|
-
Yawast::Utilities.puts_info "\t\tSignature algorithm: #{
|
160
|
+
Yawast::Utilities.puts_info "\t\tSignature algorithm: #{cert['sigAlg']}"
|
153
161
|
end
|
154
162
|
|
155
163
|
#todo - figure out what the options for this value are
|
156
|
-
if
|
164
|
+
if cert['validationType'] == 'E'
|
157
165
|
Yawast::Utilities.puts_info "\t\tExtended Validation: Yes"
|
158
|
-
elsif
|
166
|
+
elsif cert['validationType'] == 'D'
|
159
167
|
Yawast::Utilities.puts_info "\t\tExtended Validation: No (Domain Control)"
|
160
168
|
else
|
161
169
|
Yawast::Utilities.puts_info "\t\tExtended Validation: No"
|
162
170
|
end
|
163
171
|
|
164
|
-
if
|
172
|
+
if cert['sct']
|
165
173
|
# check the first bit, SCT in cert
|
166
|
-
if ep
|
174
|
+
if ep['details']['hasSct'] & 1 != 0
|
167
175
|
Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in certificate"
|
168
176
|
end
|
169
177
|
|
170
178
|
# check second bit, SCT in stapled OSCP response
|
171
|
-
if ep
|
179
|
+
if ep['details']['hasSct'] & (1<<1) != 0
|
172
180
|
Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in the stapled OCSP response"
|
173
181
|
end
|
174
182
|
|
175
183
|
# check third bit, SCT in the TLS extension
|
176
|
-
if ep
|
184
|
+
if ep['details']['hasSct'] & (1<<2) != 0
|
177
185
|
Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in the TLS extension (ServerHello)"
|
178
186
|
end
|
179
187
|
else
|
180
188
|
Yawast::Utilities.puts_info "\t\tCertificate Transparency: No"
|
181
189
|
end
|
182
190
|
|
183
|
-
|
184
|
-
when 0
|
185
|
-
Yawast::Utilities.puts_info "\t\tOCSP Must Staple: No"
|
186
|
-
when 1
|
187
|
-
Yawast::Utilities.puts_warn "\t\tOCSP Must Staple: Supported, but OCSP response is not stapled"
|
188
|
-
when 2
|
189
|
-
Yawast::Utilities.puts_info "\t\tOCSP Must Staple: OCSP response is stapled"
|
190
|
-
else
|
191
|
-
Yawast::Utilities.puts_error "\t\tOCSP Must Staple: Unknown Response #{ep.details.cert.must_staple}"
|
192
|
-
end
|
191
|
+
Yawast::Utilities.puts_info "\t\tOCSP Must Staple: #{cert['mustStaple']}"
|
193
192
|
|
194
|
-
if
|
193
|
+
if cert['revocationInfo'] & 1 != 0
|
195
194
|
Yawast::Utilities.puts_info "\t\tRevocation information: CRL information available"
|
196
195
|
end
|
197
|
-
if
|
196
|
+
if cert['revocationInfo'] & (1<<1) != 0
|
198
197
|
Yawast::Utilities.puts_info "\t\tRevocation information: OCSP information available"
|
199
198
|
end
|
200
199
|
|
201
|
-
case
|
200
|
+
case cert['revocationStatus']
|
202
201
|
when 0
|
203
202
|
Yawast::Utilities.puts_info "\t\tRevocation status: not checked"
|
204
203
|
when 1
|
@@ -212,7 +211,7 @@ module Yawast
|
|
212
211
|
when 5
|
213
212
|
Yawast::Utilities.puts_error "\t\tRevocation status: SSL Labs internal error"
|
214
213
|
else
|
215
|
-
Yawast::Utilities.puts_error "\t\tRevocation status: Unknown response #{
|
214
|
+
Yawast::Utilities.puts_error "\t\tRevocation status: Unknown response #{cert['revocationStatus']}"
|
216
215
|
end
|
217
216
|
|
218
217
|
Yawast::Utilities.puts_info "\t\tExtensions:"
|
@@ -223,6 +222,27 @@ module Yawast
|
|
223
222
|
puts "\t\t\thttps://censys.io/certificates?q=#{hash}"
|
224
223
|
puts "\t\t\thttps://crt.sh/?q=#{hash}"
|
225
224
|
|
225
|
+
puts
|
226
|
+
Yawast::Utilities.puts_info "\t\tCertificate Chains:"
|
227
|
+
ep['details']['certChains'].each do |chain|
|
228
|
+
path_count = 0
|
229
|
+
|
230
|
+
chain['trustPaths'].each do |path|
|
231
|
+
path_count += 1
|
232
|
+
puts "\t\t Path #{path_count}:"
|
233
|
+
|
234
|
+
path['certIds'].each do |path_cert|
|
235
|
+
body['certs'].each do |c|
|
236
|
+
if c['id'] == path_cert
|
237
|
+
Yawast::Utilities.puts_info "\t\t\t#{c['subject']}"
|
238
|
+
Yawast::Utilities.puts_info "\t\t\t Signature: #{c['sigAlg']} Key: #{c['keyAlg']}-#{c['keySize']}"
|
239
|
+
Yawast::Utilities.puts_info "\t\t\t https://crt.sh/?q=#{c['sha1Hash']}"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
226
246
|
puts
|
227
247
|
end
|
228
248
|
|
@@ -230,93 +250,81 @@ module Yawast
|
|
230
250
|
puts "\tConfiguration Information:"
|
231
251
|
|
232
252
|
puts "\t\tProtocol Support:"
|
233
|
-
|
234
|
-
|
235
|
-
|
253
|
+
protos = Hash.new
|
254
|
+
ep['details']['protocols'].each do |proto|
|
255
|
+
if proto['name'] == 'SSL'
|
256
|
+
Yawast::Utilities.puts_vuln "\t\t\t#{proto['name']} #{proto['version']}"
|
236
257
|
else
|
237
|
-
Yawast::Utilities.puts_info "\t\t\t#{proto
|
258
|
+
Yawast::Utilities.puts_info "\t\t\t#{proto['name']} #{proto['version']}"
|
238
259
|
end
|
260
|
+
|
261
|
+
protos[proto['id']] = "#{proto['name']} #{proto['version']}"
|
262
|
+
end
|
263
|
+
puts
|
264
|
+
|
265
|
+
puts "\t\tNamed Group Support:"
|
266
|
+
ep['details']['namedGroups']['list'].each do |group|
|
267
|
+
Yawast::Utilities.puts_info "\t\t\t#{group['name']} #{group['bits']}"
|
239
268
|
end
|
240
269
|
puts
|
241
270
|
|
242
271
|
puts "\t\tCipher Suite Support:"
|
243
|
-
if ep
|
244
|
-
ep
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
272
|
+
if ep['details']['suites'] != nil
|
273
|
+
ep['details']['suites'].each do |proto_suites|
|
274
|
+
Yawast::Utilities.puts_info "\t\t\t#{protos[proto_suites['protocol']]}"
|
275
|
+
|
276
|
+
proto_suites['list'].each do |suite|
|
277
|
+
ke = get_key_exchange suite
|
278
|
+
|
279
|
+
strength = suite['cipherStrength']
|
280
|
+
if suite['name'].include? '3DES'
|
281
|
+
# in this case, the effective strength is only 112 bits,
|
282
|
+
# which is what we want to report. So override SSL Labs
|
283
|
+
strength = 112
|
255
284
|
end
|
256
|
-
end
|
257
285
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
end
|
264
|
-
|
265
|
-
if ke != nil
|
266
|
-
suite_info = "#{suite.name.ljust(50)} - #{strength}-bits - #{ke}"
|
267
|
-
else
|
268
|
-
suite_info = "#{suite.name.ljust(50)} - #{strength}-bits"
|
269
|
-
end
|
286
|
+
if ke != nil
|
287
|
+
suite_info = "#{suite['name'].ljust(50)} - #{strength}-bits - #{ke}"
|
288
|
+
else
|
289
|
+
suite_info = "#{suite['name'].ljust(50)} - #{strength}-bits"
|
290
|
+
end
|
270
291
|
|
271
|
-
|
272
|
-
|
273
|
-
|
292
|
+
if cipher_suite_secure? suite
|
293
|
+
if strength >= 128
|
294
|
+
Yawast::Utilities.puts_info "\t\t\t #{suite_info}"
|
295
|
+
else
|
296
|
+
Yawast::Utilities.puts_warn "\t\t\t #{suite_info}"
|
297
|
+
end
|
274
298
|
else
|
275
|
-
Yawast::Utilities.
|
299
|
+
Yawast::Utilities.puts_vuln "\t\t\t #{suite_info}"
|
276
300
|
end
|
277
|
-
else
|
278
|
-
Yawast::Utilities.puts_vuln "\t\t\t#{suite_info}"
|
279
301
|
end
|
280
302
|
end
|
281
303
|
else
|
282
|
-
Yawast::Utilities.puts_error "\t\t\
|
304
|
+
Yawast::Utilities.puts_error "\t\t\t Information Not Available"
|
283
305
|
end
|
284
306
|
|
285
307
|
puts
|
286
308
|
|
287
309
|
puts "\t\tHandshake Simulation:"
|
288
|
-
if ep
|
289
|
-
ep
|
290
|
-
name = "#{sim
|
291
|
-
if sim
|
292
|
-
name += " / #{sim
|
310
|
+
if ep['details']['sims']['results'] != nil
|
311
|
+
ep['details']['sims']['results'].each do |sim|
|
312
|
+
name = "#{sim['client']['name']} #{sim['client']['version']}"
|
313
|
+
if sim['client']['platform'] != nil
|
314
|
+
name += " / #{sim['client']['platform']}"
|
293
315
|
end
|
294
316
|
name = name.ljust(28)
|
295
317
|
|
296
|
-
if sim
|
297
|
-
protocol =
|
298
|
-
ep.details.protocols.each do |proto|
|
299
|
-
if sim.protocol_id == proto.id
|
300
|
-
protocol = "#{proto.name} #{proto.version}"
|
301
|
-
end
|
302
|
-
end
|
318
|
+
if sim['errorCode'] == 0
|
319
|
+
protocol = protos[sim['protocolId']]
|
303
320
|
|
304
|
-
|
305
|
-
secure = true
|
306
|
-
ep.details.suites.list.each do |suite|
|
307
|
-
if sim.suite_id == suite.id
|
308
|
-
suite_name = suite.name
|
309
|
-
secure = cipher_suite_secure? suite
|
310
|
-
end
|
311
|
-
end
|
321
|
+
ke = get_key_exchange sim
|
312
322
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
Yawast::Utilities.puts_vuln "\t\t\t#{name} - #{protocol} - #{suite_name}"
|
317
|
-
end
|
323
|
+
suite_name = "#{sim['suiteName']} - #{ke}"
|
324
|
+
|
325
|
+
Yawast::Utilities.puts_info "\t\t\t#{name} - #{protocol} - #{suite_name}"
|
318
326
|
else
|
319
|
-
Yawast::Utilities.
|
327
|
+
Yawast::Utilities.puts_warn"\t\t\t#{name} - Simulation Failed"
|
320
328
|
end
|
321
329
|
end
|
322
330
|
else
|
@@ -329,10 +337,10 @@ module Yawast
|
|
329
337
|
def self.get_proto_info(ep)
|
330
338
|
puts "\t\tProtocol & Vulnerability Information:"
|
331
339
|
|
332
|
-
if ep
|
340
|
+
if ep['details']['drownVulnerable']
|
333
341
|
Yawast::Utilities.puts_vuln "\t\t\tDROWN: Vulnerable"
|
334
342
|
|
335
|
-
ep
|
343
|
+
ep['details']['drownHosts'].each do |dh|
|
336
344
|
Yawast::Utilities.puts_vuln "\t\t\t\t#{dh['ip']}:#{dh['port']} - #{dh['status']}"
|
337
345
|
puts "\t\t\t\thttps://test.drownattack.com/?site=#{dh['ip']}"
|
338
346
|
end
|
@@ -340,26 +348,26 @@ module Yawast
|
|
340
348
|
Yawast::Utilities.puts_info "\t\t\tDROWN: No"
|
341
349
|
end
|
342
350
|
|
343
|
-
if ep
|
351
|
+
if ep['details']['renegSupport'] & 1 != 0
|
344
352
|
Yawast::Utilities.puts_vuln "\t\t\tSecure Renegotiation: insecure client-initiated renegotiation supported"
|
345
353
|
end
|
346
|
-
if ep
|
354
|
+
if ep['details']['renegSupport'] & (1<<1) != 0
|
347
355
|
Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: secure renegotiation supported"
|
348
356
|
end
|
349
|
-
if ep
|
357
|
+
if ep['details']['renegSupport'] & (1<<2) != 0
|
350
358
|
Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: secure client-initiated renegotiation supported"
|
351
359
|
end
|
352
|
-
if ep
|
360
|
+
if ep['details']['renegSupport'] & (1<<3) != 0
|
353
361
|
Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: server requires secure renegotiation support"
|
354
362
|
end
|
355
363
|
|
356
|
-
if ep
|
364
|
+
if ep['details']['poodle']
|
357
365
|
Yawast::Utilities.puts_vuln "\t\t\tPOODLE (SSL): Vulnerable"
|
358
366
|
else
|
359
367
|
Yawast::Utilities.puts_info "\t\t\tPOODLE (SSL): No"
|
360
368
|
end
|
361
369
|
|
362
|
-
case ep
|
370
|
+
case ep['details']['poodleTls']
|
363
371
|
when -3
|
364
372
|
Yawast::Utilities.puts_info "\t\t\tPOODLE (TLS): Inconclusive (Timeout)"
|
365
373
|
when -2
|
@@ -373,28 +381,28 @@ module Yawast
|
|
373
381
|
when 2
|
374
382
|
Yawast::Utilities.puts_vuln "\t\t\tPOODLE (TLS): Vulnerable"
|
375
383
|
else
|
376
|
-
Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Unknown Response #{ep
|
384
|
+
Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Unknown Response #{ep['details'].poodle_tls}"
|
377
385
|
end
|
378
386
|
|
379
|
-
if ep
|
387
|
+
if ep['details']['fallbackScsv']
|
380
388
|
Yawast::Utilities.puts_info "\t\t\tDowngrade Prevention: Yes"
|
381
389
|
else
|
382
390
|
Yawast::Utilities.puts_warn "\t\t\tDowngrade Prevention: No"
|
383
391
|
end
|
384
392
|
|
385
|
-
if ep
|
393
|
+
if ep['details']['compressionMethods'] & 1 != 0
|
386
394
|
Yawast::Utilities.puts_warn "\t\t\tCompression: DEFLATE"
|
387
395
|
else
|
388
396
|
Yawast::Utilities.puts_info "\t\t\tCompression: No"
|
389
397
|
end
|
390
398
|
|
391
|
-
if ep
|
399
|
+
if ep['details']['heartbleed']
|
392
400
|
Yawast::Utilities.puts_vuln "\t\t\tHeartbleed: Vulnerable"
|
393
401
|
else
|
394
402
|
Yawast::Utilities.puts_info "\t\t\tHeartbleed: No"
|
395
403
|
end
|
396
404
|
|
397
|
-
case ep
|
405
|
+
case ep['details']['openSslCcs']
|
398
406
|
when -1
|
399
407
|
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Test Failed"
|
400
408
|
when 0
|
@@ -406,10 +414,10 @@ module Yawast
|
|
406
414
|
when 3
|
407
415
|
Yawast::Utilities.puts_vuln "\t\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable"
|
408
416
|
else
|
409
|
-
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep
|
417
|
+
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep['details'].open_ssl_ccs}"
|
410
418
|
end
|
411
419
|
|
412
|
-
case ep
|
420
|
+
case ep['details']['openSSLLuckyMinus20']
|
413
421
|
when -1
|
414
422
|
Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Test Failed"
|
415
423
|
when 0
|
@@ -419,38 +427,38 @@ module Yawast
|
|
419
427
|
when 2
|
420
428
|
Yawast::Utilities.puts_vuln "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Vulnerable"
|
421
429
|
else
|
422
|
-
Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Unknown Response #{ep
|
430
|
+
Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Unknown Response #{ep['details']['openSSLLuckyMinus20']}"
|
423
431
|
end
|
424
432
|
|
425
|
-
if ep
|
433
|
+
if ep['details']['forwardSecrecy'] & (1<<2) != 0
|
426
434
|
Yawast::Utilities.puts_info "\t\t\tForward Secrecy: Yes (all simulated clients)"
|
427
|
-
elsif ep
|
435
|
+
elsif ep['details']['forwardSecrecy'] & (1<<1) != 0
|
428
436
|
Yawast::Utilities.puts_info "\t\t\tForward Secrecy: Yes (modern clients)"
|
429
|
-
elsif ep
|
437
|
+
elsif ep['details']['forwardSecrecy'] & 1 != 0
|
430
438
|
Yawast::Utilities.puts_warn "\t\t\tForward Secrecy: Yes (limited support)"
|
431
439
|
else
|
432
440
|
Yawast::Utilities.puts_vuln "\t\t\tForward Secrecy: No"
|
433
441
|
end
|
434
442
|
|
435
|
-
if ep
|
443
|
+
if ep['details']['ocspStapling']
|
436
444
|
Yawast::Utilities.puts_info "\t\t\tOCSP Stapling: Yes"
|
437
445
|
else
|
438
446
|
Yawast::Utilities.puts_warn "\t\t\tOCSP Stapling: No"
|
439
447
|
end
|
440
448
|
|
441
|
-
if ep
|
449
|
+
if ep['details']['freak']
|
442
450
|
Yawast::Utilities.puts_vuln "\t\t\tFREAK: Vulnerable"
|
443
451
|
else
|
444
452
|
Yawast::Utilities.puts_info "\t\t\tFREAK: No"
|
445
453
|
end
|
446
454
|
|
447
|
-
if ep
|
455
|
+
if ep['details']['logjam']
|
448
456
|
Yawast::Utilities.puts_vuln "\t\t\tLogjam: Vulnerable"
|
449
457
|
else
|
450
458
|
Yawast::Utilities.puts_info "\t\t\tLogjam: No"
|
451
459
|
end
|
452
460
|
|
453
|
-
case ep
|
461
|
+
case ep['details']['dhUsesKnownPrimes']
|
454
462
|
when 0
|
455
463
|
Yawast::Utilities.puts_info "\t\t\tUses common DH primes: No"
|
456
464
|
when 1
|
@@ -458,39 +466,39 @@ module Yawast
|
|
458
466
|
when 2
|
459
467
|
Yawast::Utilities.puts_vuln "\t\t\tUses common DH primes: Yes (weak)"
|
460
468
|
else
|
461
|
-
unless ep
|
462
|
-
Yawast::Utilities.puts_error "\t\t\tUses common DH primes: Unknown Response #{ep
|
469
|
+
unless ep['details']['dhUsesKnownPrimes'] == nil
|
470
|
+
Yawast::Utilities.puts_error "\t\t\tUses common DH primes: Unknown Response #{ep['details']['dhUsesKnownPrimes']}"
|
463
471
|
end
|
464
472
|
end
|
465
473
|
|
466
|
-
if ep
|
474
|
+
if ep['details']['dhYsReuse']
|
467
475
|
Yawast::Utilities.puts_vuln "\t\t\tDH public server param (Ys) reuse: Yes"
|
468
476
|
else
|
469
477
|
Yawast::Utilities.puts_info "\t\t\tDH public server param (Ys) reuse: No"
|
470
478
|
end
|
471
479
|
|
472
|
-
if ep
|
473
|
-
if ep
|
480
|
+
if ep['details']['protocolIntolerance'] > 0
|
481
|
+
if ep['details']['protocolIntolerance'] & 1 != 0
|
474
482
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 1.0"
|
475
483
|
end
|
476
484
|
|
477
|
-
if ep
|
485
|
+
if ep['details']['protocolIntolerance'] & (1<<1) != 0
|
478
486
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 1.1"
|
479
487
|
end
|
480
488
|
|
481
|
-
if ep
|
489
|
+
if ep['details']['protocolIntolerance'] & (1<<2) != 0
|
482
490
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 1.2"
|
483
491
|
end
|
484
492
|
|
485
|
-
if ep
|
493
|
+
if ep['details']['protocolIntolerance'] & (1<<3) != 0
|
486
494
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 1.3"
|
487
495
|
end
|
488
496
|
|
489
|
-
if ep
|
497
|
+
if ep['details']['protocolIntolerance'] & (1<<4) != 0
|
490
498
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 1.152"
|
491
499
|
end
|
492
500
|
|
493
|
-
if ep
|
501
|
+
if ep['details']['protocolIntolerance'] & (1<<5) != 0
|
494
502
|
Yawast::Utilities.puts_warn "\t\t\tProtocol Intolerance: TLS 2.152"
|
495
503
|
end
|
496
504
|
else
|
@@ -501,22 +509,36 @@ module Yawast
|
|
501
509
|
end
|
502
510
|
|
503
511
|
def self.cipher_suite_secure?(suite)
|
504
|
-
secure =
|
512
|
+
secure = true
|
513
|
+
|
505
514
|
# check for weak DH
|
506
|
-
if suite
|
515
|
+
if suite['kxStrength'] != nil && suite['kxStrength'] < 2048
|
507
516
|
secure = false
|
508
517
|
end
|
509
518
|
# check for RC4
|
510
|
-
if suite
|
519
|
+
if suite['name'].include? 'RC4'
|
511
520
|
secure = false
|
512
521
|
end
|
513
522
|
# check for weak suites
|
514
|
-
if suite
|
523
|
+
if suite['cipherStrength'] < 112
|
515
524
|
secure = false
|
516
525
|
end
|
517
526
|
|
518
527
|
secure
|
519
528
|
end
|
529
|
+
|
530
|
+
def self.get_key_exchange(suite)
|
531
|
+
ke = nil
|
532
|
+
if suite['kxType'] != nil
|
533
|
+
if suite['namedGroupBits'] != nil
|
534
|
+
ke = "#{suite['kxType']}-#{suite['namedGroupBits']} / #{suite['namedGroupName']} (#{suite['kxStrength']} equivalent)"
|
535
|
+
else
|
536
|
+
ke = "#{suite['kxType']}-#{suite['kxStrength']}"
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
return ke
|
541
|
+
end
|
520
542
|
end
|
521
543
|
end
|
522
544
|
end
|