Skip to content

Commit d0650df

Browse files
committed
Put a bandaid over getsockname
Depending on how a socket was created, #getsockname will return either a struct sockaddr as a String (the default ruby Socket behavior) or an Array (the extend'd Rex::Socket::Tcp behavior). Avoid the ambiguity when generating SSL certificates for meterpreter handlers by always picking a random hostname. This is by no means a proper fix for the underlying problem of Socket#getsockname having ambiguous behavior before and after being extended with Rex::Socket::Tcp. It does, however, solve the immediate problem of not being able to create tunneled meterpreter sessions over http(s) sessions. [SeeRM rapid7#7350]
1 parent 5c0fb27 commit d0650df

File tree

3 files changed

+13
-4
lines changed

3 files changed

+13
-4
lines changed

lib/msf/core/handler/bind_tcp.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ def start_handler
127127
rescue Rex::ConnectionRefused
128128
# Connection refused is a-okay
129129
rescue ::Exception
130-
wlog("Exception caught in bind handler: #{$!}")
130+
wlog("Exception caught in bind handler: #{$!.class} #{$!}")
131131
end
132132

133133
break if client
@@ -138,7 +138,6 @@ def start_handler
138138

139139
# Valid client connection?
140140
if (client)
141-
142141
# Increment the has connection counter
143142
self.pending_connections += 1
144143

lib/rex/io/stream_abstraction.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ def monitor_rsock
149149
closed = true
150150
wlog("monitor_rsock: closed remote socket due to nil read")
151151
end
152+
rescue EOFError => e
153+
closed = true
154+
dlog("monitor_rsock: EOF in rsock")
152155
rescue ::Exception => e
153156
closed = true
154157
wlog("monitor_rsock: exception during read: #{e.class} #{e}")

lib/rex/post/meterpreter/client.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def swap_sock_plain_to_ssl
154154
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
155155

156156
# Use non-blocking OpenSSL operations on Windows
157-
if not ( ssl.respond_to?(:accept_nonblock) and Rex::Compat.is_windows )
157+
if !( ssl.respond_to?(:accept_nonblock) and Rex::Compat.is_windows )
158158
ssl.accept
159159
else
160160
begin
@@ -211,12 +211,19 @@ def generate_ssl_context
211211
cert.version = 2
212212
cert.serial = rand(0xFFFFFFFF)
213213

214+
# Depending on how the socket was created, getsockname will
215+
# return either a struct sockaddr as a String (the default ruby
216+
# Socket behavior) or an Array (the extend'd Rex::Socket::Tcp
217+
# behavior). Avoid the ambiguity by always picking a random
218+
# hostname. See #7350.
219+
subject_cn = Rex::Text.rand_hostname
220+
214221
subject = OpenSSL::X509::Name.new([
215222
["C","US"],
216223
['ST', Rex::Text.rand_state()],
217224
["L", Rex::Text.rand_text_alpha(rand(20) + 10)],
218225
["O", Rex::Text.rand_text_alpha(rand(20) + 10)],
219-
["CN", self.sock.getsockname[1] || Rex::Text.rand_hostname],
226+
["CN", subject_cn],
220227
])
221228
issuer = OpenSSL::X509::Name.new([
222229
["C","US"],

0 commit comments

Comments
 (0)