ssl_scan 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/bin/ssl_scan +4 -0
- data/lib/ssl_scan/client.rb +0 -0
- data/lib/ssl_scan/compat.rb +388 -0
- data/lib/ssl_scan/exceptions.rb +274 -0
- data/lib/ssl_scan/io/bidirectional_pipe.rb +161 -0
- data/lib/ssl_scan/io/datagram_abstraction.rb +35 -0
- data/lib/ssl_scan/io/ring_buffer.rb +369 -0
- data/lib/ssl_scan/io/stream.rb +312 -0
- data/lib/ssl_scan/io/stream_abstraction.rb +209 -0
- data/lib/ssl_scan/io/stream_server.rb +221 -0
- data/lib/ssl_scan/result.rb +165 -0
- data/lib/ssl_scan/scanner.rb +241 -0
- data/lib/ssl_scan/socket/comm/local.rb +526 -0
- data/lib/ssl_scan/socket/comm.rb +120 -0
- data/lib/ssl_scan/socket/ip.rb +131 -0
- data/lib/ssl_scan/socket/parameters.rb +363 -0
- data/lib/ssl_scan/socket/range_walker.rb +470 -0
- data/lib/ssl_scan/socket/ssl_tcp.rb +345 -0
- data/lib/ssl_scan/socket/ssl_tcp_server.rb +188 -0
- data/lib/ssl_scan/socket/subnet_walker.rb +76 -0
- data/lib/ssl_scan/socket/switch_board.rb +289 -0
- data/lib/ssl_scan/socket/tcp.rb +79 -0
- data/lib/ssl_scan/socket/tcp_server.rb +67 -0
- data/lib/ssl_scan/socket/udp.rb +165 -0
- data/lib/ssl_scan/socket.rb +773 -0
- data/lib/ssl_scan/sync/thread_safe.rb +83 -0
- data/lib/ssl_scan/version.rb +9 -0
- data/lib/ssl_scan.rb +11 -0
- data/sslscan.gemspec +23 -0
- metadata +107 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'ssl_scan/socket'
|
3
|
+
|
4
|
+
###
|
5
|
+
#
|
6
|
+
# This class provides methods for interacting with a IP socket.
|
7
|
+
#
|
8
|
+
###
|
9
|
+
module SSLScan::Socket::Ip
|
10
|
+
|
11
|
+
include SSLScan::Socket
|
12
|
+
|
13
|
+
##
|
14
|
+
#
|
15
|
+
# Factory
|
16
|
+
#
|
17
|
+
##
|
18
|
+
|
19
|
+
#
|
20
|
+
# Creates the client using the supplied hash.
|
21
|
+
#
|
22
|
+
def self.create(hash = {})
|
23
|
+
hash['Proto'] = 'ip'
|
24
|
+
self.create_param(SSLScan::Socket::Parameters.from_hash(hash))
|
25
|
+
end
|
26
|
+
|
27
|
+
#
|
28
|
+
# Wrapper around the base socket class' creation method that automatically
|
29
|
+
# sets the parameter's protocol to IP.
|
30
|
+
#
|
31
|
+
def self.create_param(param)
|
32
|
+
param.proto = 'ip'
|
33
|
+
SSLScan::Socket.create_param(param)
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
#
|
38
|
+
# IP connected state methods
|
39
|
+
#
|
40
|
+
##
|
41
|
+
|
42
|
+
#
|
43
|
+
# Write the supplied datagram to the connected IP socket.
|
44
|
+
#
|
45
|
+
def write(gram)
|
46
|
+
raise RuntimeError, "IP sockets must use sendto(), not write()"
|
47
|
+
end
|
48
|
+
|
49
|
+
alias put write
|
50
|
+
|
51
|
+
#
|
52
|
+
# Read a datagram from the IP socket.
|
53
|
+
#
|
54
|
+
def read(length = 65535)
|
55
|
+
raise RuntimeError, "IP sockets must use recvfrom(), not read()"
|
56
|
+
end
|
57
|
+
|
58
|
+
##
|
59
|
+
#
|
60
|
+
# IP non-connected state methods
|
61
|
+
#
|
62
|
+
##
|
63
|
+
|
64
|
+
#
|
65
|
+
# Sends a datagram to the supplied host:port with optional flags.
|
66
|
+
#
|
67
|
+
def sendto(gram, peerhost, flags = 0)
|
68
|
+
dest = ::Socket.pack_sockaddr_in(0, peerhost)
|
69
|
+
|
70
|
+
# Some BSDs require byteswap for len and offset
|
71
|
+
if(
|
72
|
+
SSLScan::Compat.is_freebsd or
|
73
|
+
SSLScan::Compat.is_netbsd or
|
74
|
+
SSLScan::Compat.is_bsdi or
|
75
|
+
SSLScan::Compat.is_macosx
|
76
|
+
)
|
77
|
+
gram=gram.dup
|
78
|
+
gram[2,2]=gram[2,2].unpack("n").pack("s")
|
79
|
+
gram[6,2]=gram[6,2].unpack("n").pack("s")
|
80
|
+
end
|
81
|
+
|
82
|
+
begin
|
83
|
+
send(gram, flags, dest)
|
84
|
+
rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL,::Errno::EADDRNOTAVAIL
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Receives a datagram and returns the data and host of the requestor
|
92
|
+
# as [ data, host ].
|
93
|
+
#
|
94
|
+
def recvfrom(length = 65535, timeout=def_read_timeout)
|
95
|
+
begin
|
96
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
97
|
+
(rv[0]) and (rv[0][0] == fd)
|
98
|
+
)
|
99
|
+
data, saddr = super(length)
|
100
|
+
af, host = SSLScan::Socket.from_sockaddr(saddr)
|
101
|
+
|
102
|
+
return [ data, host ]
|
103
|
+
else
|
104
|
+
return [ '', nil ]
|
105
|
+
end
|
106
|
+
rescue Exception
|
107
|
+
return [ '', nil ]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# Calls recvfrom and only returns the data
|
113
|
+
#
|
114
|
+
def get(timeout=nil)
|
115
|
+
data, saddr = recvfrom(65535, timeout)
|
116
|
+
return data
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# The default number of seconds to wait for a read operation to timeout.
|
121
|
+
#
|
122
|
+
def def_read_timeout
|
123
|
+
10
|
124
|
+
end
|
125
|
+
|
126
|
+
def type?
|
127
|
+
return 'ip'
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
@@ -0,0 +1,363 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
require 'ssl_scan/socket'
|
3
|
+
|
4
|
+
###
|
5
|
+
#
|
6
|
+
# This class represents the set of parameters that are used to create
|
7
|
+
# a socket, whether it be a server or client socket.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# nsock = SSLScan::Socket::Tcp.create(
|
11
|
+
# 'PeerHost' => opts['RHOST'] || rhost,
|
12
|
+
# 'PeerPort' => (opts['RPORT'] || rport).to_i,
|
13
|
+
# 'LocalHost' => opts['CHOST'] || chost || "0.0.0.0",
|
14
|
+
# 'LocalPort' => (opts['CPORT'] || cport || 0).to_i,
|
15
|
+
# 'SSL' => dossl,
|
16
|
+
# 'SSLVersion'=> opts['SSLVersion'] || ssl_version,
|
17
|
+
# 'Proxies' => proxies,
|
18
|
+
# 'Timeout' => (opts['ConnectTimeout'] || connect_timeout || 10).to_i,
|
19
|
+
# 'Context' =>
|
20
|
+
# {
|
21
|
+
# 'Msf' => framework,
|
22
|
+
# 'MsfExploit' => self,
|
23
|
+
# })
|
24
|
+
#
|
25
|
+
###
|
26
|
+
class SSLScan::Socket::Parameters
|
27
|
+
|
28
|
+
##
|
29
|
+
#
|
30
|
+
# Factory
|
31
|
+
#
|
32
|
+
##
|
33
|
+
|
34
|
+
#
|
35
|
+
# Creates an instance of the Parameters class using the supplied hash.
|
36
|
+
#
|
37
|
+
def self.from_hash(hash)
|
38
|
+
return self.new(hash)
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
#
|
43
|
+
# Constructor
|
44
|
+
#
|
45
|
+
##
|
46
|
+
|
47
|
+
#
|
48
|
+
# Initializes the attributes from the supplied hash. The following hash
|
49
|
+
# keys can be specified.
|
50
|
+
#
|
51
|
+
# @option hash [String] 'PeerHost' The remote host to connect to
|
52
|
+
# @option hash [String] 'PeerAddr' (alias for 'PeerHost')
|
53
|
+
# @option hash [Fixnum] 'PeerPort' The remote port to connect to
|
54
|
+
# @option hash [String] 'LocalHost' The local host to communicate from, if any
|
55
|
+
# @option hash [String] 'LocalPort' The local port to communicate from, if any
|
56
|
+
# @option hash [Bool] 'Bool' Create a bare socket
|
57
|
+
# @option hash [Bool] 'Server' Whether or not this should be a server
|
58
|
+
# @option hash [Bool] 'SSL' Whether or not SSL should be used
|
59
|
+
# @option hash [String] 'SSLVersion' Specify SSL2, SSL3, or TLS1 (SSL3 is
|
60
|
+
# default)
|
61
|
+
# @option hash [String] 'SSLCert' A file containing an SSL certificate (for
|
62
|
+
# server sockets)
|
63
|
+
# @option hash [String] 'SSLCipher' see {#ssl_cipher}
|
64
|
+
# @option hash [Bool] 'SSLCompression' enable SSL-level compression where available
|
65
|
+
# @option hash [String] 'SSLVerifyMode' SSL certificate verification
|
66
|
+
# mechanism. One of 'NONE' (default), 'CLIENT_ONCE', 'FAIL_IF_NO_PEER_CERT ', 'PEER'
|
67
|
+
# @option hash [String] 'Proxies' List of proxies to use.
|
68
|
+
# @option hash [String] 'Proto' The underlying protocol to use.
|
69
|
+
# @option hash [String] 'IPv6' Force the use of IPv6.
|
70
|
+
# @option hash [String] 'Comm' The underlying {Comm} object to use to create
|
71
|
+
# the socket for this parameter set.
|
72
|
+
# @option hash [Hash] 'Context' A context hash that can allow users of
|
73
|
+
# this parameter class instance to determine who is responsible for
|
74
|
+
# requesting that a socket be created.
|
75
|
+
# @option hash [String] 'Retries' The number of times a connection should be
|
76
|
+
# retried.
|
77
|
+
# @option hash [Fixnum] 'Timeout' The number of seconds before a connection
|
78
|
+
# should time out
|
79
|
+
def initialize(hash)
|
80
|
+
if (hash['PeerHost'])
|
81
|
+
self.peerhost = hash['PeerHost']
|
82
|
+
elsif (hash['PeerAddr'])
|
83
|
+
self.peerhost = hash['PeerAddr']
|
84
|
+
else
|
85
|
+
self.peerhost = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
if (hash['LocalHost'])
|
89
|
+
self.localhost = hash['LocalHost']
|
90
|
+
elsif (hash['LocalAddr'])
|
91
|
+
self.localhost = hash['LocalAddr']
|
92
|
+
else
|
93
|
+
self.localhost = '0.0.0.0'
|
94
|
+
end
|
95
|
+
|
96
|
+
if (hash['PeerPort'])
|
97
|
+
self.peerport = hash['PeerPort'].to_i
|
98
|
+
else
|
99
|
+
self.peerport = 0
|
100
|
+
end
|
101
|
+
|
102
|
+
if (hash['LocalPort'])
|
103
|
+
self.localport = hash['LocalPort'].to_i
|
104
|
+
else
|
105
|
+
self.localport = 0
|
106
|
+
end
|
107
|
+
|
108
|
+
if (hash['Bare'])
|
109
|
+
self.bare = hash['Bare']
|
110
|
+
else
|
111
|
+
self.bare = false
|
112
|
+
end
|
113
|
+
|
114
|
+
if (hash['SSL'] and hash['SSL'].to_s =~ /^(t|y|1)/i)
|
115
|
+
self.ssl = true
|
116
|
+
else
|
117
|
+
self.ssl = false
|
118
|
+
end
|
119
|
+
|
120
|
+
supported_ssl_versions = ['SSL2', 'SSL23', 'TLS1', 'SSL3', :SSLv2, :SSLv3, :SSLv23, :TLSv1]
|
121
|
+
if (hash['SSLVersion'] and supported_ssl_versions.include? hash['SSLVersion'])
|
122
|
+
self.ssl_version = hash['SSLVersion']
|
123
|
+
end
|
124
|
+
|
125
|
+
supported_ssl_verifiers = %W{CLIENT_ONCE FAIL_IF_NO_PEER_CERT NONE PEER}
|
126
|
+
if (hash['SSLVerifyMode'] and supported_ssl_verifiers.include? hash['SSLVerifyMode'])
|
127
|
+
self.ssl_verify_mode = hash['SSLVerifyMode']
|
128
|
+
end
|
129
|
+
|
130
|
+
if hash['SSLCompression']
|
131
|
+
self.ssl_compression = hash['SSLCompression']
|
132
|
+
end
|
133
|
+
|
134
|
+
if (hash['SSLCipher'])
|
135
|
+
self.ssl_cipher = hash['SSLCipher']
|
136
|
+
end
|
137
|
+
|
138
|
+
if (hash['SSLCert'] and ::File.file?(hash['SSLCert']))
|
139
|
+
begin
|
140
|
+
self.ssl_cert = ::File.read(hash['SSLCert'])
|
141
|
+
rescue ::Exception => e
|
142
|
+
elog("Failed to read cert: #{e.class}: #{e}", LogSource)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
if hash['Proxies']
|
147
|
+
self.proxies = hash['Proxies'].split('-').map{|a| a.strip}.map{|a| a.split(':').map{|b| b.strip}}
|
148
|
+
end
|
149
|
+
|
150
|
+
# The protocol this socket will be using
|
151
|
+
if (hash['Proto'])
|
152
|
+
self.proto = hash['Proto'].downcase
|
153
|
+
else
|
154
|
+
self.proto = 'tcp'
|
155
|
+
end
|
156
|
+
|
157
|
+
# Whether or not the socket should be a server
|
158
|
+
self.server = hash['Server'] || false
|
159
|
+
|
160
|
+
# The communication subsystem to use to create the socket
|
161
|
+
self.comm = hash['Comm']
|
162
|
+
|
163
|
+
# The context that was passed in, if any.
|
164
|
+
self.context = hash['Context'] || {}
|
165
|
+
|
166
|
+
# If no comm was supplied, try to use the comm that is best fit to
|
167
|
+
# handle the provided host based on the current routing table.
|
168
|
+
if( self.server )
|
169
|
+
if (self.comm == nil and self.localhost)
|
170
|
+
self.comm = SSLScan::Socket::SwitchBoard.best_comm(self.localhost)
|
171
|
+
end
|
172
|
+
else
|
173
|
+
if (self.comm == nil and self.peerhost)
|
174
|
+
self.comm = SSLScan::Socket::SwitchBoard.best_comm(self.peerhost)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# If we still haven't found a comm, we default to the local comm.
|
179
|
+
self.comm = SSLScan::Socket::Comm::Local if (self.comm == nil)
|
180
|
+
|
181
|
+
# If we are a UDP server, turn off the server flag as it was only set when
|
182
|
+
# creating the UDP socket in order to avail of the switch board above.
|
183
|
+
if( self.server and self.proto == 'udp' )
|
184
|
+
self.server = false
|
185
|
+
end
|
186
|
+
|
187
|
+
# The number of connection retries to make (client only)
|
188
|
+
if hash['Retries']
|
189
|
+
self.retries = hash['Retries'].to_i
|
190
|
+
else
|
191
|
+
self.retries = 0
|
192
|
+
end
|
193
|
+
|
194
|
+
# The number of seconds before a connect attempt times out (client only)
|
195
|
+
if hash['Timeout']
|
196
|
+
self.timeout = hash['Timeout'].to_i
|
197
|
+
else
|
198
|
+
self.timeout = 5
|
199
|
+
end
|
200
|
+
|
201
|
+
# Whether to force IPv6 addressing
|
202
|
+
self.v6 = hash['IPv6'] || false
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
#
|
207
|
+
# Conditionals
|
208
|
+
#
|
209
|
+
##
|
210
|
+
|
211
|
+
#
|
212
|
+
# Returns true if this represents parameters for a server.
|
213
|
+
#
|
214
|
+
def server?
|
215
|
+
return (server == true)
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# Returns true if this represents parameters for a client.
|
220
|
+
#
|
221
|
+
def client?
|
222
|
+
return (server == false)
|
223
|
+
end
|
224
|
+
|
225
|
+
#
|
226
|
+
# Returns true if the protocol for the parameters is TCP.
|
227
|
+
#
|
228
|
+
def tcp?
|
229
|
+
return (proto == 'tcp')
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# Returns true if the protocol for the parameters is UDP.
|
234
|
+
#
|
235
|
+
def udp?
|
236
|
+
return (proto == 'udp')
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Returns true if the protocol for the parameters is IP.
|
241
|
+
#
|
242
|
+
def ip?
|
243
|
+
return (proto == 'ip')
|
244
|
+
end
|
245
|
+
|
246
|
+
#
|
247
|
+
# Returns true if the socket is a bare socket that does not inherit from
|
248
|
+
# any extended Rex classes.
|
249
|
+
#
|
250
|
+
def bare?
|
251
|
+
return (bare == true)
|
252
|
+
end
|
253
|
+
|
254
|
+
#
|
255
|
+
# Returns true if SSL has been requested.
|
256
|
+
#
|
257
|
+
def ssl?
|
258
|
+
return ssl
|
259
|
+
end
|
260
|
+
|
261
|
+
#
|
262
|
+
# Returns true if IPv6 has been enabled
|
263
|
+
#
|
264
|
+
def v6?
|
265
|
+
return v6
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
##
|
270
|
+
#
|
271
|
+
# Attributes
|
272
|
+
#
|
273
|
+
##
|
274
|
+
|
275
|
+
# The remote host information, equivalent to the PeerHost parameter hash
|
276
|
+
# key.
|
277
|
+
# @return [String]
|
278
|
+
attr_accessor :peerhost
|
279
|
+
|
280
|
+
# The remote port. Equivalent to the PeerPort parameter hash key.
|
281
|
+
# @return [Fixnum]
|
282
|
+
attr_accessor :peerport
|
283
|
+
|
284
|
+
# The local host. Equivalent to the LocalHost parameter hash key.
|
285
|
+
# @return [String]
|
286
|
+
attr_accessor :localhost
|
287
|
+
|
288
|
+
# The local port. Equivalent to the LocalPort parameter hash key.
|
289
|
+
# @return [Fixnum]
|
290
|
+
attr_accessor :localport
|
291
|
+
|
292
|
+
# The protocol to to use, such as TCP. Equivalent to the Proto parameter
|
293
|
+
# hash key.
|
294
|
+
# @return [String]
|
295
|
+
attr_accessor :proto
|
296
|
+
|
297
|
+
# Whether or not this is a server. Equivalent to the Server parameter
|
298
|
+
# hash key.
|
299
|
+
# @return [Bool]
|
300
|
+
attr_accessor :server
|
301
|
+
|
302
|
+
# The {Comm} instance that should be used to create the underlying socket.
|
303
|
+
# @return [Comm]
|
304
|
+
attr_accessor :comm
|
305
|
+
|
306
|
+
# The context hash that was passed in to the structure. (default: {})
|
307
|
+
# @return [Hash]
|
308
|
+
attr_accessor :context
|
309
|
+
|
310
|
+
# The number of attempts that should be made.
|
311
|
+
# @return [Fixnum]
|
312
|
+
attr_accessor :retries
|
313
|
+
|
314
|
+
# The number of seconds before a connection attempt should time out.
|
315
|
+
# @return [Fixnum]
|
316
|
+
attr_accessor :timeout
|
317
|
+
|
318
|
+
# Whether or not this is a bare (non-extended) socket instance that should
|
319
|
+
# be created.
|
320
|
+
# @return [Bool]
|
321
|
+
attr_accessor :bare
|
322
|
+
|
323
|
+
# Whether or not SSL should be used to wrap the connection.
|
324
|
+
# @return [Bool]
|
325
|
+
attr_accessor :ssl
|
326
|
+
|
327
|
+
# What version of SSL to use (SSL2, SSL3, SSL23, TLS1)
|
328
|
+
# @return [String,Symbol]
|
329
|
+
attr_accessor :ssl_version
|
330
|
+
|
331
|
+
# What specific SSL Cipher(s) to use, may be a string containing the cipher
|
332
|
+
# name or an array of strings containing cipher names e.g.
|
333
|
+
# ["DHE-RSA-AES256-SHA", "DHE-DSS-AES256-SHA"]
|
334
|
+
# @return [String,Array]
|
335
|
+
attr_accessor :ssl_cipher
|
336
|
+
|
337
|
+
# The SSL certificate, in pem format, stored as a string. See
|
338
|
+
# {SSLScan::Socket::SslTcpServer#makessl}
|
339
|
+
# @return [String]
|
340
|
+
attr_accessor :ssl_cert
|
341
|
+
|
342
|
+
# Enables SSL/TLS-level compression
|
343
|
+
# @return [Bool]
|
344
|
+
attr_accessor :ssl_compression
|
345
|
+
|
346
|
+
#
|
347
|
+
# The SSL context verification mechanism
|
348
|
+
#
|
349
|
+
attr_accessor :ssl_verify_mode
|
350
|
+
|
351
|
+
#
|
352
|
+
# Whether we should use IPv6
|
353
|
+
# @return [Bool]
|
354
|
+
attr_accessor :v6
|
355
|
+
|
356
|
+
|
357
|
+
# List of proxies to use
|
358
|
+
# @return [String]
|
359
|
+
attr_accessor :proxies
|
360
|
+
|
361
|
+
alias peeraddr peerhost
|
362
|
+
alias localaddr localhost
|
363
|
+
end
|