yawast 0.6.0.beta4 → 0.6.0.beta5
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/.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
|
+
|