Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions lib/rex/socket/comm/local.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ def self.create_by_type(param, type, proto = 0)
sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
end

sock.bind(Rex::Socket.to_sockaddr(param.localhost, param.localport))
if Rex::Socket.is_ip_addr?(param.localhost)
ip = param.localhost
elsif param.v6
ip = Rex::Socket.getaddresses(param.localhost, true).select { |address| Rex::Socket.is_ipv6?(address) }.sample
else
ip = Rex::Socket.getaddresses(param.localhost, false).select { |address| Rex::Socket.is_ipv4?(address) }.sample
Comment on lines +183 to +185

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem: choosing a resolved address via .sample makes socket binding/connecting non-deterministic and can cause intermittent failures when some returned addresses are unreachable/unusable.

This is by design and replicates real-world behavior. When there are multiple addresses, we should be choosing one at random.

end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.getaddresses will resolve the address which will raise Socket::ResolutionError when the name can't be resolved which seems like the correct behavior. ip will not be nil.

[3] pry(#<Msf::Modules::Auxiliary__Gather__Kerberoast::MetasploitModule>)> ::Addrinfo.getaddrinfo('doesnotexist.lan', 0, ::Socket::AF_UNSPEC, ::Socket::SOCK_STREAM)
Socket::ResolutionError: getaddrinfo: Name or service not known (Socket::ResolutionError)

sock.bind(Rex::Socket.to_sockaddr(ip, param.localport))

rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
sock.close
Expand Down Expand Up @@ -256,7 +264,13 @@ def self.create_by_type(param, type, proto = 0)
ip = param.proxies.first.host
port = param.proxies.first.port
else
ip = Rex::Socket.getaddress(param.peerhost)
if Rex::Socket.is_ip_addr?(param.peerhost)
ip = param.peerhost
elsif param.v6
ip = Rex::Socket.getaddresses(param.peerhost, true).select { |address| Rex::Socket.is_ipv6?(address) }.sample
else
ip = Rex::Socket.getaddresses(param.peerhost, false).select { |address| Rex::Socket.is_ipv4?(address) }.sample
end
Comment on lines +267 to +273

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect, see #84 (comment)

port = param.peerport
end

Expand Down
Loading