yawast 0.2.0.beta1

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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +7 -0
  5. data/README.md +454 -0
  6. data/Rakefile +9 -0
  7. data/bin/yawast +69 -0
  8. data/lib/commands/cms.rb +10 -0
  9. data/lib/commands/head.rb +12 -0
  10. data/lib/commands/scan.rb +11 -0
  11. data/lib/commands/ssl.rb +11 -0
  12. data/lib/commands/utils.rb +36 -0
  13. data/lib/resources/common.txt +1960 -0
  14. data/lib/scanner/apache.rb +72 -0
  15. data/lib/scanner/cms.rb +14 -0
  16. data/lib/scanner/core.rb +95 -0
  17. data/lib/scanner/generic.rb +323 -0
  18. data/lib/scanner/iis.rb +63 -0
  19. data/lib/scanner/nginx.rb +13 -0
  20. data/lib/scanner/obj_presence.rb +63 -0
  21. data/lib/scanner/php.rb +19 -0
  22. data/lib/scanner/ssl.rb +237 -0
  23. data/lib/scanner/ssl_labs.rb +491 -0
  24. data/lib/shared/http.rb +67 -0
  25. data/lib/string_ext.rb +16 -0
  26. data/lib/uri_ext.rb +5 -0
  27. data/lib/util.rb +25 -0
  28. data/lib/yawast.rb +57 -0
  29. data/test/base.rb +43 -0
  30. data/test/data/apache_server_info.txt +486 -0
  31. data/test/data/apache_server_status.txt +184 -0
  32. data/test/data/cms_none_body.txt +242 -0
  33. data/test/data/cms_wordpress_body.txt +467 -0
  34. data/test/data/iis_server_header.txt +13 -0
  35. data/test/data/tomcat_release_notes.txt +172 -0
  36. data/test/data/wordpress_readme_html.txt +86 -0
  37. data/test/test_cmd_util.rb +35 -0
  38. data/test/test_helper.rb +5 -0
  39. data/test/test_object_presence.rb +36 -0
  40. data/test/test_scan_apache_banner.rb +58 -0
  41. data/test/test_scan_apache_server_info.rb +22 -0
  42. data/test/test_scan_apache_server_status.rb +22 -0
  43. data/test/test_scan_cms.rb +27 -0
  44. data/test/test_scan_iis_headers.rb +40 -0
  45. data/test/test_scan_nginx_banner.rb +18 -0
  46. data/test/test_shared_http.rb +40 -0
  47. data/test/test_shared_util.rb +44 -0
  48. data/test/test_string_ext.rb +15 -0
  49. data/test/test_yawast.rb +17 -0
  50. data/yawast.gemspec +35 -0
  51. metadata +283 -0
@@ -0,0 +1,491 @@
1
+ require 'ssllabs'
2
+ require 'date'
3
+ require 'openssl'
4
+ require 'digest/sha1'
5
+
6
+ module Yawast
7
+ module Scanner
8
+ class SslLabs
9
+ def self.info(uri, sslsessioncount)
10
+ puts 'Beginning SSL Labs scan (this could take a minute or two)'
11
+
12
+ api = Ssllabs::Api.new
13
+
14
+ info = api.info
15
+
16
+ info.messages.each do |msg|
17
+ puts "[SSL Labs]\t#{msg}"
18
+ end
19
+
20
+ begin
21
+ api.analyse(host: uri.host, publish: 'off', fromCache: 'on', all: 'done', ignoreMismatch: 'on')
22
+
23
+ status = ''
24
+ host = nil
25
+ until status == 'READY' || status == 'ERROR' || status == 'DNS'
26
+ # poll for updates every 5 seconds
27
+ # don't want to poll faster, to avoid excess load / errors
28
+ sleep(5)
29
+
30
+ host = api.analyse(host: uri.host, publish: 'off', all: 'done', ignoreMismatch: 'on')
31
+ status = host.status
32
+
33
+ print '.'
34
+ end
35
+ puts
36
+ puts
37
+
38
+ host.endpoints.each do |ep|
39
+ Yawast::Utilities.puts_info "IP: #{ep.ip_address} - Grade: #{ep.grade}"
40
+ puts
41
+
42
+ begin
43
+ if ep.status_message == 'Ready'
44
+ get_cert_info(ep)
45
+ get_config_info(ep)
46
+ get_proto_info(ep)
47
+ else
48
+ Yawast::Utilities.puts_error "Error getting information for IP: #{ep.ip_address}: #{ep.status_message}"
49
+ end
50
+ rescue => e
51
+ Yawast::Utilities.puts_error "Error getting information for IP: #{ep.ip_address}: #{e.message}"
52
+ end
53
+
54
+ Yawast::Scanner::Ssl.get_session_msg_count(uri) if sslsessioncount
55
+
56
+ puts
57
+ end
58
+ rescue => e
59
+ Yawast::Utilities.puts_error "SSL Labs Error: #{e.message}"
60
+ end
61
+ end
62
+
63
+ def self.get_cert_info (ep)
64
+ # get the ChainCert info for the server cert - needed for extra details
65
+ cert = nil
66
+ ossl_cert = nil
67
+ ep.details.chain.certs.each do |c|
68
+ if c.subject == ep.details.cert.subject
69
+ cert = c
70
+ ossl_cert = OpenSSL::X509::Certificate.new cert.raw
71
+ end
72
+ end
73
+
74
+ puts "\tCertificate Information:"
75
+ unless ep.details.cert.valid?
76
+ Yawast::Utilities.puts_vuln "\t\tCertificate Has Issues - Not Valid"
77
+
78
+ if ep.details.cert.issues & 1 != 0
79
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: no chain of trust"
80
+ end
81
+
82
+ if ep.details.cert.issues & (1<<1) != 0
83
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: certificate not yet valid"
84
+ end
85
+
86
+ if ep.details.cert.issues & (1<<2) != 0
87
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: certificate expired"
88
+ end
89
+
90
+ if ep.details.cert.issues & (1<<3) != 0
91
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: hostname mismatch"
92
+ end
93
+
94
+ if ep.details.cert.issues & (1<<4) != 0
95
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: revoked"
96
+ end
97
+
98
+ if ep.details.cert.issues & (1<<5) != 0
99
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: bad common name"
100
+ end
101
+
102
+ if ep.details.cert.issues & (1<<6) != 0
103
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: self-signed"
104
+ end
105
+
106
+ if ep.details.cert.issues & (1<<7) != 0
107
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: blacklisted"
108
+ end
109
+
110
+ if ep.details.cert.issues & (1<<8) != 0
111
+ Yawast::Utilities.puts_vuln "\t\tCertificate Issue: insecure signature"
112
+ end
113
+ end
114
+
115
+ Yawast::Utilities.puts_info "\t\tSubject: #{ep.details.cert.subject}"
116
+ Yawast::Utilities.puts_info "\t\tCommon Names: #{ep.details.cert.common_names}"
117
+
118
+ Yawast::Utilities.puts_info "\t\tAlternative names:"
119
+ ep.details.cert.alt_names.each do |name|
120
+ Yawast::Utilities.puts_info "\t\t\t#{name}"
121
+ end
122
+
123
+ # here we divide the time by 1000 to strip the fractions of a second off.
124
+ Yawast::Utilities.puts_info "\t\tNot Before: #{Time.at(ep.details.cert.not_before / 1000).utc.to_datetime}"
125
+ Yawast::Utilities.puts_info "\t\tNot After: #{Time.at(ep.details.cert.not_after / 1000).utc.to_datetime}"
126
+
127
+ if cert.key_alg == 'EC'
128
+ Yawast::Utilities.puts_info "\t\tKey: #{cert.key_alg} #{cert.key_size} (RSA equivalent: #{cert.key_strength})"
129
+ else
130
+ if cert.key_size < 2048
131
+ Yawast::Utilities.puts_vuln "\t\tKey: #{cert.key_alg} #{cert.key_size}"
132
+ else
133
+ Yawast::Utilities.puts_info "\t\tKey: #{cert.key_alg} #{cert.key_size}"
134
+ end
135
+ end
136
+
137
+ Yawast::Utilities.puts_info "\t\tPublic Key Hash: #{Digest::SHA1.hexdigest(ossl_cert.public_key.to_s)}"
138
+
139
+ Yawast::Utilities.puts_info "\t\tVersion: #{ossl_cert.version}"
140
+
141
+ Yawast::Utilities.puts_info "\t\tSerial: #{ossl_cert.serial}"
142
+
143
+ Yawast::Utilities.puts_info "\t\tIssuer: #{ep.details.cert.issuer_label}"
144
+
145
+ if ep.details.cert.sig_alg.include?('SHA1') || ep.details.cert.sig_alg.include?('MD5')
146
+ Yawast::Utilities.puts_vuln "\t\tSignature algorithm: #{ep.details.cert.sig_alg}"
147
+ else
148
+ Yawast::Utilities.puts_info "\t\tSignature algorithm: #{ep.details.cert.sig_alg}"
149
+ end
150
+
151
+ #todo - figure out what the options for this value are
152
+ if ep.details.cert.validation_type == 'E'
153
+ Yawast::Utilities.puts_info "\t\tExtended Validation: Yes"
154
+ elsif ep.details.cert.validation_type == 'D'
155
+ Yawast::Utilities.puts_info "\t\tExtended Validation: No (Domain Control)"
156
+ else
157
+ Yawast::Utilities.puts_info "\t\tExtended Validation: No"
158
+ end
159
+
160
+ if ep.details.cert.sct?
161
+ # check the first bit, SCT in cert
162
+ if ep.details.has_sct & 1 != 0
163
+ Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in certificate"
164
+ end
165
+
166
+ # check second bit, SCT in stapled OSCP response
167
+ if ep.details.has_sct & (1<<1) != 0
168
+ Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in the stapled OCSP response"
169
+ end
170
+
171
+ # check third bit, SCT in the TLS extension
172
+ if ep.details.has_sct & (1<<2) != 0
173
+ Yawast::Utilities.puts_info "\t\tCertificate Transparency: SCT in the TLS extension (ServerHello)"
174
+ end
175
+ else
176
+ Yawast::Utilities.puts_info "\t\tCertificate Transparency: No"
177
+ end
178
+
179
+ case ep.details.cert.must_staple
180
+ when 0
181
+ Yawast::Utilities.puts_info "\t\tOCSP Must Staple: No"
182
+ when 1
183
+ Yawast::Utilities.puts_warn "\t\tOCSP Must Staple: Supported, but OCSP response is not stapled"
184
+ when 2
185
+ Yawast::Utilities.puts_info "\t\tOCSP Must Staple: OCSP response is stapled"
186
+ else
187
+ Yawast::Utilities.puts_error "\t\tOCSP Must Staple: Unknown Response #{ep.details.cert.must_staple}"
188
+ end
189
+
190
+ if ep.details.cert.revocation_info & 1 != 0
191
+ Yawast::Utilities.puts_info "\t\tRevocation information: CRL information available"
192
+ end
193
+ if ep.details.cert.revocation_info & (1<<1) != 0
194
+ Yawast::Utilities.puts_info "\t\tRevocation information: OCSP information available"
195
+ end
196
+
197
+ case ep.details.cert.revocation_status
198
+ when 0
199
+ Yawast::Utilities.puts_info "\t\tRevocation status: not checked"
200
+ when 1
201
+ Yawast::Utilities.puts_vuln "\t\tRevocation status: certificate revoked"
202
+ when 2
203
+ Yawast::Utilities.puts_info "\t\tRevocation status: certificate not revoked"
204
+ when 3
205
+ Yawast::Utilities.puts_error "\t\tRevocation status: revocation check error"
206
+ when 4
207
+ Yawast::Utilities.puts_info "\t\tRevocation status: no revocation information"
208
+ when 5
209
+ Yawast::Utilities.puts_error "\t\tRevocation status: SSL Labs internal error"
210
+ else
211
+ Yawast::Utilities.puts_error "\t\tRevocation status: Unknown response #{ep.details.cert.revocation_status}"
212
+ end
213
+
214
+ Yawast::Utilities.puts_info "\t\tExtensions:"
215
+ ossl_cert.extensions.each { |ext| Yawast::Utilities.puts_info "\t\t\t#{ext}" unless ext.oid == 'subjectAltName' }
216
+
217
+ hash = Digest::SHA1.hexdigest(ossl_cert.to_der)
218
+ Yawast::Utilities.puts_info "\t\tHash: #{hash}"
219
+ puts "\t\t\thttps://censys.io/certificates?q=#{hash}"
220
+ puts "\t\t\thttps://crt.sh/?q=#{hash}"
221
+
222
+ puts
223
+ end
224
+
225
+ def self.get_config_info(ep)
226
+ puts "\tConfiguration Information:"
227
+
228
+ puts "\t\tProtocol Support:"
229
+ ep.details.protocols.each do |proto|
230
+ if proto.name == 'SSL'
231
+ Yawast::Utilities.puts_vuln "\t\t\t#{proto.name} #{proto.version}"
232
+ else
233
+ Yawast::Utilities.puts_info "\t\t\t#{proto.name} #{proto.version}"
234
+ end
235
+ end
236
+ puts
237
+
238
+ puts "\t\tCipher Suite Support:"
239
+ if ep.details.suites.list != nil
240
+ ep.details.suites.list.each do |suite|
241
+ ke = nil
242
+ if suite.ecdh_bits != nil || suite.dh_strength != nil
243
+ if suite.name.include? 'ECDHE'
244
+ ke = "ECDHE-#{suite.ecdh_bits}-bits"
245
+ elsif suite.name.include? 'ECDH'
246
+ ke = "ECDH-#{suite.ecdh_bits}"
247
+ elsif suite.name.include? 'DHE'
248
+ ke = "DHE-#{suite.dh_strength}-bits"
249
+ elsif suite.name.include? 'DH'
250
+ ke = "DH-#{suite.dh_strength}-bits"
251
+ end
252
+ end
253
+
254
+ strength = suite.cipher_strength
255
+ if suite.name.include? '3DES'
256
+ # in this case, the effective strength is only 112 bits,
257
+ # which is what we want to report. So override SSL Labs
258
+ strength = 112
259
+ end
260
+
261
+ suite_info = nil
262
+ if ke != nil
263
+ suite_info = "#{suite.name.ljust(50)} - #{strength}-bits - #{ke}"
264
+ else
265
+ suite_info = "#{suite.name.ljust(50)} - #{strength}-bits"
266
+ end
267
+
268
+ if cipher_suite_secure? suite
269
+ if strength >= 128
270
+ Yawast::Utilities.puts_info "\t\t\t#{suite_info}"
271
+ else
272
+ Yawast::Utilities.puts_warn "\t\t\t#{suite_info}"
273
+ end
274
+ else
275
+ Yawast::Utilities.puts_vuln "\t\t\t#{suite_info}"
276
+ end
277
+ end
278
+ else
279
+ Yawast::Utilities.puts_error "\t\t\tInformation Not Available"
280
+ end
281
+
282
+ puts
283
+
284
+ puts "\t\tHandshake Simulation:"
285
+ if ep.details.sims.results != nil
286
+ ep.details.sims.results.each do |sim|
287
+ name = "#{sim.client.name} #{sim.client.version}"
288
+ if sim.client.platform != nil
289
+ name += " / #{sim.client.platform}"
290
+ end
291
+ name = name.ljust(28)
292
+
293
+ if sim.success?
294
+ protocol = nil
295
+ ep.details.protocols.each do |proto|
296
+ if sim.protocol_id == proto.id
297
+ protocol = "#{proto.name} #{proto.version}"
298
+ end
299
+ end
300
+
301
+ suite_name = nil
302
+ secure = true
303
+ ep.details.suites.list.each do |suite|
304
+ if sim.suite_id == suite.id
305
+ suite_name = suite.name
306
+ secure = cipher_suite_secure? suite
307
+ end
308
+ end
309
+
310
+ if secure
311
+ Yawast::Utilities.puts_info "\t\t\t#{name} - #{protocol} - #{suite_name}"
312
+ else
313
+ Yawast::Utilities.puts_vuln "\t\t\t#{name} - #{protocol} - #{suite_name}"
314
+ end
315
+ else
316
+ Yawast::Utilities.puts_error "\t\t\t#{name} - Simulation Failed"
317
+ end
318
+ end
319
+ else
320
+ Yawast::Utilities.puts_error "\t\t\tInformation Not Available"
321
+ end
322
+
323
+ puts
324
+ end
325
+
326
+ def self.get_proto_info(ep)
327
+ puts "\t\tProtocol & Vulnerability Information:"
328
+
329
+ if ep.details.drown_vulnerable?
330
+ Yawast::Utilities.puts_vuln "\t\t\tDROWN: Vulnerable"
331
+
332
+ ep.details.drown_hosts.each do |dh|
333
+ Yawast::Utilities.puts_vuln "\t\t\t\t#{dh['ip']}:#{dh['port']} - #{dh['status']}"
334
+ puts "\t\t\t\thttps://test.drownattack.com/?site=#{dh['ip']}"
335
+ end
336
+ else
337
+ Yawast::Utilities.puts_info "\t\t\tDROWN: No"
338
+ end
339
+
340
+ if ep.details.reneg_support & 1 != 0
341
+ Yawast::Utilities.puts_vuln "\t\t\tSecure Renegotiation: insecure client-initiated renegotiation supported"
342
+ end
343
+ if ep.details.reneg_support & (1<<1) != 0
344
+ Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: secure renegotiation supported"
345
+ end
346
+ if ep.details.reneg_support & (1<<2) != 0
347
+ Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: secure client-initiated renegotiation supported"
348
+ end
349
+ if ep.details.reneg_support & (1<<3) != 0
350
+ Yawast::Utilities.puts_info "\t\t\tSecure Renegotiation: server requires secure renegotiation support"
351
+ end
352
+
353
+ if ep.details.poodle?
354
+ Yawast::Utilities.puts_vuln "\t\t\tPOODLE (SSL): Vulnerable"
355
+ else
356
+ Yawast::Utilities.puts_info "\t\t\tPOODLE (SSL): No"
357
+ end
358
+
359
+ case ep.details.poodle_tls
360
+ when -3
361
+ Yawast::Utilities.puts_info "\t\t\tPOODLE (TLS): Inconclusive (Timeout)"
362
+ when -2
363
+ Yawast::Utilities.puts_info "\t\t\tPOODLE (TLS): TLS Not Supported"
364
+ when -1
365
+ Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Test Failed"
366
+ when 0
367
+ Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Test Failed (Unknown)"
368
+ when 1
369
+ Yawast::Utilities.puts_info "\t\t\tPOODLE (TLS): No"
370
+ when 2
371
+ Yawast::Utilities.puts_vuln "\t\t\tPOODLE (TLS): Vulnerable"
372
+ else
373
+ Yawast::Utilities.puts_error "\t\t\tPOODLE (TLS): Unknown Response #{ep.details.poodle_tls}"
374
+ end
375
+
376
+ if ep.details.fallback_scsv?
377
+ Yawast::Utilities.puts_info "\t\t\tDowngrade Prevention: Yes"
378
+ else
379
+ Yawast::Utilities.puts_warn "\t\t\tDowngrade Prevention: No"
380
+ end
381
+
382
+ if ep.details.compression_methods & 1 != 0
383
+ Yawast::Utilities.puts_warn "\t\t\tCompression: DEFLATE"
384
+ else
385
+ Yawast::Utilities.puts_info "\t\t\tCompression: No"
386
+ end
387
+
388
+ if ep.details.heartbleed?
389
+ Yawast::Utilities.puts_vuln "\t\t\tHeartbleed: Vulnerable"
390
+ else
391
+ Yawast::Utilities.puts_info "\t\t\tHeartbleed: No"
392
+ end
393
+
394
+ case ep.details.open_ssl_ccs
395
+ when -1
396
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Test Failed"
397
+ when 0
398
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Test Failed (Unknown)"
399
+ when 1
400
+ Yawast::Utilities.puts_info "\t\t\tOpenSSL CCS (CVE-2014-0224): No"
401
+ when 2
402
+ Yawast::Utilities.puts_vuln "\t\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable - Not Exploitable"
403
+ when 3
404
+ Yawast::Utilities.puts_vuln "\t\t\tOpenSSL CCS (CVE-2014-0224): Vulnerable"
405
+ else
406
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL CCS (CVE-2014-0224): Unknown Response #{ep.details.open_ssl_ccs}"
407
+ end
408
+
409
+ case ep.details.open_ssl_lucky_minus20
410
+ when -1
411
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Test Failed"
412
+ when 0
413
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Test Failed (Unknown)"
414
+ when 1
415
+ Yawast::Utilities.puts_info "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): No"
416
+ when 2
417
+ Yawast::Utilities.puts_vuln "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Vulnerable"
418
+ else
419
+ Yawast::Utilities.puts_error "\t\t\tOpenSSL Padding Oracle (CVE-2016-2107): Unknown Response #{ep.details.open_ssl_lucky_minus20}"
420
+ end
421
+
422
+ if ep.details.forward_secrecy & (1<<2) != 0
423
+ Yawast::Utilities.puts_info "\t\t\tForward Secrecy: Yes (all simulated clients)"
424
+ elsif ep.details.forward_secrecy & (1<<1) != 0
425
+ Yawast::Utilities.puts_info "\t\t\tForward Secrecy: Yes (modern clients)"
426
+ elsif ep.details.forward_secrecy & 1 != 0
427
+ Yawast::Utilities.puts_warn "\t\t\tForward Secrecy: Yes (limited support)"
428
+ else
429
+ Yawast::Utilities.puts_vuln "\t\t\tForward Secrecy: No"
430
+ end
431
+
432
+ if ep.details.ocsp_stapling?
433
+ Yawast::Utilities.puts_info "\t\t\tOCSP Stapling: Yes"
434
+ else
435
+ Yawast::Utilities.puts_warn "\t\t\tOCSP Stapling: No"
436
+ end
437
+
438
+ if ep.details.freak?
439
+ Yawast::Utilities.puts_vuln "\t\t\tFREAK: Vulnerable"
440
+ else
441
+ Yawast::Utilities.puts_info "\t\t\tFREAK: No"
442
+ end
443
+
444
+ if ep.details.logjam?
445
+ Yawast::Utilities.puts_vuln "\t\t\tLogjam: Vulnerable"
446
+ else
447
+ Yawast::Utilities.puts_info "\t\t\tLogjam: No"
448
+ end
449
+
450
+ case ep.details.dh_uses_known_primes
451
+ when 0
452
+ Yawast::Utilities.puts_info "\t\t\tUses common DH primes: No"
453
+ when 1
454
+ Yawast::Utilities.puts_warn "\t\t\tUses common DH primes: Yes (not weak)"
455
+ when 2
456
+ Yawast::Utilities.puts_vuln "\t\t\tUses common DH primes: Yes (weak)"
457
+ else
458
+ unless ep.details.dh_uses_known_primes == nil
459
+ Yawast::Utilities.puts_error "\t\t\tUses common DH primes: Unknown Response #{ep.details.dh_uses_known_primes}"
460
+ end
461
+ end
462
+
463
+ if ep.details.dh_ys_reuse?
464
+ Yawast::Utilities.puts_vuln "\t\t\tDH public server param (Ys) reuse: Yes"
465
+ else
466
+ Yawast::Utilities.puts_info "\t\t\tDH public server param (Ys) reuse: No"
467
+ end
468
+
469
+ puts
470
+ end
471
+
472
+ def self.cipher_suite_secure?(suite)
473
+ secure = suite.secure?
474
+ # check for weak DH
475
+ if suite.dh_strength != nil && suite.dh_strength < 2048
476
+ secure = false
477
+ end
478
+ # check for RC4
479
+ if suite.name.include? 'RC4'
480
+ secure = false
481
+ end
482
+ # check for weak suites
483
+ if suite.cipher_strength < 112
484
+ secure = false
485
+ end
486
+
487
+ secure
488
+ end
489
+ end
490
+ end
491
+ end
@@ -0,0 +1,67 @@
1
+ module Yawast
2
+ module Shared
3
+ class Http
4
+ def self.setup(proxy, cookie)
5
+ if proxy != nil && proxy.include?(':')
6
+ @proxy_host, @proxy_port = proxy.split(':')
7
+ @proxy = true
8
+
9
+ puts "Using Proxy: #{proxy}"
10
+ else
11
+ @proxy = false
12
+ end
13
+
14
+ @cookie = cookie
15
+ puts "Using Cookie: #{@cookie}" if @cookie != nil
16
+ end
17
+
18
+ def self.head(uri)
19
+ req = get_http(uri)
20
+ req.use_ssl = uri.scheme == 'https'
21
+ req.head(uri.path, get_headers)
22
+ end
23
+
24
+ def self.get(uri)
25
+ body = ''
26
+
27
+ begin
28
+ req = get_http(uri)
29
+ req.use_ssl = uri.scheme == 'https'
30
+ res = req.request_get(uri.path, get_headers)
31
+ body = res.read_body
32
+ rescue
33
+ #do nothing for now
34
+ end
35
+
36
+ body
37
+ end
38
+
39
+ def self.get_status_code(uri)
40
+ req = get_http(uri)
41
+ req.use_ssl = uri.scheme == 'https'
42
+ res = req.head(uri.path, get_headers)
43
+ res.code
44
+ end
45
+
46
+ def self.get_http(uri)
47
+ if @proxy
48
+ req = Net::HTTP.new(uri.host, uri.port, @proxy_host, @proxy_port)
49
+ else
50
+ req = Net::HTTP.new(uri.host, uri.port)
51
+ end
52
+
53
+ req
54
+ end
55
+
56
+ def self.get_headers
57
+ if @cookie == nil
58
+ headers = { 'User-Agent' => HTTP_UA }
59
+ else
60
+ headers = { 'User-Agent' => HTTP_UA, 'Cookie' => @cookie }
61
+ end
62
+
63
+ headers
64
+ end
65
+ end
66
+ end
67
+ end
data/lib/string_ext.rb ADDED
@@ -0,0 +1,16 @@
1
+ class String
2
+ #see if string is numeric
3
+ def is_number?
4
+ true if Float(self) rescue false
5
+ end
6
+
7
+ def trim
8
+ trimmed = self.strip
9
+
10
+ if trimmed == nil
11
+ self
12
+ else
13
+ trimmed
14
+ end
15
+ end
16
+ end
data/lib/uri_ext.rb ADDED
@@ -0,0 +1,5 @@
1
+ module URI
2
+ def copy
3
+ URI.parse(self.to_s)
4
+ end
5
+ end
data/lib/util.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'colorize'
2
+
3
+ module Yawast
4
+ class Utilities
5
+ def self.puts_msg(type, msg)
6
+ puts "#{type} #{msg}"
7
+ end
8
+
9
+ def self.puts_error(msg)
10
+ puts_msg('[E]'.red, msg)
11
+ end
12
+
13
+ def self.puts_vuln(msg)
14
+ puts_msg('[V]'.magenta, msg)
15
+ end
16
+
17
+ def self.puts_warn(msg)
18
+ puts_msg('[W]'.yellow, msg)
19
+ end
20
+
21
+ def self.puts_info(msg)
22
+ puts_msg('[I]'.green, msg)
23
+ end
24
+ end
25
+ end
data/lib/yawast.rb ADDED
@@ -0,0 +1,57 @@
1
+ # Require all of the Ruby files in the given directory.
2
+ #
3
+ # path - The String relative path from here to the directory.
4
+ def require_all(path)
5
+ glob = File.join(File.dirname(__FILE__), path, '*.rb')
6
+ Dir[glob].each do |f|
7
+ require f
8
+ end
9
+ end
10
+
11
+ require 'uri'
12
+ require 'resolv'
13
+ require 'net/http'
14
+ require 'socket'
15
+
16
+ require './lib/string_ext'
17
+ require './lib/uri_ext'
18
+ require './lib/util'
19
+
20
+ require_all '/commands'
21
+ require_all '/scanner'
22
+ require_all '/shared'
23
+
24
+ module Yawast
25
+ VERSION = '0.2.0.beta1'
26
+ DESCRIPTION = 'The YAWAST Antecedent Web Application Security Toolkit'
27
+ HTTP_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Yawast/#{VERSION} Chrome/52.0.2743.24 Safari/537.36"
28
+
29
+ def self.header
30
+ puts '__ _____ _ _ ___ _____ _____ '
31
+ puts '\ \ / / _ \| | | |/ _ \ / ___|_ _|'
32
+ puts ' \ V / /_\ \ | | / /_\ \\\ `--. | | '
33
+ puts ' \ /| _ | |/\| | _ | `--. \ | | '
34
+ puts ' | || | | \ /\ / | | |/\__/ / | | '
35
+ puts ' \_/\_| |_/\/ \/\_| |_/\____/ \_/ '
36
+ puts ''
37
+ puts "YAWAST v#{VERSION} - #{DESCRIPTION}"
38
+ puts ' Copyright (c) 2013-2016 Adam Caudill <adam@adamcaudill.com>'
39
+ puts ' Support & Documentation: https://github.com/adamcaudill/yawast'
40
+ puts " Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}; #{OpenSSL::OPENSSL_VERSION} (#{RUBY_PLATFORM})"
41
+ puts ''
42
+ end
43
+
44
+ def self.set_openssl_options
45
+ #change certain defaults, to make things work better
46
+ #we prefer RSA, to avoid issues with small DH keys
47
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ciphers] = "RSA:ALL:COMPLEMENTOFALL"
48
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
49
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] = OpenSSL::SSL::OP_ALL
50
+ end
51
+
52
+ trap 'SIGINT' do
53
+ puts
54
+ puts 'Scan cancelled by user.'
55
+ exit 0
56
+ end
57
+ end