yawast 0.6.0.beta5 → 0.6.0.beta6
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 +9 -1148
- data/.ruby-version +1 -1
- data/CHANGELOG.md +1 -0
- data/bin/yawast +1 -0
- data/lib/commands/dns.rb +1 -1
- data/lib/resources/common_file.txt +1 -0
- data/lib/scanner/core.rb +3 -25
- data/lib/scanner/generic.rb +0 -25
- data/lib/scanner/plugins/dns/generic.rb +16 -6
- data/lib/scanner/plugins/ssl/ssl.rb +55 -0
- data/lib/scanner/ssl_labs.rb +55 -3
- data/lib/shared/http.rb +10 -12
- data/lib/version.rb +1 -1
- data/lib/yawast.rb +0 -8
- data/test/data/ssl_labs_analyze_data.json +683 -278
- data/test/data/ssl_labs_analyze_data_activationservice1_installshield_com.json +1376 -0
- data/test/data/ssl_labs_analyze_data_forest_gov_tw.json +3762 -0
- data/test/test_cmd_util.rb +6 -0
- data/test/test_shared_http.rb +23 -0
- data/test/test_ssl.rb +31 -0
- data/test/test_ssl_labs_analyze.rb +30 -0
- metadata +7 -3
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.4.1
|
data/CHANGELOG.md
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
* [#120](https://github.com/adamcaudill/yawast/issues/120) - Add Docker support
|
12
12
|
* [#122](https://github.com/adamcaudill/yawast/issues/122) - SSL Labs API v3
|
13
13
|
* [#125](https://github.com/adamcaudill/yawast/issues/125) - Add new search paths for Struts Sample Files
|
14
|
+
* [#129](https://github.com/adamcaudill/yawast/issues/129) - Bug: DNS Info fails if MX record points to a domain without records
|
14
15
|
|
15
16
|
## 0.5.2 - 2017-07-13
|
16
17
|
|
data/bin/yawast
CHANGED
@@ -56,6 +56,7 @@ command :ssl do |c|
|
|
56
56
|
c.option '--nociphers', 'Disables check for supported ciphers (only with --internalssl)'
|
57
57
|
c.option '--internalssl', 'Disable SSL Labs integration'
|
58
58
|
c.option '--tdessessioncount', 'Counts the number of messages that can be sent in a single session'
|
59
|
+
c.option '--nodns', 'Disable DNS checks'
|
59
60
|
|
60
61
|
c.action do |args, options|
|
61
62
|
Yawast::Commands::Ssl.process(args, options)
|
data/lib/commands/dns.rb
CHANGED
@@ -13987,6 +13987,7 @@ wp-email.php
|
|
13987
13987
|
wp-fbuser.php
|
13988
13988
|
wp-feed.php
|
13989
13989
|
wp-forum.phps
|
13990
|
+
wp-includes/js/swfupload/swfupload.swf
|
13990
13991
|
wp-includes/js/tinymce/plugins/wpview/diff.php
|
13991
13992
|
wp-json
|
13992
13993
|
wp-json/wp/v2/posts
|
data/lib/scanner/core.rb
CHANGED
@@ -14,13 +14,13 @@ module Yawast
|
|
14
14
|
|
15
15
|
print_header
|
16
16
|
|
17
|
-
ssl_redirect = check_for_ssl_redirect
|
17
|
+
ssl_redirect = Yawast::Scanner::Plugins::SSL::SSL.check_for_ssl_redirect @uri
|
18
18
|
if ssl_redirect
|
19
19
|
@uri = ssl_redirect
|
20
20
|
puts "Server redirects to TLS: Scanning: #{@uri}"
|
21
21
|
end
|
22
22
|
|
23
|
-
Yawast.set_openssl_options
|
23
|
+
Yawast::Scanner::Plugins::SSL::SSL.set_openssl_options
|
24
24
|
|
25
25
|
unless options.nodns
|
26
26
|
Yawast::Scanner::Plugins::DNS::Generic.dns_info @uri, options
|
@@ -50,7 +50,7 @@ module Yawast
|
|
50
50
|
#process the 'scan' stuff that goes beyond 'head'
|
51
51
|
unless options.head
|
52
52
|
# connection details for SSL
|
53
|
-
Yawast::Scanner::
|
53
|
+
Yawast::Scanner::Plugins::SSL::SSL.ssl_connection_info @uri
|
54
54
|
|
55
55
|
# server specific checks
|
56
56
|
Yawast::Scanner::Plugins::Servers::Apache.check_all(@uri)
|
@@ -88,28 +88,6 @@ module Yawast
|
|
88
88
|
Yawast::Scanner::Cms.get_generator(body)
|
89
89
|
end
|
90
90
|
|
91
|
-
def self.check_for_ssl_redirect
|
92
|
-
#check to see if the site redirects to SSL by default
|
93
|
-
if @uri.scheme != 'https'
|
94
|
-
head = Yawast::Shared::Http.head(@uri)
|
95
|
-
|
96
|
-
if head['Location'] != nil
|
97
|
-
begin
|
98
|
-
location = URI.parse(head['Location'])
|
99
|
-
|
100
|
-
if location.scheme == 'https'
|
101
|
-
#we run this through extract_uri as it performs a few checks we need
|
102
|
-
return Yawast::Shared::Uri.extract_uri location.to_s
|
103
|
-
end
|
104
|
-
rescue
|
105
|
-
#we don't care if this fails
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
return nil
|
111
|
-
end
|
112
|
-
|
113
91
|
def self.check_ssl(uri, options, head)
|
114
92
|
setup(uri, options)
|
115
93
|
|
data/lib/scanner/generic.rb
CHANGED
@@ -205,31 +205,6 @@ module Yawast
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
end
|
208
|
-
|
209
|
-
def self.ssl_connection_info(uri)
|
210
|
-
begin
|
211
|
-
# we only care if this is https
|
212
|
-
if uri.scheme == 'https'
|
213
|
-
# setup the connection
|
214
|
-
socket = TCPSocket.new(uri.host, uri.port)
|
215
|
-
|
216
|
-
ctx = OpenSSL::SSL::SSLContext.new
|
217
|
-
ctx.ciphers = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
|
218
|
-
|
219
|
-
ssl = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
220
|
-
ssl.hostname = uri.host
|
221
|
-
ssl.connect
|
222
|
-
|
223
|
-
# this provides a bunch of useful info, that's already formatted
|
224
|
-
# instead of building this manually, we'll let OpenSSL do the work
|
225
|
-
puts ssl.session.to_text
|
226
|
-
|
227
|
-
puts
|
228
|
-
end
|
229
|
-
rescue => e
|
230
|
-
Yawast::Utilities.puts_error "SSL Information: Error Getting Details: #{e.message}"
|
231
|
-
end
|
232
|
-
end
|
233
208
|
end
|
234
209
|
|
235
210
|
#Custom class to allow using the PROPFIND verb
|
@@ -77,9 +77,13 @@ module Yawast
|
|
77
77
|
mx = resv.getresources(uri.host, Resolv::DNS::Resource::IN::MX)
|
78
78
|
unless mx.empty?
|
79
79
|
mx.each do |rec|
|
80
|
-
|
80
|
+
begin
|
81
|
+
ip = resv.getaddress rec.exchange
|
81
82
|
|
82
|
-
|
83
|
+
Yawast::Utilities.puts_info "\t\tMX: #{rec.exchange} (#{rec.preference}) - #{ip} (#{get_network_info(ip.to_s)})"
|
84
|
+
rescue => e
|
85
|
+
Yawast::Utilities.puts_error "\t\tMX: #{rec.exchange} (#{rec.preference}) - Error: #{e.message})"
|
86
|
+
end
|
83
87
|
end
|
84
88
|
end
|
85
89
|
|
@@ -88,9 +92,13 @@ module Yawast
|
|
88
92
|
mx = resv.getresources(root_domain, Resolv::DNS::Resource::IN::MX)
|
89
93
|
unless mx.empty?
|
90
94
|
mx.each do |rec|
|
91
|
-
|
95
|
+
begin
|
96
|
+
ip = resv.getaddress rec.exchange
|
92
97
|
|
93
|
-
|
98
|
+
Yawast::Utilities.puts_info "\t\tMX (#{root_domain}): #{rec.exchange} (#{rec.preference}) - #{ip} (#{get_network_info(ip.to_s)})"
|
99
|
+
rescue => e
|
100
|
+
Yawast::Utilities.puts_error "\t\tMX (#{root_domain}): #{rec.exchange} (#{rec.preference}) - Error: #{e.message})"
|
101
|
+
end
|
94
102
|
end
|
95
103
|
end
|
96
104
|
end
|
@@ -113,8 +121,10 @@ module Yawast
|
|
113
121
|
end
|
114
122
|
end
|
115
123
|
|
116
|
-
#get the CAA info
|
117
|
-
|
124
|
+
#get the CAA info - unless it's an IP
|
125
|
+
unless IPAddress.valid? uri.host
|
126
|
+
Yawast::Scanner::Plugins::DNS::CAA.caa_info uri
|
127
|
+
end
|
118
128
|
|
119
129
|
puts
|
120
130
|
rescue => e
|
@@ -48,6 +48,61 @@ module Yawast
|
|
48
48
|
Yawast::Utilities.puts_error "Error getting HSTS preload information: #{e.message}"
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def self.set_openssl_options
|
53
|
+
#change certain defaults, to make things work better
|
54
|
+
#we prefer RSA, to avoid issues with small DH keys
|
55
|
+
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = 'RSA:ALL:COMPLEMENTOFALL'
|
56
|
+
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
57
|
+
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_ALL
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.check_for_ssl_redirect(uri)
|
61
|
+
#check to see if the site redirects to SSL by default
|
62
|
+
if uri.scheme != 'https'
|
63
|
+
head = Yawast::Shared::Http.head(uri)
|
64
|
+
|
65
|
+
if head['Location'] != nil
|
66
|
+
begin
|
67
|
+
location = URI.parse(head['Location'])
|
68
|
+
|
69
|
+
if location.scheme == 'https'
|
70
|
+
#we run this through extract_uri as it performs a few checks we need
|
71
|
+
return Yawast::Shared::Uri.extract_uri location.to_s
|
72
|
+
end
|
73
|
+
rescue
|
74
|
+
#we don't care if this fails
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
return nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.ssl_connection_info(uri)
|
83
|
+
begin
|
84
|
+
# we only care if this is https
|
85
|
+
if uri.scheme == 'https'
|
86
|
+
# setup the connection
|
87
|
+
socket = TCPSocket.new(uri.host, uri.port)
|
88
|
+
|
89
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
90
|
+
ctx.ciphers = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers]
|
91
|
+
|
92
|
+
ssl = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
93
|
+
ssl.hostname = uri.host
|
94
|
+
ssl.connect
|
95
|
+
|
96
|
+
# this provides a bunch of useful info, that's already formatted
|
97
|
+
# instead of building this manually, we'll let OpenSSL do the work
|
98
|
+
puts ssl.session.to_text
|
99
|
+
|
100
|
+
puts
|
101
|
+
end
|
102
|
+
rescue => e
|
103
|
+
Yawast::Utilities.puts_error "SSL Information: Error Getting Details: #{e.message}"
|
104
|
+
end
|
105
|
+
end
|
51
106
|
end
|
52
107
|
end
|
53
108
|
end
|
data/lib/scanner/ssl_labs.rb
CHANGED
@@ -5,7 +5,6 @@ require 'json'
|
|
5
5
|
|
6
6
|
module Yawast
|
7
7
|
module Scanner
|
8
|
-
# noinspection RubyResolve
|
9
8
|
class SslLabs
|
10
9
|
def self.info(uri, tdes_session_count)
|
11
10
|
puts 'Beginning SSL Labs scan (this could take a minute or two)'
|
@@ -227,16 +226,51 @@ module Yawast
|
|
227
226
|
ep['details']['certChains'].each do |chain|
|
228
227
|
path_count = 0
|
229
228
|
|
229
|
+
# build list of trust paths
|
230
|
+
trust_paths = Hash.new
|
230
231
|
chain['trustPaths'].each do |path|
|
232
|
+
trusts = nil
|
233
|
+
# in practice, it seems there is only only per path, but just in case
|
234
|
+
path['trust'].each do |trust|
|
235
|
+
if trust['isTrusted']
|
236
|
+
trust_line = "#{trust['rootStore']} (trusted)"
|
237
|
+
else
|
238
|
+
trust_line = "#{trust['rootStore']} (#{trust['trustErrorMessage']})"
|
239
|
+
end
|
240
|
+
|
241
|
+
if trusts == nil
|
242
|
+
trusts = trust_line
|
243
|
+
else
|
244
|
+
trusts += " #{trust_line}"
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
# build the hash and add the list of roots
|
249
|
+
if trust_paths.has_key? path['certIds']
|
250
|
+
trust_paths[path['certIds']] += " #{trusts}"
|
251
|
+
else
|
252
|
+
trust_paths[path['certIds']] = trusts
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
# process each of the trust paths
|
257
|
+
trust_paths.each_key do |key|
|
231
258
|
path_count += 1
|
232
259
|
puts "\t\t Path #{path_count}:"
|
260
|
+
puts "\t\t Root Stores: #{trust_paths[key]}"
|
233
261
|
|
234
|
-
|
262
|
+
key.each do |path_cert|
|
235
263
|
body['certs'].each do |c|
|
236
264
|
if c['id'] == path_cert
|
237
265
|
Yawast::Utilities.puts_info "\t\t\t#{c['subject']}"
|
238
266
|
Yawast::Utilities.puts_info "\t\t\t Signature: #{c['sigAlg']} Key: #{c['keyAlg']}-#{c['keySize']}"
|
239
267
|
Yawast::Utilities.puts_info "\t\t\t https://crt.sh/?q=#{c['sha1Hash']}"
|
268
|
+
|
269
|
+
if chain['certIds'].find_index(c['sha256Hash']) != nil
|
270
|
+
Yawast::Utilities.puts_info "\t\t\t (provided by server)"
|
271
|
+
end
|
272
|
+
|
273
|
+
puts
|
240
274
|
end
|
241
275
|
end
|
242
276
|
end
|
@@ -420,9 +454,10 @@ module Yawast
|
|
420
454
|
when 2
|
421
455
|
Yawast::Utilities.puts_vuln "\t\t\tTicketbleed (CVE-2016-9244): Vulnerable"
|
422
456
|
else
|
423
|
-
Yawast::Utilities.puts_error "\t\t\
|
457
|
+
Yawast::Utilities.puts_error "\t\t\tTicketbleed (CVE-2016-9244): Unknown Response #{ep['details']['ticketbleed']}"
|
424
458
|
end
|
425
459
|
|
460
|
+
|
426
461
|
case ep['details']['openSslCcs']
|
427
462
|
when -1
|
428
463
|
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Test Failed"
|
@@ -451,6 +486,23 @@ module Yawast
|
|
451
486
|
Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Unknown Response #{ep['details']['openSSLLuckyMinus20']}"
|
452
487
|
end
|
453
488
|
|
489
|
+
case ep['details']['bleichenbacher']
|
490
|
+
when -1
|
491
|
+
Yawast::Utilities.puts_error "\t\t\tROBOT: Test Failed"
|
492
|
+
when 0
|
493
|
+
Yawast::Utilities.puts_error "\t\t\tROBOT: Test Failed (Unknown)"
|
494
|
+
when 1
|
495
|
+
Yawast::Utilities.puts_info "\t\t\tROBOT: No"
|
496
|
+
when 2
|
497
|
+
Yawast::Utilities.puts_warn "\t\t\tROBOT: Not Exploitable"
|
498
|
+
when 3
|
499
|
+
Yawast::Utilities.puts_vuln "\t\t\tROBOT: Exploitable"
|
500
|
+
when nil
|
501
|
+
# if it's null, we don't care
|
502
|
+
else
|
503
|
+
Yawast::Utilities.puts_error "\t\t\tROBOT: Unknown Response #{ep['details']['bleichenbacher']}"
|
504
|
+
end
|
505
|
+
|
454
506
|
if ep['details']['forwardSecrecy'] & (1<<2) != 0
|
455
507
|
Yawast::Utilities.puts_info "\t\t\tForward Secrecy: Yes (all simulated clients)"
|
456
508
|
elsif ep['details']['forwardSecrecy'] & (1<<1) != 0
|
data/lib/shared/http.rb
CHANGED
@@ -5,7 +5,7 @@ module Yawast
|
|
5
5
|
module Shared
|
6
6
|
class Http
|
7
7
|
def self.setup(proxy, cookie)
|
8
|
-
if proxy
|
8
|
+
if !proxy.nil? && proxy.include?(':')
|
9
9
|
@proxy_host, @proxy_port = proxy.split(':')
|
10
10
|
@proxy = true
|
11
11
|
|
@@ -15,7 +15,7 @@ module Yawast
|
|
15
15
|
end
|
16
16
|
|
17
17
|
@cookie = cookie
|
18
|
-
puts "Using Cookie: #{@cookie}"
|
18
|
+
puts "Using Cookie: #{@cookie}" unless @cookie.nil?
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.head(uri)
|
@@ -24,8 +24,8 @@ module Yawast
|
|
24
24
|
req.use_ssl = uri.scheme == 'https'
|
25
25
|
req.head(uri, get_headers)
|
26
26
|
rescue
|
27
|
-
#if we get here, the HEAD failed - but GET may work
|
28
|
-
#so we silently fail back to using GET instead
|
27
|
+
# if we get here, the HEAD failed - but GET may work
|
28
|
+
# so we silently fail back to using GET instead
|
29
29
|
req = get_http(uri)
|
30
30
|
req.use_ssl = uri.scheme == 'https'
|
31
31
|
res = req.request_get(uri, get_headers)
|
@@ -42,7 +42,7 @@ module Yawast
|
|
42
42
|
res = req.request_get(uri, get_headers(headers))
|
43
43
|
body = res.read_body
|
44
44
|
rescue
|
45
|
-
#do nothing for now
|
45
|
+
# do nothing for now
|
46
46
|
end
|
47
47
|
|
48
48
|
body
|
@@ -54,10 +54,10 @@ module Yawast
|
|
54
54
|
begin
|
55
55
|
req = get_http(uri)
|
56
56
|
req.use_ssl = uri.scheme == 'https'
|
57
|
-
res = req.request_get(uri,
|
57
|
+
res = req.request_get(uri, 'User-Agent' => "YAWAST/#{Yawast::VERSION}")
|
58
58
|
body = res.read_body
|
59
59
|
rescue
|
60
|
-
#do nothing for now
|
60
|
+
# do nothing for now
|
61
61
|
end
|
62
62
|
|
63
63
|
JSON.parse body
|
@@ -69,7 +69,7 @@ module Yawast
|
|
69
69
|
req.use_ssl = uri.scheme == 'https'
|
70
70
|
res = req.request_put(uri, body, get_headers(headers))
|
71
71
|
rescue
|
72
|
-
#do nothing for now
|
72
|
+
# do nothing for now
|
73
73
|
end
|
74
74
|
|
75
75
|
res.read_body
|
@@ -102,7 +102,7 @@ module Yawast
|
|
102
102
|
end
|
103
103
|
|
104
104
|
if Yawast::Shared::Http.get_status_code(fake_uri) != '404'
|
105
|
-
#crazy 404 handling
|
105
|
+
# crazy 404 handling
|
106
106
|
return false
|
107
107
|
end
|
108
108
|
|
@@ -117,9 +117,7 @@ module Yawast
|
|
117
117
|
headers = { 'User-Agent' => HTTP_UA, 'Cookie' => @cookie }
|
118
118
|
end
|
119
119
|
|
120
|
-
|
121
|
-
headers.merge! extra_headers
|
122
|
-
end
|
120
|
+
headers.merge! extra_headers unless extra_headers.nil?
|
123
121
|
|
124
122
|
headers
|
125
123
|
end
|
data/lib/version.rb
CHANGED
data/lib/yawast.rb
CHANGED
@@ -53,14 +53,6 @@ module Yawast
|
|
53
53
|
puts ''
|
54
54
|
end
|
55
55
|
|
56
|
-
def self.set_openssl_options
|
57
|
-
#change certain defaults, to make things work better
|
58
|
-
#we prefer RSA, to avoid issues with small DH keys
|
59
|
-
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = 'RSA:ALL:COMPLEMENTOFALL'
|
60
|
-
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
61
|
-
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_ALL
|
62
|
-
end
|
63
|
-
|
64
56
|
STDOUT.sync = true
|
65
57
|
|
66
58
|
trap 'SIGINT' do
|