ssl_scan 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/ssl_scan +14 -1
- data/lib/ssl_scan/commands/command.rb +31 -0
- data/lib/ssl_scan/commands/host.rb +27 -0
- data/lib/ssl_scan/commands/only_certain_ssl.rb +13 -0
- data/lib/ssl_scan/commands/targets.rb +31 -0
- data/lib/ssl_scan/main.rb +157 -0
- data/lib/ssl_scan/scanner.rb +8 -2
- data/lib/ssl_scan/version.rb +1 -1
- data/lib/ssl_scan.rb +0 -1
- data/sslscan.gemspec +1 -1
- metadata +7 -3
- data/lib/ssl_scan/client.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee1b01a1ed01a07e0c4f9bdadf2629fba62cec7c
|
4
|
+
data.tar.gz: 7baa900e8e512ac129a19672dc6011ee6611e522
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9bef799b8620cf82a8b3b1ac388a5ad74a752b3c0e0c434eacc13740261b9f870ab4a4d91f5d76f5860499b421e069689ff56516da4b8648ebe98f5bc4973ae
|
7
|
+
data.tar.gz: 56c3419bfbd31b857b3b1594c7f8877f74952bca6fe9374e8e86a35da98869256d02ef78673a974caffa2bf2fe4fd2f4512ce7b615bf720fe99be56f39c01611
|
data/bin/ssl_scan
CHANGED
@@ -1,4 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
4
|
-
require 'ssl_scan/
|
4
|
+
require 'ssl_scan/main'
|
5
|
+
|
6
|
+
|
7
|
+
# register interrupt handlers
|
8
|
+
trap("TERM") do
|
9
|
+
exit(1)
|
10
|
+
end
|
11
|
+
|
12
|
+
trap("QUIT") do
|
13
|
+
exit(1)
|
14
|
+
end
|
15
|
+
|
16
|
+
app = SSLScan::Main.new
|
17
|
+
app.run(ARGV.length, ARGV)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SSLScan
|
2
|
+
module Commands
|
3
|
+
class Command
|
4
|
+
attr_accessor :results, :options
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@results = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def execute
|
11
|
+
raise "Implement"
|
12
|
+
end
|
13
|
+
|
14
|
+
# Display Methods
|
15
|
+
def display_header(host, port=443)
|
16
|
+
printf "\nTesting SSL server #{host} on port #{port}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def display_ciphers(scanner=nil)
|
20
|
+
printf "\nSupported Server Cipher(s):\n"
|
21
|
+
scanner.scan do |ssl_version, cipher_name, alg_length, status|
|
22
|
+
unless options.no_failed && status == :failed
|
23
|
+
printf "%12s %10s %10s %s\n", status, ssl_version, "#{alg_length} bits", cipher_name
|
24
|
+
end
|
25
|
+
end
|
26
|
+
scanner
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SSLScan
|
2
|
+
module Commands
|
3
|
+
class Host < Command
|
4
|
+
attr_accessor :hostname, :options
|
5
|
+
|
6
|
+
def initialize(hostname, options)
|
7
|
+
super()
|
8
|
+
@hostname = hostname
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
parts = hostname.split(":")
|
14
|
+
if parts.length == 2
|
15
|
+
display_header(parts[0], parts[1])
|
16
|
+
scanner = SSLScan::Scanner.new(parts[0], parts[1].to_i)
|
17
|
+
else
|
18
|
+
display_header(parts[0])
|
19
|
+
scanner = SSLScan::Scanner.new(parts[0])
|
20
|
+
end
|
21
|
+
display_ciphers(scanner)
|
22
|
+
@results << scanner.results
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Host
|
26
|
+
end # Commands
|
27
|
+
end # SSLScan
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SSLScan
|
2
|
+
module Commands
|
3
|
+
class Targets < Command
|
4
|
+
|
5
|
+
attr_accessor :file, :hosts
|
6
|
+
|
7
|
+
def initialize(filename="", options)
|
8
|
+
super()
|
9
|
+
@file = File.read(filename)
|
10
|
+
@hosts = @file.split("\n").map(&:strip).select { |h| h.length > 0 }
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute
|
15
|
+
hosts.each do |host|
|
16
|
+
parts = host.split(":")
|
17
|
+
if parts.length == 2
|
18
|
+
display_header(parts[0], parts[1])
|
19
|
+
scanner = SSLScan::Scanner.new(parts[0], parts[1].to_i)
|
20
|
+
else
|
21
|
+
display_header(host)
|
22
|
+
scanner = SSLScan::Scanner.new(parts[0])
|
23
|
+
end
|
24
|
+
display_ciphers(scanner)
|
25
|
+
@results << scanner.results
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "ssl_scan/compat"
|
2
|
+
require "ssl_scan/version"
|
3
|
+
require "ssl_scan/scanner"
|
4
|
+
require "ssl_scan/result"
|
5
|
+
require "openssl"
|
6
|
+
require "optparse"
|
7
|
+
require "ostruct"
|
8
|
+
|
9
|
+
require "ssl_scan/commands/command"
|
10
|
+
require "ssl_scan/commands/targets"
|
11
|
+
require "ssl_scan/commands/only_certain_ssl"
|
12
|
+
require "ssl_scan/commands/host"
|
13
|
+
|
14
|
+
module SSLScan
|
15
|
+
class Main
|
16
|
+
|
17
|
+
EXIT_SUCCESS = 0
|
18
|
+
EXIT_FAILURE = 1
|
19
|
+
|
20
|
+
WEBSITE = "https://www.testcloud.de"
|
21
|
+
COPYRIGHT = "Copyright (C) John Faucett #{Time.now.year}"
|
22
|
+
|
23
|
+
attr_accessor :options
|
24
|
+
|
25
|
+
def main(argc, argv)
|
26
|
+
@options = self.class.parse_options(argv)
|
27
|
+
|
28
|
+
if options.file
|
29
|
+
command = SSLScan::Commands::Targets.new(options.file)
|
30
|
+
command.execute
|
31
|
+
else
|
32
|
+
valid = true
|
33
|
+
port = 443
|
34
|
+
error_msg = "Host invalid"
|
35
|
+
begin
|
36
|
+
host = argv.last
|
37
|
+
if !host
|
38
|
+
error_msg = "Host not given"
|
39
|
+
valid = false
|
40
|
+
else
|
41
|
+
host_parts = host.split(":")
|
42
|
+
host = host_parts.first
|
43
|
+
port = host_parts.last.to_i if host_parts.last != host
|
44
|
+
::Socket.gethostbyname(host)
|
45
|
+
end
|
46
|
+
rescue ::SocketError => ex
|
47
|
+
error_msg = ex.message
|
48
|
+
valid = false
|
49
|
+
end
|
50
|
+
|
51
|
+
unless valid
|
52
|
+
printf("Error: %s\n", error_msg)
|
53
|
+
exit(EXIT_FAILURE)
|
54
|
+
end
|
55
|
+
|
56
|
+
if (options.only_ssl2 || options.only_ssl3 || options.only_tls1 )
|
57
|
+
command = SSLScan::Commands::OnlyCertainSSL.new(options)
|
58
|
+
command.execute
|
59
|
+
else
|
60
|
+
command = SSLScan::Commands::Host.new(argv.last)
|
61
|
+
command.execute
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
show_certificate(command.results.first.cert)
|
66
|
+
end
|
67
|
+
|
68
|
+
alias_method :run, :main
|
69
|
+
|
70
|
+
def self.show_version_info
|
71
|
+
printf("ssl_scan version %s\n%s\n%s\n", VERSION::STRING, WEBSITE, COPYRIGHT)
|
72
|
+
end
|
73
|
+
|
74
|
+
def show_certificate(cert)
|
75
|
+
printf("SSL Certificate:\n")
|
76
|
+
printf(" Version: %d\n", cert.version)
|
77
|
+
printf(" Serial Number: %s\n", cert.serial.to_s(16))
|
78
|
+
printf(" Signature Algorithm: %s\n", cert.signature_algorithm)
|
79
|
+
printf(" Issuer: %s\n", cert.issuer.to_s)
|
80
|
+
printf(" Not valid before: %s\n", cert.not_before.to_s)
|
81
|
+
printf(" Not valid after: %s\n", cert.not_after.to_s)
|
82
|
+
printf(" Subject: %s\n", cert.subject.to_s)
|
83
|
+
printf(" %s", cert.public_key.to_text)
|
84
|
+
|
85
|
+
# TODO: Implement extensions (see: cert.extensions)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.parse_options(args)
|
89
|
+
options = OpenStruct.new
|
90
|
+
options.file = false
|
91
|
+
options.no_failed = false
|
92
|
+
options.only_ssl2 = false
|
93
|
+
options.only_ssl3 = false
|
94
|
+
options.only_tls1 = false
|
95
|
+
|
96
|
+
opts = OptionParser.new do |opts|
|
97
|
+
opts.banner = "Command: ssl_scan [options] [host:port | host]"
|
98
|
+
|
99
|
+
opts.separator ""
|
100
|
+
opts.separator "Options:"
|
101
|
+
|
102
|
+
# File containing list of hosts to check
|
103
|
+
opts.on( "-t",
|
104
|
+
"--targets FILE",
|
105
|
+
"A file containing a list of hosts to check with syntax ( host | host:port).") do |filename|
|
106
|
+
options.file = filename
|
107
|
+
end
|
108
|
+
|
109
|
+
# List only accepted ciphers
|
110
|
+
opts.on( "--no-failed",
|
111
|
+
"List only accepted ciphers.") do
|
112
|
+
options.no_failed = true
|
113
|
+
end
|
114
|
+
|
115
|
+
opts.on( "--ssl2",
|
116
|
+
"Only check SSLv2 ciphers.") do
|
117
|
+
options.only_ssl2 = true
|
118
|
+
end
|
119
|
+
|
120
|
+
opts.on( "--ssl3",
|
121
|
+
"Only check SSLv3 ciphers.") do
|
122
|
+
options.only_ssl3 = true
|
123
|
+
end
|
124
|
+
|
125
|
+
opts.on( "--tls1",
|
126
|
+
"Only check TLSv1 ciphers.") do
|
127
|
+
options.only_tls1 = true
|
128
|
+
end
|
129
|
+
|
130
|
+
opts.on( "-d",
|
131
|
+
"--debug",
|
132
|
+
"Print any SSL errors to stderr.") do
|
133
|
+
OpenSSL.debug = true
|
134
|
+
end
|
135
|
+
|
136
|
+
opts.on_tail( "-h",
|
137
|
+
"--help",
|
138
|
+
"Display the help text you are now reading.") do
|
139
|
+
puts opts
|
140
|
+
exit(EXIT_SUCCESS)
|
141
|
+
end
|
142
|
+
|
143
|
+
opts.on_tail( "-v",
|
144
|
+
"--version",
|
145
|
+
"Display the program version.") do
|
146
|
+
show_version_info
|
147
|
+
exit(EXIT_SUCCESS)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
opts.parse!(args)
|
153
|
+
options.freeze
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
end
|
data/lib/ssl_scan/scanner.rb
CHANGED
@@ -12,6 +12,7 @@ class Scanner
|
|
12
12
|
|
13
13
|
attr_reader :supported_versions
|
14
14
|
attr_reader :peer_supported_versions
|
15
|
+
attr_reader :results
|
15
16
|
attr_reader :sslv2
|
16
17
|
|
17
18
|
# Initializes the scanner object
|
@@ -70,7 +71,7 @@ class Scanner
|
|
70
71
|
end
|
71
72
|
|
72
73
|
if block_given?
|
73
|
-
yield(ssl_version, cipher_name,
|
74
|
+
yield(ssl_version, cipher_name, alg_length, status, scan_result.cert)
|
74
75
|
end
|
75
76
|
|
76
77
|
end
|
@@ -80,6 +81,7 @@ class Scanner
|
|
80
81
|
psv << :SSLv3 if scan_result.supports_sslv3?
|
81
82
|
psv << :TLSv1 if scan_result.supports_tlsv1?
|
82
83
|
end
|
84
|
+
@results = scan_result
|
83
85
|
scan_result
|
84
86
|
end
|
85
87
|
|
@@ -164,7 +166,11 @@ class Scanner
|
|
164
166
|
'Timeout' => @timeout
|
165
167
|
)
|
166
168
|
rescue ::Exception => e
|
167
|
-
|
169
|
+
if e.kind_of?(Errno::ECONNRESET)
|
170
|
+
return :failed
|
171
|
+
else
|
172
|
+
return :rejected
|
173
|
+
end
|
168
174
|
ensure
|
169
175
|
if scan_client
|
170
176
|
scan_client.close
|
data/lib/ssl_scan/version.rb
CHANGED
data/lib/ssl_scan.rb
CHANGED
data/sslscan.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["jwaterfaucett@gmail.com"]
|
11
11
|
spec.summary = %q{Ruby SSL Scanner}
|
12
12
|
spec.description = %q{An SSL Scanner Library and Utility in pure Ruby}
|
13
|
-
spec.homepage = ""
|
13
|
+
spec.homepage = "https://github.com/jwaterfaucett/ssl_scan"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssl_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Faucett
|
@@ -53,7 +53,10 @@ files:
|
|
53
53
|
- Rakefile
|
54
54
|
- bin/ssl_scan
|
55
55
|
- lib/ssl_scan.rb
|
56
|
-
- lib/ssl_scan/
|
56
|
+
- lib/ssl_scan/commands/command.rb
|
57
|
+
- lib/ssl_scan/commands/host.rb
|
58
|
+
- lib/ssl_scan/commands/only_certain_ssl.rb
|
59
|
+
- lib/ssl_scan/commands/targets.rb
|
57
60
|
- lib/ssl_scan/compat.rb
|
58
61
|
- lib/ssl_scan/exceptions.rb
|
59
62
|
- lib/ssl_scan/io/bidirectional_pipe.rb
|
@@ -62,6 +65,7 @@ files:
|
|
62
65
|
- lib/ssl_scan/io/stream.rb
|
63
66
|
- lib/ssl_scan/io/stream_abstraction.rb
|
64
67
|
- lib/ssl_scan/io/stream_server.rb
|
68
|
+
- lib/ssl_scan/main.rb
|
65
69
|
- lib/ssl_scan/result.rb
|
66
70
|
- lib/ssl_scan/scanner.rb
|
67
71
|
- lib/ssl_scan/socket.rb
|
@@ -80,7 +84,7 @@ files:
|
|
80
84
|
- lib/ssl_scan/sync/thread_safe.rb
|
81
85
|
- lib/ssl_scan/version.rb
|
82
86
|
- sslscan.gemspec
|
83
|
-
homepage:
|
87
|
+
homepage: https://github.com/jwaterfaucett/ssl_scan
|
84
88
|
licenses:
|
85
89
|
- MIT
|
86
90
|
metadata: {}
|
data/lib/ssl_scan/client.rb
DELETED
File without changes
|