@@ -42,9 +42,14 @@ class Client
42
42
@@ext_hash = { }
43
43
44
44
#
45
- # Cached SSL certificate (required to scale)
45
+ # Cached SSL context (required to scale)
46
46
#
47
- @@ssl_ctx = nil
47
+ @@ssl_cert_info = nil
48
+
49
+ #
50
+ # Cached SSL certificate
51
+ #
52
+ @@ssl_cached_cert = nil
48
53
49
54
#
50
55
# Mutex to synchronize class-wide operations
@@ -116,9 +121,21 @@ def init_meterpreter(sock,opts={})
116
121
117
122
self . response_timeout = opts [ :timeout ] || self . class . default_timeout
118
123
self . send_keepalives = true
124
+
125
+ # TODO: Clarify why we don't allow unicode to be set in initial options
119
126
# self.encode_unicode = opts.has_key?(:encode_unicode) ? opts[:encode_unicode] : true
120
127
self . encode_unicode = false
121
128
129
+ # The SSL certificate is being passed down as a file path
130
+ if opts [ :ssl_cert ]
131
+ if ! File . exists? opts [ :ssl_cert ]
132
+ elog ( "SSL certificate at #{ opts [ :ssl_cert ] } does not exist and will be ignored" )
133
+ else
134
+ # Load the certificate the same way that SslTcpServer does it
135
+ self . ssl_cert = ::File . read ( opts [ :ssl_cert ] )
136
+ end
137
+ end
138
+
122
139
if opts [ :passive_dispatcher ]
123
140
initialize_passive_dispatcher
124
141
@@ -200,68 +217,48 @@ def swap_sock_ssl_to_plain
200
217
end
201
218
202
219
def generate_ssl_context
220
+
221
+ # Initialize a null context
222
+ ctx = nil
223
+
224
+ # Synchronize to prevent race conditions
203
225
@@ssl_mutex . synchronize do
204
- if not @@ssl_ctx
205
-
206
- wlog ( "Generating SSL certificate for Meterpreter sessions" )
207
-
208
- key = OpenSSL ::PKey ::RSA . new ( 1024 ) { }
209
- cert = OpenSSL ::X509 ::Certificate . new
210
- cert . version = 2
211
- cert . serial = rand ( 0xFFFFFFFF )
212
-
213
- # Depending on how the socket was created, getsockname will
214
- # return either a struct sockaddr as a String (the default ruby
215
- # Socket behavior) or an Array (the extend'd Rex::Socket::Tcp
216
- # behavior). Avoid the ambiguity by always picking a random
217
- # hostname. See #7350.
218
- subject_cn = Rex ::Text . rand_hostname
219
-
220
- subject = OpenSSL ::X509 ::Name . new ( [
221
- [ "C" , "US" ] ,
222
- [ 'ST' , Rex ::Text . rand_state ( ) ] ,
223
- [ "L" , Rex ::Text . rand_text_alpha ( rand ( 20 ) + 10 ) ] ,
224
- [ "O" , Rex ::Text . rand_text_alpha ( rand ( 20 ) + 10 ) ] ,
225
- [ "CN" , subject_cn ] ,
226
- ] )
227
- issuer = OpenSSL ::X509 ::Name . new ( [
228
- [ "C" , "US" ] ,
229
- [ 'ST' , Rex ::Text . rand_state ( ) ] ,
230
- [ "L" , Rex ::Text . rand_text_alpha ( rand ( 20 ) + 10 ) ] ,
231
- [ "O" , Rex ::Text . rand_text_alpha ( rand ( 20 ) + 10 ) ] ,
232
- [ "CN" , Rex ::Text . rand_text_alpha ( rand ( 20 ) + 10 ) ] ,
233
- ] )
234
-
235
- cert . subject = subject
236
- cert . issuer = issuer
237
- cert . not_before = Time . now - ( 3600 * 365 ) + rand ( 3600 * 14 )
238
- cert . not_after = Time . now + ( 3600 * 365 ) + rand ( 3600 * 14 )
239
- cert . public_key = key . public_key
240
- ef = OpenSSL ::X509 ::ExtensionFactory . new ( nil , cert )
241
- cert . extensions = [
242
- ef . create_extension ( "basicConstraints" , "CA:FALSE" ) ,
243
- ef . create_extension ( "subjectKeyIdentifier" , "hash" ) ,
244
- ef . create_extension ( "extendedKeyUsage" , "serverAuth" ) ,
245
- ef . create_extension ( "keyUsage" , "keyEncipherment,dataEncipherment,digitalSignature" )
246
- ]
247
- ef . issuer_certificate = cert
248
- cert . add_extension ef . create_extension ( "authorityKeyIdentifier" , "keyid:always,issuer:always" )
249
- cert . sign ( key , OpenSSL ::Digest ::SHA1 . new )
250
-
251
- ctx = OpenSSL ::SSL ::SSLContext . new
252
- ctx . key = key
253
- ctx . cert = cert
254
-
255
- ctx . session_id_context = Rex ::Text . rand_text ( 16 )
256
-
257
- wlog ( "Generated SSL certificate for Meterpreter sessions" )
258
-
259
- @@ssl_ctx = ctx
260
-
261
- end # End of if not @ssl_ctx
226
+
227
+ # If the user specified a certificate and its not the cached one, delete the cached info
228
+ if self . ssl_cert && self . ssl_cert != @@ssl_cached_cert
229
+ @ssl_ctx = nil
230
+ end
231
+
232
+ # If the user did not specify a certificate and we have cached one, delete the cached info
233
+ if ! self . ssl_cert && @@ssl_cached_cert
234
+ @@ssl_cert_info = nil
235
+ end
236
+
237
+ unless @@ssl_cert_info
238
+ # If no certificate was specified, generate one
239
+ unless self . ssl_cert
240
+ wlog ( "Generating SSL certificate for Meterpreter sessions" )
241
+ @@ssl_cert_info = Rex ::Socket ::SslTcpServer . ssl_generate_certificate
242
+ wlog ( "Generated SSL certificate for Meterpreter sessions" )
243
+ # Load the user's specified certificate
244
+ else
245
+ wlog ( "Loading custom SSL certificate for Meterpreter sessions" )
246
+ @@ssl_cert_info = Rex ::Socket ::SslTcpServer . ssl_parse_pem ( self . ssl_cert )
247
+ wlog ( "Loaded custom SSL certificate for Meterpreter sessions" )
248
+ @@ssl_cached_cert = self . ssl_cert
249
+ end
250
+ end
251
+
252
+ # Create a new context for each session
253
+ ctx = OpenSSL ::SSL ::SSLContext . new ( )
254
+ ctx . key = @@ssl_cert_info [ 0 ]
255
+ ctx . cert = @@ssl_cert_info [ 1 ]
256
+ ctx . extra_chain_cert = @@ssl_cert_info [ 2 ]
257
+ ctx . options = 0
258
+ ctx . session_id_context = Rex ::Text . rand_text ( 16 )
262
259
end # End of mutex.synchronize
263
260
264
- @@ssl_ctx
261
+ ctx
265
262
end
266
263
267
264
##
@@ -453,6 +450,10 @@ def unicode_filter_decode(str)
453
450
#
454
451
attr_accessor :ssl
455
452
#
453
+ # Use this SSL Certificate (unified PEM)
454
+ #
455
+ attr_accessor :ssl_cert
456
+ #
456
457
# The Session Expiration Timeout
457
458
#
458
459
attr_accessor :expiration
0 commit comments