yawast 0.2.0.beta1

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