yawast 0.6.0.beta5 → 0.6.0.beta6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|