yawast 0.7.0.beta1 → 0.7.0.beta2
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/.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
|