yawast 0.6.0.beta4 → 0.6.0.beta5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/CHANGELOG.md +1 -0
- data/README.md +2 -1
- data/lib/resources/common_file.txt +214 -29
- data/lib/scanner/core.rb +3 -3
- data/lib/scanner/plugins/dns/generic.rb +48 -40
- data/lib/scanner/plugins/servers/apache.rb +22 -0
- data/lib/scanner/plugins/ssl/ssl.rb +55 -0
- data/lib/scanner/plugins/ssl/ssl_labs/analyze.rb +38 -3
- data/lib/scanner/plugins/ssl/sweet32.rb +7 -13
- data/lib/scanner/ssl.rb +5 -41
- data/lib/scanner/ssl_labs.rb +93 -37
- data/lib/shared/http.rb +16 -0
- data/lib/version.rb +1 -1
- data/lib/yawast.rb +2 -2
- data/test/data/hsts_disabled_server_header.txt +16 -0
- data/test/data/hsts_server_header.txt +17 -0
- data/test/data/ssl_labs_analyze_data_file_zetlab_com.json +3851 -0
- data/test/data/ssl_labs_analyze_data_parivahan_gov_in.json +1440 -0
- data/test/test_scan_apache.rb +50 -0
- data/test/test_scan_dns.rb +23 -0
- data/test/test_ssl.rb +43 -0
- data/test/test_ssl_labs_analyze.rb +29 -0
- data/test/test_ssl_sweet32.rb +29 -0
- data/test/test_yawast.rb +2 -1
- metadata +19 -2
@@ -105,48 +105,11 @@ module Yawast
|
|
105
105
|
end
|
106
106
|
|
107
107
|
if options.srv
|
108
|
-
|
109
|
-
f.each_line do |line|
|
110
|
-
host = line.strip + '.' + root_domain
|
111
|
-
begin
|
112
|
-
srv = resv.getresources(host, Resolv::DNS::Resource::IN::SRV)
|
113
|
-
|
114
|
-
unless srv.empty?
|
115
|
-
srv.each do |rec|
|
116
|
-
ip = resv.getaddress rec.target
|
117
|
-
|
118
|
-
Yawast::Utilities.puts_info "\t\tSRV: #{host}: #{rec.target}:#{rec.port} - #{ip} (#{get_network_info(ip.to_s)})"
|
119
|
-
end
|
120
|
-
end
|
121
|
-
rescue
|
122
|
-
#if this fails, don't really care
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
108
|
+
find_srv root_domain, resv
|
126
109
|
end
|
127
110
|
|
128
111
|
if options.subdomains
|
129
|
-
|
130
|
-
f.each_line do |line|
|
131
|
-
host = line.strip + '.' + root_domain
|
132
|
-
|
133
|
-
begin
|
134
|
-
a = resv.getresources(host, Resolv::DNS::Resource::IN::A)
|
135
|
-
|
136
|
-
unless a.empty?
|
137
|
-
a.each do |ip|
|
138
|
-
if IPAddr.new(ip.address.to_s, Socket::AF_INET).private?
|
139
|
-
Yawast::Utilities.puts_info "\t\tA: #{host}: #{ip.address}"
|
140
|
-
else
|
141
|
-
Yawast::Utilities.puts_info "\t\tA: #{host}: #{ip.address} (#{get_network_info(ip.address)})"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
rescue
|
146
|
-
#if this fails, don't really care
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
112
|
+
find_subdomains root_domain, resv
|
150
113
|
end
|
151
114
|
end
|
152
115
|
|
@@ -160,6 +123,51 @@ module Yawast
|
|
160
123
|
end
|
161
124
|
end
|
162
125
|
|
126
|
+
def self.find_srv(root_domain, resv)
|
127
|
+
File.open(File.dirname(__FILE__) + '/../../../resources/srv_list.txt', 'r') do |f|
|
128
|
+
f.each_line do |line|
|
129
|
+
host = line.strip + '.' + root_domain
|
130
|
+
begin
|
131
|
+
srv = resv.getresources(host, Resolv::DNS::Resource::IN::SRV)
|
132
|
+
|
133
|
+
unless srv.empty?
|
134
|
+
srv.each do |rec|
|
135
|
+
ip = resv.getaddress rec.target
|
136
|
+
|
137
|
+
Yawast::Utilities.puts_info "\t\tSRV: #{host}: #{rec.target}:#{rec.port} - #{ip} (#{get_network_info(ip.to_s)})"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
rescue
|
141
|
+
#if this fails, don't really care
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.find_subdomains(root_domain, resv)
|
148
|
+
File.open(File.dirname(__FILE__) + '/../../../resources/subdomain_list.txt', 'r') do |f|
|
149
|
+
f.each_line do |line|
|
150
|
+
host = line.strip + '.' + root_domain
|
151
|
+
|
152
|
+
begin
|
153
|
+
a = resv.getresources(host, Resolv::DNS::Resource::IN::A)
|
154
|
+
|
155
|
+
unless a.empty?
|
156
|
+
a.each do |ip|
|
157
|
+
if IPAddr.new(ip.address.to_s, Socket::AF_INET).private?
|
158
|
+
Yawast::Utilities.puts_info "\t\tA: #{host}: #{ip.address}"
|
159
|
+
else
|
160
|
+
Yawast::Utilities.puts_info "\t\tA: #{host}: #{ip.address} (#{get_network_info(ip.address)})"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
rescue
|
165
|
+
#if this fails, don't really care
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
163
171
|
def self.get_network_info(ip)
|
164
172
|
#check to see if we have this one cached
|
165
173
|
@netinfo = Hash.new if @netinfo == nil
|
@@ -171,7 +179,7 @@ module Yawast
|
|
171
179
|
return 'Network Information disabled due to prior failure' if @netinfo_failed
|
172
180
|
|
173
181
|
begin
|
174
|
-
network_info =
|
182
|
+
network_info = Yawast::Shared::Http.get_json URI("https://api.iptoasn.com/v1/as/ip/#{ip}")
|
175
183
|
|
176
184
|
ret = "#{network_info['as_country_code']} - #{network_info['as_description']}"
|
177
185
|
@netinfo[ip] = ret
|
@@ -47,6 +47,7 @@ module Yawast
|
|
47
47
|
check_tomcat_manager(uri.copy)
|
48
48
|
check_tomcat_version(uri.copy)
|
49
49
|
check_tomcat_put_rce(uri.copy)
|
50
|
+
check_struts2_samples(uri.copy)
|
50
51
|
end
|
51
52
|
|
52
53
|
def self.check_server_status(uri)
|
@@ -140,12 +141,33 @@ module Yawast
|
|
140
141
|
Yawast::Shared::Http.put(uri, req_data)
|
141
142
|
|
142
143
|
# check to see of we get check_value back
|
144
|
+
uri.path = uri.path.chomp('/')
|
143
145
|
res = Yawast::Shared::Http.get(uri)
|
144
146
|
if res.include? check_value
|
145
147
|
Yawast::Utilities.puts_vuln "Apache Tomcat PUT RCE (CVE-2017-12615): #{uri}"
|
146
148
|
end
|
147
149
|
end
|
148
150
|
|
151
|
+
def self.check_struts2_samples(uri)
|
152
|
+
search = Array.new
|
153
|
+
search.push '/Struts2XMLHelloWorld/User/home.action'
|
154
|
+
search.push '/struts2-showcase/showcase.action'
|
155
|
+
search.push '/struts2-showcase/titles/index.action'
|
156
|
+
search.push '/struts2-bootstrap-showcase/'
|
157
|
+
search.push '/struts2-showcase/index.action'
|
158
|
+
search.push '/struts2-bootstrap-showcase/index.action'
|
159
|
+
search.push '/struts2-rest-showcase/'
|
160
|
+
|
161
|
+
search.each do |path|
|
162
|
+
uri.path = path
|
163
|
+
|
164
|
+
ret = Yawast::Shared::Http.get_status_code uri
|
165
|
+
if ret == 200
|
166
|
+
Yawast::Utilities.puts_warn "Apache Struts2 Sample Files: #{uri}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
149
171
|
def self.check_page_for_string(uri, path, search)
|
150
172
|
uri.path = path
|
151
173
|
uri.query = '' if uri.query != nil
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Yawast
|
2
|
+
module Scanner
|
3
|
+
module Plugins
|
4
|
+
module SSL
|
5
|
+
class SSL
|
6
|
+
def self.print_precert(cert)
|
7
|
+
scts = cert.extensions.find {|e| e.oid == 'ct_precert_scts'}
|
8
|
+
|
9
|
+
unless scts.nil?
|
10
|
+
Yawast::Utilities.puts_info "\t\tSCTs:"
|
11
|
+
scts.value.split("\n").each { |line| puts "\t\t\t#{line}" }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.print_cert_hash(cert)
|
16
|
+
hash = Digest::SHA1.hexdigest(cert.to_der)
|
17
|
+
Yawast::Utilities.puts_info "\t\tHash: #{hash}"
|
18
|
+
puts "\t\t\thttps://censys.io/certificates?q=#{hash}"
|
19
|
+
puts "\t\t\thttps://crt.sh/?q=#{hash}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.check_hsts(head)
|
23
|
+
found = ''
|
24
|
+
|
25
|
+
head.each do |k, v|
|
26
|
+
if k.downcase.include? 'strict-transport-security'
|
27
|
+
found = "#{k}: #{v}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if found == ''
|
32
|
+
Yawast::Utilities.puts_warn 'HSTS: Not Enabled'
|
33
|
+
else
|
34
|
+
Yawast::Utilities.puts_info "HSTS: Enabled (#{found})"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.check_hsts_preload(uri)
|
39
|
+
begin
|
40
|
+
info = Yawast::Shared::Http.get_json URI("https://hstspreload.com/api/v1/status/#{uri.host}")
|
41
|
+
|
42
|
+
chrome = info['chrome'] != nil
|
43
|
+
firefox = info['firefox'] != nil
|
44
|
+
tor = info['tor'] != nil
|
45
|
+
|
46
|
+
Yawast::Utilities.puts_info "HSTS Preload: Chrome - #{chrome}; Firefox - #{firefox}; Tor - #{tor}"
|
47
|
+
rescue => e
|
48
|
+
Yawast::Utilities.puts_error "Error getting HSTS preload information: #{e.message}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -5,18 +5,53 @@ module Yawast
|
|
5
5
|
module Plugins
|
6
6
|
module SSL
|
7
7
|
module SSLLabs
|
8
|
+
# setup exception classes
|
9
|
+
class InvocationError < StandardError; end
|
10
|
+
class RequestRateTooHigh < StandardError; end
|
11
|
+
class InternalError < StandardError; end
|
12
|
+
class ServiceNotAvailable < StandardError; end
|
13
|
+
class ServiceOverloaded < StandardError; end
|
14
|
+
|
8
15
|
class Analyze
|
9
|
-
def self.scan(endpoint, target,
|
16
|
+
def self.scan(endpoint, target, start_new)
|
10
17
|
uri = endpoint.copy
|
11
18
|
uri.path = '/api/v3/analyze'
|
12
19
|
|
13
|
-
if
|
20
|
+
if start_new
|
14
21
|
uri.query = "host=#{target}&publish=off&startNew=on&all=done&ignoreMismatch=on"
|
15
22
|
else
|
16
23
|
uri.query = "host=#{target}&publish=off&all=done&ignoreMismatch=on"
|
17
24
|
end
|
18
25
|
|
19
|
-
|
26
|
+
req = Yawast::Shared::Http.get_http(uri)
|
27
|
+
req.use_ssl = uri.scheme == 'https'
|
28
|
+
res = req.request_get(uri, { 'User-Agent' => "YAWAST/#{Yawast::VERSION}" })
|
29
|
+
body = res.read_body
|
30
|
+
code = res.code.to_i
|
31
|
+
|
32
|
+
# check for error in the response - if we don't, we'll wait forever for nothing
|
33
|
+
json = JSON.parse body
|
34
|
+
if json.key?('errors')
|
35
|
+
raise InvocationError, "API returned: #{json['errors']}"
|
36
|
+
end
|
37
|
+
|
38
|
+
# check the response code, make sure it's 200 - otherwise, we should stop now
|
39
|
+
if code != 200
|
40
|
+
case code
|
41
|
+
when 400
|
42
|
+
raise InvocationError, 'invalid parameters'
|
43
|
+
when 429
|
44
|
+
raise RequestRateTooHigh, 'request rate is too high, please slow down'
|
45
|
+
when 500
|
46
|
+
raise InternalError, 'service encountered an error, sleep 5 minutes'
|
47
|
+
when 503
|
48
|
+
raise ServiceNotAvailable, 'service is not available, sleep 15 minutes'
|
49
|
+
when 529
|
50
|
+
raise ServiceOverloaded, 'service is overloaded, sleep 30 minutes'
|
51
|
+
else
|
52
|
+
raise StandardError, "http error code #{r.code}"
|
53
|
+
end
|
54
|
+
end
|
20
55
|
|
21
56
|
return body
|
22
57
|
end
|
@@ -3,12 +3,13 @@ module Yawast
|
|
3
3
|
module Plugins
|
4
4
|
module SSL
|
5
5
|
class Sweet32
|
6
|
-
def self.get_tdes_session_msg_count(uri)
|
6
|
+
def self.get_tdes_session_msg_count(uri, limit = 10000)
|
7
7
|
# this method will send a number of HEAD requests to see
|
8
8
|
# if the connection is eventually killed.
|
9
|
-
unless check_tdes
|
9
|
+
unless check_tdes
|
10
10
|
#if the OpenSSL install doesn't support 3DES, bailout
|
11
11
|
Yawast::Utilities.puts_error "Your copy of OpenSSL doesn't support 3DES cipher suites - SWEET32 test aborted."
|
12
|
+
puts ' See here for more information: https://github.com/adamcaudill/yawast/wiki/OpenSSL-&-3DES-Compatibility'
|
12
13
|
return
|
13
14
|
end
|
14
15
|
|
@@ -84,7 +85,7 @@ module Yawast
|
|
84
85
|
|
85
86
|
req.start do |http|
|
86
87
|
#cache the number of hits
|
87
|
-
|
88
|
+
limit.times do |i|
|
88
89
|
if use_head
|
89
90
|
http.head(uri.path, headers)
|
90
91
|
else
|
@@ -116,20 +117,13 @@ module Yawast
|
|
116
117
|
end
|
117
118
|
|
118
119
|
puts
|
119
|
-
|
120
|
+
limit_formatted = limit.to_s.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
121
|
+
Yawast::Utilities.puts_vuln "TLS Session Request Limit: Connection not terminated after #{limit_formatted} requests; possibly vulnerable to SWEET32"
|
120
122
|
end
|
121
123
|
|
122
|
-
def self.check_tdes
|
124
|
+
def self.check_tdes
|
123
125
|
puts 'Confirming your OpenSSL supports 3DES cipher suites...'
|
124
126
|
|
125
|
-
dns = Resolv::DNS.new
|
126
|
-
|
127
|
-
if IPAddress.valid? uri.host
|
128
|
-
ip = IPAddress.parse uri.host
|
129
|
-
else
|
130
|
-
ip = dns.getaddresses(uri.host)[0]
|
131
|
-
end
|
132
|
-
|
133
127
|
#find all versions that don't include '_server' or '_client'
|
134
128
|
versions = OpenSSL::SSL::SSLContext::METHODS.find_all { |v| !v.to_s.include?('_client') && !v.to_s.include?('_server')}
|
135
129
|
|
data/lib/scanner/ssl.rb
CHANGED
@@ -68,12 +68,8 @@ module Yawast
|
|
68
68
|
Yawast::Utilities.puts_info "\t\tExtensions:"
|
69
69
|
cert.extensions.each { |ext| Yawast::Utilities.puts_info "\t\t\t#{ext}" unless ext.oid == 'subjectAltName' || ext.oid == 'ct_precert_scts' }
|
70
70
|
|
71
|
-
#ct_precert_scts
|
72
|
-
|
73
|
-
unless scts.nil?
|
74
|
-
Yawast::Utilities.puts_info "\t\tSCTs:"
|
75
|
-
scts.value.split("\n").each { |line| puts "\t\t\t#{line}" }
|
76
|
-
end
|
71
|
+
# ct_precert_scts
|
72
|
+
Yawast::Scanner::Plugins::SSL::SSL.print_precert cert
|
77
73
|
|
78
74
|
#alt names
|
79
75
|
alt_names = cert.extensions.find {|e| e.oid == 'subjectAltName'}
|
@@ -82,11 +78,9 @@ module Yawast
|
|
82
78
|
alt_names.value.split(',').each { |name| Yawast::Utilities.puts_info "\t\t\t#{name.strip.delete('DNS:')}" }
|
83
79
|
end
|
84
80
|
|
85
|
-
|
86
|
-
|
87
|
-
puts
|
88
|
-
puts "\t\t\thttps://crt.sh/?q=#{hash}"
|
89
|
-
puts ''
|
81
|
+
Yawast::Scanner::Plugins::SSL::SSL.print_cert_hash cert
|
82
|
+
|
83
|
+
puts
|
90
84
|
end
|
91
85
|
|
92
86
|
def self.get_cert_chain_info(cert_chain, cert)
|
@@ -173,36 +167,6 @@ module Yawast
|
|
173
167
|
end
|
174
168
|
end
|
175
169
|
|
176
|
-
def self.check_hsts(head)
|
177
|
-
found = ''
|
178
|
-
|
179
|
-
head.each do |k, v|
|
180
|
-
if k.downcase.include? 'strict-transport-security'
|
181
|
-
found = "#{k}: #{v}"
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
if found == ''
|
186
|
-
Yawast::Utilities.puts_warn 'HSTS: Not Enabled'
|
187
|
-
else
|
188
|
-
Yawast::Utilities.puts_info "HSTS: Enabled (#{found})"
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
def self.check_hsts_preload(uri)
|
193
|
-
begin
|
194
|
-
info = JSON.parse(Net::HTTP.get(URI("https://hstspreload.com/api/v1/status/#{uri.host}")))
|
195
|
-
|
196
|
-
chrome = info['chrome'] != nil
|
197
|
-
firefox = info['firefox'] != nil
|
198
|
-
tor = info['tor'] != nil
|
199
|
-
|
200
|
-
Yawast::Utilities.puts_info "HSTS Preload: Chrome - #{chrome}; Firefox - #{firefox}; Tor - #{tor}"
|
201
|
-
rescue => e
|
202
|
-
Yawast::Utilities.puts_error "Error getting HSTS preload information: #{e.message}"
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
170
|
#private methods
|
207
171
|
class << self
|
208
172
|
private
|
data/lib/scanner/ssl_labs.rb
CHANGED
@@ -11,7 +11,7 @@ module Yawast
|
|
11
11
|
puts 'Beginning SSL Labs scan (this could take a minute or two)'
|
12
12
|
|
13
13
|
begin
|
14
|
-
endpoint =
|
14
|
+
endpoint = URI::Parser.new.parse 'https://api.ssllabs.com'
|
15
15
|
|
16
16
|
info_body = Yawast::Scanner::Plugins::SSL::SSLLabs::Info.call_info endpoint
|
17
17
|
|
@@ -215,12 +215,12 @@ module Yawast
|
|
215
215
|
end
|
216
216
|
|
217
217
|
Yawast::Utilities.puts_info "\t\tExtensions:"
|
218
|
-
ossl_cert.extensions.each { |ext| Yawast::Utilities.puts_info "\t\t\t#{ext}" unless ext.oid == 'subjectAltName' }
|
218
|
+
ossl_cert.extensions.each { |ext| Yawast::Utilities.puts_info "\t\t\t#{ext}" unless ext.oid == 'subjectAltName' || ext.oid == 'ct_precert_scts' }
|
219
219
|
|
220
|
-
|
221
|
-
Yawast::
|
222
|
-
|
223
|
-
|
220
|
+
# ct_precert_scts
|
221
|
+
Yawast::Scanner::Plugins::SSL::SSL.print_precert ossl_cert
|
222
|
+
|
223
|
+
Yawast::Scanner::Plugins::SSL::SSL.print_cert_hash ossl_cert
|
224
224
|
|
225
225
|
puts
|
226
226
|
Yawast::Utilities.puts_info "\t\tCertificate Chains:"
|
@@ -263,10 +263,12 @@ module Yawast
|
|
263
263
|
puts
|
264
264
|
|
265
265
|
puts "\t\tNamed Group Support:"
|
266
|
-
ep['details']['namedGroups']
|
267
|
-
|
266
|
+
if ep['details']['namedGroups'] != nil
|
267
|
+
ep['details']['namedGroups']['list'].each do |group|
|
268
|
+
Yawast::Utilities.puts_info "\t\t\t#{group['name']} #{group['bits']}"
|
269
|
+
end
|
270
|
+
puts
|
268
271
|
end
|
269
|
-
puts
|
270
272
|
|
271
273
|
puts "\t\tCipher Suite Support:"
|
272
274
|
if ep['details']['suites'] != nil
|
@@ -381,7 +383,7 @@ module Yawast
|
|
381
383
|
when 2
|
382
384
|
Yawast::Utilities.puts_vuln "\t\t\tPOODLE (TLS): Vulnerable"
|
383
385
|
else
|
384
|
-
Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Unknown Response #{ep['details']
|
386
|
+
Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Unknown Response #{ep['details']['poodleTls']}"
|
385
387
|
end
|
386
388
|
|
387
389
|
if ep['details']['fallbackScsv']
|
@@ -396,12 +398,31 @@ module Yawast
|
|
396
398
|
Yawast::Utilities.puts_info "\t\t\tCompression: No"
|
397
399
|
end
|
398
400
|
|
401
|
+
if ep['details']['heartbeat']
|
402
|
+
Yawast::Utilities.puts_warn "\t\t\tHeartbeat: Enabled"
|
403
|
+
else
|
404
|
+
Yawast::Utilities.puts_info "\t\t\tHeartbeat: Disabled"
|
405
|
+
end
|
406
|
+
|
399
407
|
if ep['details']['heartbleed']
|
400
408
|
Yawast::Utilities.puts_vuln "\t\t\tHeartbleed: Vulnerable"
|
401
409
|
else
|
402
410
|
Yawast::Utilities.puts_info "\t\t\tHeartbleed: No"
|
403
411
|
end
|
404
412
|
|
413
|
+
case ep['details']['ticketbleed']
|
414
|
+
when -1
|
415
|
+
Yawast::Utilities.puts_error "\t\t\tTicketbleed (CVE-2016-9244): Test Failed"
|
416
|
+
when 0
|
417
|
+
Yawast::Utilities.puts_error "\t\t\tTicketbleed (CVE-2016-9244): Test Failed (Unknown)"
|
418
|
+
when 1
|
419
|
+
Yawast::Utilities.puts_info "\t\t\tTicketbleed (CVE-2016-9244): No"
|
420
|
+
when 2
|
421
|
+
Yawast::Utilities.puts_vuln "\t\t\tTicketbleed (CVE-2016-9244): Vulnerable"
|
422
|
+
else
|
423
|
+
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep['details']['ticketbleed']}"
|
424
|
+
end
|
425
|
+
|
405
426
|
case ep['details']['openSslCcs']
|
406
427
|
when -1
|
407
428
|
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Test Failed"
|
@@ -414,7 +435,7 @@ module Yawast
|
|
414
435
|
when 3
|
415
436
|
Yawast::Utilities.puts_vuln "\t\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable"
|
416
437
|
else
|
417
|
-
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep['details']
|
438
|
+
Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep['details']['openSslCcs']}"
|
418
439
|
end
|
419
440
|
|
420
441
|
case ep['details']['openSSLLuckyMinus20']
|
@@ -440,41 +461,39 @@ module Yawast
|
|
440
461
|
Yawast::Utilities.puts_vuln "\t\t\tForward Secrecy: No"
|
441
462
|
end
|
442
463
|
|
443
|
-
|
444
|
-
Yawast::Utilities.puts_info "\t\t\tOCSP Stapling: Yes"
|
445
|
-
else
|
446
|
-
Yawast::Utilities.puts_warn "\t\t\tOCSP Stapling: No"
|
447
|
-
end
|
448
|
-
|
449
|
-
if ep['details']['freak']
|
450
|
-
Yawast::Utilities.puts_vuln "\t\t\tFREAK: Vulnerable"
|
451
|
-
else
|
452
|
-
Yawast::Utilities.puts_info "\t\t\tFREAK: No"
|
453
|
-
end
|
464
|
+
Yawast::Utilities.puts_info "\t\t\tALPN: #{ep['details']['alpnProtocols']}"
|
454
465
|
|
455
|
-
|
456
|
-
Yawast::Utilities.puts_vuln "\t\t\tLogjam: Vulnerable"
|
457
|
-
else
|
458
|
-
Yawast::Utilities.puts_info "\t\t\tLogjam: No"
|
459
|
-
end
|
466
|
+
Yawast::Utilities.puts_info "\t\t\tNPN: #{ep['details']['npnProtocols']}"
|
460
467
|
|
461
|
-
case ep['details']['
|
468
|
+
case ep['details']['sessionResumption']
|
462
469
|
when 0
|
463
|
-
Yawast::Utilities.puts_info "\t\t\
|
470
|
+
Yawast::Utilities.puts_info "\t\t\tSession Resumption: Not Enabled / Empty Tickets"
|
464
471
|
when 1
|
465
|
-
Yawast::Utilities.
|
472
|
+
Yawast::Utilities.puts_info "\t\t\tSession Resumption: Enabled / No Resumption"
|
466
473
|
when 2
|
467
|
-
Yawast::Utilities.
|
474
|
+
Yawast::Utilities.puts_warn "\t\t\tSession Resumption: Enabled"
|
468
475
|
else
|
469
|
-
|
470
|
-
Yawast::Utilities.puts_error "\t\t\tUses common DH primes: Unknown Response #{ep['details']['dhUsesKnownPrimes']}"
|
471
|
-
end
|
476
|
+
Yawast::Utilities.puts_error "\t\t\tSession Resumption: Unknown Response #{ep['details']['sessionResumption']}"
|
472
477
|
end
|
473
478
|
|
474
|
-
if ep['details']['
|
475
|
-
Yawast::Utilities.
|
479
|
+
if ep['details']['ocspStapling']
|
480
|
+
Yawast::Utilities.puts_info "\t\t\tOCSP Stapling: Yes"
|
476
481
|
else
|
477
|
-
Yawast::Utilities.
|
482
|
+
Yawast::Utilities.puts_warn "\t\t\tOCSP Stapling: No"
|
483
|
+
end
|
484
|
+
|
485
|
+
if ep['details']['miscIntolerance'] > 0
|
486
|
+
if ep['details']['miscIntolerance'] & 1 != 0
|
487
|
+
Yawast::Utilities.puts_warn "\t\t\tTLS Extension Intolerance: Yes"
|
488
|
+
end
|
489
|
+
|
490
|
+
if ep['details']['miscIntolerance'] & (1<<1) != 0
|
491
|
+
Yawast::Utilities.puts_warn "\t\t\tLong Handshake Intolerance: Yes"
|
492
|
+
end
|
493
|
+
|
494
|
+
if ep['details']['miscIntolerance'] & (1<<2) != 0
|
495
|
+
Yawast::Utilities.puts_warn "\t\t\tLong Handshake Intolerance: Workaround Success"
|
496
|
+
end
|
478
497
|
end
|
479
498
|
|
480
499
|
if ep['details']['protocolIntolerance'] > 0
|
@@ -505,6 +524,43 @@ module Yawast
|
|
505
524
|
Yawast::Utilities.puts_info "\t\t\tProtocol Intolerance: No"
|
506
525
|
end
|
507
526
|
|
527
|
+
if ep['details']['freak']
|
528
|
+
Yawast::Utilities.puts_vuln "\t\t\tFREAK: Vulnerable (512-bit key exchange supported)"
|
529
|
+
else
|
530
|
+
Yawast::Utilities.puts_info "\t\t\tFREAK: No"
|
531
|
+
end
|
532
|
+
|
533
|
+
if ep['details']['logjam']
|
534
|
+
Yawast::Utilities.puts_vuln "\t\t\tLogjam: Vulnerable (DH key exchange with keys smaller than 1024 bits)"
|
535
|
+
else
|
536
|
+
Yawast::Utilities.puts_info "\t\t\tLogjam: No"
|
537
|
+
end
|
538
|
+
|
539
|
+
case ep['details']['dhUsesKnownPrimes']
|
540
|
+
when 0
|
541
|
+
Yawast::Utilities.puts_info "\t\t\tUses common DH primes: No"
|
542
|
+
when 1
|
543
|
+
Yawast::Utilities.puts_warn "\t\t\tUses common DH primes: Yes (not weak)"
|
544
|
+
when 2
|
545
|
+
Yawast::Utilities.puts_vuln "\t\t\tUses common DH primes: Yes (weak)"
|
546
|
+
else
|
547
|
+
unless ep['details']['dhUsesKnownPrimes'] == nil
|
548
|
+
Yawast::Utilities.puts_error "\t\t\tUses common DH primes: Unknown Response #{ep['details']['dhUsesKnownPrimes']}"
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
if ep['details']['dhYsReuse']
|
553
|
+
Yawast::Utilities.puts_vuln "\t\t\tDH public server param (Ys) reuse: Yes"
|
554
|
+
else
|
555
|
+
Yawast::Utilities.puts_info "\t\t\tDH public server param (Ys) reuse: No"
|
556
|
+
end
|
557
|
+
|
558
|
+
if ep['details']['ecdhParameterReuse']
|
559
|
+
Yawast::Utilities.puts_vuln "\t\t\tECDH Public Server Param Reuse: Yes"
|
560
|
+
else
|
561
|
+
Yawast::Utilities.puts_info "\t\t\tECDH Public Server Param Reuse: No"
|
562
|
+
end
|
563
|
+
|
508
564
|
puts
|
509
565
|
end
|
510
566
|
|
data/lib/shared/http.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'securerandom'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Yawast
|
4
5
|
module Shared
|
@@ -47,6 +48,21 @@ module Yawast
|
|
47
48
|
body
|
48
49
|
end
|
49
50
|
|
51
|
+
def self.get_json(uri)
|
52
|
+
body = ''
|
53
|
+
|
54
|
+
begin
|
55
|
+
req = get_http(uri)
|
56
|
+
req.use_ssl = uri.scheme == 'https'
|
57
|
+
res = req.request_get(uri, { 'User-Agent' => "YAWAST/#{Yawast::VERSION}" })
|
58
|
+
body = res.read_body
|
59
|
+
rescue
|
60
|
+
#do nothing for now
|
61
|
+
end
|
62
|
+
|
63
|
+
JSON.parse body
|
64
|
+
end
|
65
|
+
|
50
66
|
def self.put(uri, body, headers = nil)
|
51
67
|
begin
|
52
68
|
req = get_http(uri)
|
data/lib/version.rb
CHANGED
data/lib/yawast.rb
CHANGED
@@ -25,7 +25,7 @@ require_all '/shared'
|
|
25
25
|
|
26
26
|
module Yawast
|
27
27
|
DESCRIPTION = 'The YAWAST Antecedent Web Application Security Toolkit'
|
28
|
-
HTTP_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X
|
28
|
+
HTTP_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) YAWAST/#{VERSION} Chrome/61.0.3163.100 Safari/537.36"
|
29
29
|
|
30
30
|
def self.header
|
31
31
|
puts '__ _____ _ _ ___ _____ _____ '
|
@@ -41,7 +41,7 @@ module Yawast
|
|
41
41
|
puts " Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}; #{OpenSSL::OPENSSL_VERSION} (#{RUBY_PLATFORM})"
|
42
42
|
|
43
43
|
begin
|
44
|
-
version =
|
44
|
+
version = Yawast::Shared::Http.get_json(URI('https://rubygems.org/api/v1/versions/yawast/latest.json'))['version']
|
45
45
|
|
46
46
|
if version != VERSION
|
47
47
|
puts " Latest Version: YAWAST v#{version} is the officially supported version, please update.".blue
|
@@ -0,0 +1,16 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Sun, 22 Oct 2017 22:44:34 GMT
|
3
|
+
Content-Type: text/html; charset=UTF-8
|
4
|
+
Connection: keep-alive
|
5
|
+
Set-Cookie: __cfduid=d1f8c33f1dccb58e367a4570c63ac5ce41508712274; expires=Mon, 22-Oct-18 22:44:34 GMT; path=/; domain=.adamcaudill.com; HttpOnly; Secure
|
6
|
+
Vary: Accept-Encoding,Cookie
|
7
|
+
Last-Modified: Fri, 13 Oct 2017 19:39:19 GMT
|
8
|
+
X-Content-Type-Options: nosniff
|
9
|
+
X-Frame-Options: sameorigin
|
10
|
+
Pragma: public
|
11
|
+
Cache-Control: public, max-age=86400
|
12
|
+
CF-Cache-Status: HIT
|
13
|
+
Expires: Mon, 23 Oct 2017 22:44:34 GMT
|
14
|
+
Server: cloudflare-nginx
|
15
|
+
CF-RAY: 3b1ffb6499c12ea5-MIA
|
16
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Date: Sun, 22 Oct 2017 22:44:34 GMT
|
3
|
+
Content-Type: text/html; charset=UTF-8
|
4
|
+
Connection: keep-alive
|
5
|
+
Set-Cookie: __cfduid=d1f8c33f1dccb58e367a4570c63ac5ce41508712274; expires=Mon, 22-Oct-18 22:44:34 GMT; path=/; domain=.adamcaudill.com; HttpOnly; Secure
|
6
|
+
Vary: Accept-Encoding,Cookie
|
7
|
+
Last-Modified: Fri, 13 Oct 2017 19:39:19 GMT
|
8
|
+
X-Content-Type-Options: nosniff
|
9
|
+
X-Frame-Options: sameorigin
|
10
|
+
Pragma: public
|
11
|
+
Cache-Control: public, max-age=86400
|
12
|
+
CF-Cache-Status: HIT
|
13
|
+
Expires: Mon, 23 Oct 2017 22:44:34 GMT
|
14
|
+
Strict-Transport-Security: max-age=15552000; preload
|
15
|
+
Server: cloudflare-nginx
|
16
|
+
CF-RAY: 3b1ffb6499c12ea5-MIA
|
17
|
+
|