rex-socket 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ module Rex
2
+ module Socket
3
+
4
+ # This class exists to abuse the Proxy capabilities in the Net::SSH library to allow the use of Rex::Sockets
5
+ # for the transport layer in Net::SSH. The SSHFactory object will respond to the #open method and create the
6
+ # {Rex::Socket::Tcp}
7
+ class SSHFactory
8
+
9
+ # @!attribute msfraemwork
10
+ # @return [Object] The framework instance object
11
+ attr_accessor :framework
12
+ # @!attribute msfmodule
13
+ # @return [Object] The metasploit module this socket belongs to
14
+ attr_accessor :msfmodule
15
+ # @!attribute proxies
16
+ # @return [String] Any proxies to use for the connection
17
+ attr_accessor :proxies
18
+
19
+ def initialize(framework, msfmodule, proxies)
20
+ @framework = framework
21
+ @msfmodule = msfmodule
22
+ @proxies = proxies
23
+ end
24
+
25
+ # Responds to the proxy setup routine Net::SSH will call when
26
+ # initialising the Transport Layer. This will instead create our
27
+ # {Rex::Socket::Tcp} and tie the socket back to the calling module
28
+ # @param host [String] The host to open the connection to
29
+ # @param port [Fixnum] the port to open the connection on
30
+ # @param options [Hash] the options hash
31
+ def open(host, port, options={})
32
+ socket = Rex::Socket::Tcp.create(
33
+ 'PeerHost' => host,
34
+ 'PeerPort' => port,
35
+ 'Proxies' => proxies,
36
+ 'Context' => {
37
+ 'Msf' => framework,
38
+ 'MsfExploit' => msfmodule
39
+ }
40
+ )
41
+ msfmodule.add_socket(socket) if msfmodule
42
+ socket
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,374 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/socket'
3
+ ###
4
+ #
5
+ # This class provides methods for interacting with an SSL TCP client
6
+ # connection.
7
+ #
8
+ ###
9
+ module Rex::Socket::SslTcp
10
+
11
+ begin
12
+ @@loaded_openssl = false
13
+
14
+ begin
15
+ require 'openssl'
16
+ @@loaded_openssl = true
17
+ require 'openssl/nonblock'
18
+ rescue ::Exception
19
+ end
20
+
21
+
22
+ include Rex::Socket::Tcp
23
+
24
+ ##
25
+ #
26
+ # Factory
27
+ #
28
+ ##
29
+
30
+ #
31
+ # Creates an SSL TCP instance.
32
+ #
33
+ def self.create(hash = {})
34
+ raise RuntimeError, "No OpenSSL support" if not @@loaded_openssl
35
+ hash['SSL'] = true
36
+ self.create_param(Rex::Socket::Parameters.from_hash(hash))
37
+ end
38
+
39
+ #
40
+ # Set the SSL flag to true and call the base class's create_param routine.
41
+ #
42
+ def self.create_param(param)
43
+ param.ssl = true
44
+ Rex::Socket::Tcp.create_param(param)
45
+ end
46
+
47
+ ##
48
+ #
49
+ # Class initialization
50
+ #
51
+ ##
52
+
53
+ #
54
+ # Initializes the SSL socket.
55
+ #
56
+ def initsock(params = nil)
57
+ super
58
+
59
+ # Default to SSLv23 (automatically negotiate)
60
+ version = :SSLv23
61
+
62
+ # Let the caller specify a particular SSL/TLS version
63
+ if params
64
+ case params.ssl_version
65
+ when 'SSL2', :SSLv2
66
+ version = :SSLv2
67
+ # 'TLS' will be the new name for autonegotation with newer versions of OpenSSL
68
+ when 'SSL23', :SSLv23, 'TLS', 'Auto'
69
+ version = :SSLv23
70
+ when 'SSL3', :SSLv3
71
+ version = :SSLv3
72
+ when 'TLS1','TLS1.0', :TLSv1
73
+ version = :TLSv1
74
+ when 'TLS1.1', :TLSv1_1
75
+ version = :TLSv1_1
76
+ when 'TLS1.2', :TLSv1_2
77
+ version = :TLSv1_2
78
+ end
79
+ end
80
+
81
+ # Raise an error if no selected versions are supported
82
+ if ! OpenSSL::SSL::SSLContext::METHODS.include? version
83
+ raise ArgumentError, 'The system OpenSSL does not support the requested SSL/TLS version'
84
+ end
85
+
86
+ # Try intializing the socket with this SSL/TLS version
87
+ # This will throw an exception if it fails
88
+ initsock_with_ssl_version(params, version)
89
+
90
+ # Track the SSL version
91
+ self.ssl_negotiated_version = version
92
+ end
93
+
94
+ def initsock_with_ssl_version(params, version)
95
+ # Build the SSL connection
96
+ self.sslctx = OpenSSL::SSL::SSLContext.new(version)
97
+
98
+ # Configure the SSL context
99
+ # TODO: Allow the user to specify the verify mode callback
100
+ # Valid modes:
101
+ # VERIFY_CLIENT_ONCE
102
+ # VERIFY_FAIL_IF_NO_PEER_CERT
103
+ # VERIFY_NONE
104
+ # VERIFY_PEER
105
+ if params.ssl_verify_mode
106
+ self.sslctx.verify_mode = OpenSSL::SSL.const_get("VERIFY_#{params.ssl_verify_mode}".intern)
107
+ else
108
+ # Could also do this as graceful faildown in case a passed verify_mode is not supported
109
+ self.sslctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
110
+ end
111
+
112
+ self.sslctx.options = OpenSSL::SSL::OP_ALL
113
+
114
+ if params.ssl_cipher
115
+ self.sslctx.ciphers = params.ssl_cipher
116
+ end
117
+
118
+ # Set the verification callback
119
+ self.sslctx.verify_callback = Proc.new do |valid, store|
120
+ self.peer_verified = valid
121
+ true
122
+ end
123
+
124
+ # Tie the context to a socket
125
+ self.sslsock = OpenSSL::SSL::SSLSocket.new(self, self.sslctx)
126
+
127
+ # If peerhost looks like a hostname, set the undocumented 'hostname'
128
+ # attribute on sslsock, which enables the Server Name Indication (SNI)
129
+ # extension
130
+ self.sslsock.hostname = self.peerhost if !Rex::Socket.dotted_ip?(self.peerhost)
131
+
132
+ # Force a negotiation timeout
133
+ begin
134
+ Timeout.timeout(params.timeout) do
135
+ if not allow_nonblock?
136
+ self.sslsock.connect
137
+ else
138
+ begin
139
+ self.sslsock.connect_nonblock
140
+ # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
141
+ rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
142
+ IO::select(nil, nil, nil, 0.10)
143
+ retry
144
+
145
+ # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
146
+ rescue ::Exception => e
147
+ if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
148
+ IO::select( [ self.sslsock ], nil, nil, 0.10 )
149
+ retry
150
+ end
151
+
152
+ if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
153
+ IO::select( nil, [ self.sslsock ], nil, 0.10 )
154
+ retry
155
+ end
156
+
157
+ raise e
158
+ end
159
+ end
160
+ end
161
+
162
+ rescue ::Timeout::Error
163
+ raise Rex::ConnectionTimeout.new(params.peerhost, params.peerport)
164
+ end
165
+ end
166
+
167
+ ##
168
+ #
169
+ # Stream mixin implementations
170
+ #
171
+ ##
172
+
173
+ #
174
+ # Writes data over the SSL socket.
175
+ #
176
+ def write(buf, opts = {})
177
+ return sslsock.write(buf) if not allow_nonblock?
178
+
179
+ total_sent = 0
180
+ total_length = buf.length
181
+ block_size = 16384
182
+ retry_time = 0.5
183
+
184
+ begin
185
+ while( total_sent < total_length )
186
+ s = Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, 0.25 )
187
+ if( s == nil || s[0] == nil )
188
+ next
189
+ end
190
+ data = buf[total_sent, block_size]
191
+ sent = sslsock.write_nonblock( data )
192
+ if sent > 0
193
+ total_sent += sent
194
+ end
195
+ end
196
+
197
+ rescue ::IOError, ::Errno::EPIPE
198
+ return nil
199
+
200
+ # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
201
+ rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
202
+ # Sleep for a half a second, or until we can write again
203
+ Rex::ThreadSafe.select( nil, [ self.sslsock ], nil, retry_time )
204
+ # Decrement the block size to handle full sendQs better
205
+ block_size = 1024
206
+ # Try to write the data again
207
+ retry
208
+
209
+ # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
210
+ rescue ::Exception => e
211
+ if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
212
+ IO::select( [ self.sslsock ], nil, nil, retry_time )
213
+ retry
214
+ end
215
+
216
+ if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
217
+ IO::select( nil, [ self.sslsock ], nil, retry_time )
218
+ retry
219
+ end
220
+
221
+ # Another form of SSL error, this is always fatal
222
+ if e.kind_of?(::OpenSSL::SSL::SSLError)
223
+ return nil
224
+ end
225
+
226
+ # Bubble the event up to the caller otherwise
227
+ raise e
228
+ end
229
+
230
+ total_sent
231
+ end
232
+
233
+ #
234
+ # Reads data from the SSL socket.
235
+ #
236
+ def read(length = nil, opts = {})
237
+ if not allow_nonblock?
238
+ length = 16384 unless length
239
+ begin
240
+ return sslsock.sysread(length)
241
+ rescue ::IOError, ::Errno::EPIPE, ::OpenSSL::SSL::SSLError
242
+ return nil
243
+ end
244
+ return
245
+ end
246
+
247
+
248
+ begin
249
+ while true
250
+ s = Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
251
+ if( s == nil || s[0] == nil )
252
+ next
253
+ end
254
+ return sslsock.read_nonblock( length )
255
+ end
256
+
257
+ rescue ::IOError, ::Errno::EPIPE
258
+ return nil
259
+
260
+ # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
261
+ rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
262
+ # Sleep for a tenth a second, or until we can read again
263
+ Rex::ThreadSafe.select( [ self.sslsock ], nil, nil, 0.10 )
264
+ # Decrement the block size to handle full sendQs better
265
+ block_size = 1024
266
+ # Try to write the data again
267
+ retry
268
+
269
+ # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
270
+ rescue ::Exception => e
271
+ if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
272
+ IO::select( [ self.sslsock ], nil, nil, 0.5 )
273
+ retry
274
+ end
275
+
276
+ if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
277
+ IO::select( nil, [ self.sslsock ], nil, 0.5 )
278
+ retry
279
+ end
280
+
281
+ # Another form of SSL error, this is always fatal
282
+ if e.kind_of?(::OpenSSL::SSL::SSLError)
283
+ return nil
284
+ end
285
+
286
+ raise e
287
+ end
288
+
289
+ end
290
+
291
+
292
+ #
293
+ # Closes the SSL socket.
294
+ #
295
+ def close
296
+ sslsock.close rescue nil
297
+ super
298
+ end
299
+
300
+ #
301
+ # Ignore shutdown requests
302
+ #
303
+ def shutdown(how=0)
304
+ # Calling shutdown() on an SSL socket can lead to bad things
305
+ # Cause of http://metasploit.com/dev/trac/ticket/102
306
+ end
307
+
308
+ #
309
+ # Access to peer cert
310
+ #
311
+ def peer_cert
312
+ sslsock.peer_cert if sslsock
313
+ end
314
+
315
+ #
316
+ # Access to peer cert chain
317
+ #
318
+ def peer_cert_chain
319
+ sslsock.peer_cert_chain if sslsock
320
+ end
321
+
322
+ #
323
+ # Access to the current cipher
324
+ #
325
+ def cipher
326
+ sslsock.cipher if sslsock
327
+ end
328
+
329
+ #
330
+ # Prevent a sysread from the bare socket
331
+ #
332
+ def sysread(*args)
333
+ raise RuntimeError, "Invalid sysread() call on SSL socket"
334
+ end
335
+
336
+ #
337
+ # Prevent a sysread from the bare socket
338
+ #
339
+ def syswrite(*args)
340
+ raise RuntimeError, "Invalid syswrite() call on SSL socket"
341
+ end
342
+
343
+ #
344
+ # This flag determines whether to use the non-blocking openssl
345
+ # API calls when they are available. This is still buggy on
346
+ # Linux/Mac OS X, but is required on Windows
347
+ #
348
+ def allow_nonblock?
349
+ avail = self.sslsock.respond_to?(:accept_nonblock)
350
+ if avail and Rex::Compat.is_windows
351
+ return true
352
+ end
353
+ false
354
+ end
355
+
356
+ attr_reader :peer_verified # :nodoc:
357
+ attr_reader :ssl_negotiated_version # :nodoc:
358
+ attr_accessor :sslsock, :sslctx, :sslhash # :nodoc:
359
+
360
+ def type?
361
+ return 'tcp-ssl'
362
+ end
363
+
364
+ protected
365
+
366
+ attr_writer :peer_verified # :nodoc:
367
+ attr_writer :ssl_negotiated_version # :nodoc:
368
+
369
+
370
+ rescue LoadError
371
+ end
372
+
373
+ end
374
+
@@ -0,0 +1,220 @@
1
+ # -*- coding: binary -*-
2
+ require 'rex/socket'
3
+ require 'rex/socket/tcp_server'
4
+ require 'rex/io/stream_server'
5
+ require 'rex/socket/x509_certificate'
6
+
7
+ ###
8
+ #
9
+ # This class provides methods for interacting with an SSL wrapped TCP server. It
10
+ # implements the StreamServer IO interface.
11
+ #
12
+ ###
13
+ module Rex::Socket::SslTcpServer
14
+
15
+ @@loaded_openssl = false
16
+
17
+ begin
18
+ require 'openssl'
19
+ @@loaded_openssl = true
20
+ require 'openssl/nonblock'
21
+ rescue ::Exception
22
+ end
23
+
24
+ include Rex::Socket::TcpServer
25
+
26
+ ##
27
+ #
28
+ # Factory
29
+ #
30
+ ##
31
+
32
+ def self.create(hash = {})
33
+ hash['Proto'] = 'tcp'
34
+ hash['Server'] = true
35
+ hash['SSL'] = true
36
+ self.create_param(Rex::Socket::Parameters.from_hash(hash))
37
+ end
38
+
39
+ #
40
+ # Wrapper around the base class' creation method that automatically sets
41
+ # the parameter's protocol to TCP and sets the server flag to true.
42
+ #
43
+ def self.create_param(param)
44
+ param.proto = 'tcp'
45
+ param.server = true
46
+ param.ssl = true
47
+ Rex::Socket.create_param(param)
48
+ end
49
+
50
+ def initsock(params = nil)
51
+ raise RuntimeError, 'No OpenSSL support' unless @@loaded_openssl
52
+
53
+ if params && params.sslctx && params.sslctx.kind_of?(OpenSSL::SSL::SSLContext)
54
+ self.sslctx = params.sslctx
55
+ else
56
+ self.sslctx = makessl(params)
57
+ end
58
+
59
+ super
60
+ end
61
+
62
+ # (see TcpServer#accept)
63
+ def accept(opts = {})
64
+ sock = super()
65
+ return if not sock
66
+
67
+ begin
68
+ ssl = OpenSSL::SSL::SSLSocket.new(sock, self.sslctx)
69
+
70
+ if not allow_nonblock?(ssl)
71
+ ssl.accept
72
+ else
73
+ begin
74
+ ssl.accept_nonblock
75
+
76
+ # Ruby 1.8.7 and 1.9.0/1.9.1 uses a standard Errno
77
+ rescue ::Errno::EAGAIN, ::Errno::EWOULDBLOCK
78
+ IO::select(nil, nil, nil, 0.10)
79
+ retry
80
+
81
+ # Ruby 1.9.2+ uses IO::WaitReadable/IO::WaitWritable
82
+ rescue ::Exception => e
83
+ if ::IO.const_defined?('WaitReadable') and e.kind_of?(::IO::WaitReadable)
84
+ IO::select( [ ssl ], nil, nil, 0.10 )
85
+ retry
86
+ end
87
+
88
+ if ::IO.const_defined?('WaitWritable') and e.kind_of?(::IO::WaitWritable)
89
+ IO::select( nil, [ ssl ], nil, 0.10 )
90
+ retry
91
+ end
92
+
93
+ raise e
94
+ end
95
+ end
96
+
97
+ sock.extend(Rex::Socket::SslTcp)
98
+ sock.sslsock = ssl
99
+ sock.sslctx = self.sslctx
100
+
101
+ return sock
102
+
103
+ rescue ::OpenSSL::SSL::SSLError
104
+ sock.close
105
+ nil
106
+ end
107
+ end
108
+
109
+ #
110
+ # Parse a certificate in unified PEM format that contains a private key and
111
+ # one or more certificates. The first certificate is the primary, while any
112
+ # additional certificates are treated as intermediary certificates. This emulates
113
+ # the behavior of web servers like nginx.
114
+ #
115
+ # @param [String] ssl_cert
116
+ # @return [String, String, Array]
117
+ def self.ssl_parse_pem(ssl_cert)
118
+ Rex::Socket::X509Certificate.parse_pem(ssl_cert)
119
+ end
120
+
121
+ #
122
+ # Shim for the ssl_parse_pem module method
123
+ #
124
+ def ssl_parse_pem(ssl_cert)
125
+ Rex::Socket::SslTcpServer.ssl_parse_pem(ssl_cert)
126
+ end
127
+
128
+ #
129
+ # Generate a realistic-looking but obstensibly fake SSL
130
+ # certificate. This matches a typical "snakeoil" cert.
131
+ #
132
+ # @return [String, String, Array]
133
+ def self.ssl_generate_certificate
134
+ yr = 24*3600*365
135
+ vf = Time.at(Time.now.to_i - rand(yr * 3) - yr)
136
+ vt = Time.at(vf.to_i + (10 * yr))
137
+ cn = Rex::Text.rand_text_alpha_lower(rand(8)+2)
138
+ key = OpenSSL::PKey::RSA.new(2048){ }
139
+ cert = OpenSSL::X509::Certificate.new
140
+ cert.version = 2
141
+ cert.serial = (rand(0xFFFFFFFF) << 32) + rand(0xFFFFFFFF)
142
+ cert.subject = OpenSSL::X509::Name.new([["CN", cn]])
143
+ cert.issuer = OpenSSL::X509::Name.new([["CN", cn]])
144
+ cert.not_before = vf
145
+ cert.not_after = vt
146
+ cert.public_key = key.public_key
147
+
148
+ ef = OpenSSL::X509::ExtensionFactory.new(nil,cert)
149
+ cert.extensions = [
150
+ ef.create_extension("basicConstraints","CA:FALSE")
151
+ ]
152
+ ef.issuer_certificate = cert
153
+
154
+ cert.sign(key, OpenSSL::Digest::SHA256.new)
155
+
156
+ [key, cert, nil]
157
+ end
158
+
159
+ #
160
+ # Shim for the ssl_generate_certificate module method
161
+ #
162
+ def ssl_generate_certificate
163
+ Rex::Socket::SslTcpServer.ssl_generate_certificate
164
+ end
165
+
166
+ #
167
+ # Create a new ssl context. If +ssl_cert+ is not given, generates a new
168
+ # key and a leaf certificate with random values.
169
+ #
170
+ # @param [Rex::Socket::Parameters] params
171
+ # @return [::OpenSSL::SSL::SSLContext]
172
+ def makessl(params)
173
+
174
+ if params.ssl_cert
175
+ key, cert, chain = ssl_parse_pem(params.ssl_cert)
176
+ else
177
+ key, cert, chain = ssl_generate_certificate
178
+ end
179
+
180
+ ctx = OpenSSL::SSL::SSLContext.new()
181
+ ctx.key = key
182
+ ctx.cert = cert
183
+ ctx.extra_chain_cert = chain
184
+ ctx.options = 0
185
+
186
+ if params.ssl_cipher
187
+ ctx.ciphers = params.ssl_cipher
188
+ end
189
+
190
+ # Older versions of OpenSSL do not export the OP_NO_COMPRESSION symbol
191
+ if defined?(OpenSSL::SSL::OP_NO_COMPRESSION)
192
+ # enable/disable the SSL/TLS-level compression
193
+ if params.ssl_compression
194
+ ctx.options &= ~OpenSSL::SSL::OP_NO_COMPRESSION
195
+ else
196
+ ctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
197
+ end
198
+ end
199
+
200
+ ctx.session_id_context = Rex::Text.rand_text(16)
201
+
202
+ return ctx
203
+ end
204
+
205
+ #
206
+ # This flag determines whether to use the non-blocking openssl
207
+ # API calls when they are available. This is still buggy on
208
+ # Linux/Mac OS X, but is required on Windows
209
+ #
210
+ def allow_nonblock?(sock=self.sock)
211
+ avail = sock.respond_to?(:accept_nonblock)
212
+ if avail and Rex::Compat.is_windows
213
+ return true
214
+ end
215
+ false
216
+ end
217
+
218
+ attr_accessor :sslctx
219
+ end
220
+