diff --git a/Gemfile b/Gemfile index 0a37e48d0a621..e400dc65cea98 100644 --- a/Gemfile +++ b/Gemfile @@ -3,6 +3,10 @@ source 'https://rubygems.org' # spec.add_runtime_dependency '', [] gemspec name: 'metasploit-framework' +# Temporary: pull in the rex-socket #recvfrom stdlib alignment + #timed_recvfrom +# until a release is cut. Revert this commit once rex-socket is published. +gem 'rex-socket', git: 'https://github.com/zeroSteiner/rex-socket', branch: 'fix/udp/recvfrom-api' + # separate from test as simplecov is not run on travis-ci group :coverage do # code coverage for tests diff --git a/Gemfile.lock b/Gemfile.lock index f49d9ac22ad21..8d7a5610f0621 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,6 +12,15 @@ GIT with_env (= 1.1.0) xml-simple (~> 1.1.9) +GIT + remote: https://github.com/zeroSteiner/rex-socket + revision: 1c1e60bb77abd786ec0c3b35e735a6a8f58a057c + branch: fix/udp/recvfrom-api + specs: + rex-socket (0.1.68) + dnsruby + rex-core + PATH remote: . specs: @@ -550,9 +559,6 @@ GEM metasm rex-core rex-text - rex-socket (0.1.65) - dnsruby - rex-core rex-sslscan (0.1.13) rex-core rex-socket @@ -717,6 +723,7 @@ DEPENDENCIES pry-byebug rake redcarpet + rex-socket! rspec-rails rspec-rerun rubocop (= 1.75.7) diff --git a/lib/metasploit/framework/login_scanner/snmp.rb b/lib/metasploit/framework/login_scanner/snmp.rb index 2f32c4e7c809e..8fe18e3cafa3f 100644 --- a/lib/metasploit/framework/login_scanner/snmp.rb +++ b/lib/metasploit/framework/login_scanner/snmp.rb @@ -205,7 +205,8 @@ def process_logins(opts = {}) def recv_wrapper(sock, max_size, timeout) res = nil if protocol == 'udp' - res = sock.recvfrom(max_size, timeout) + data, addr = sock.timed_recvfrom(max_size, timeout) + res = [data, addr[3], addr[1]] if addr elsif protocol == 'tcp' ready = ::IO.select([sock], nil, nil, timeout) if ready diff --git a/lib/msf/core/auxiliary/udp_scanner.rb b/lib/msf/core/auxiliary/udp_scanner.rb index c453115864286..4d84c98b07424 100644 --- a/lib/msf/core/auxiliary/udp_scanner.rb +++ b/lib/msf/core/auxiliary/udp_scanner.rb @@ -173,7 +173,7 @@ def scanner_recv(timeout = 0.1) readable, _, _ = ::IO.select(@udp_sockets.values, nil, nil, timeout) if readable for sock in readable - res = sock.recvfrom(65535, timeout) + res = sock.recvfrom(65535) # Ignore invalid responses break if not res[1] @@ -182,12 +182,12 @@ def scanner_recv(timeout = 0.1) next if not (res[0] and res[0].length > 0) # Trim the IPv6-compat prefix off if needed - shost = res[1].sub(/^::ffff:/, '') + shost = res[1][3].sub(/^::ffff:/, '') # Ignore the response if we have a boundary next unless inside_workspace_boundary?(shost) - queue << [res[0], shost, res[2]] + queue << [res[0], shost, res[1][1]] if queue.length > datastore['ScannerRecvQueueLimit'] break diff --git a/lib/msf/core/exploit/remote/mssql.rb b/lib/msf/core/exploit/remote/mssql.rb index 80f48b10d0e20..fca80e3bfb405 100644 --- a/lib/msf/core/exploit/remote/mssql.rb +++ b/lib/msf/core/exploit/remote/mssql.rb @@ -78,7 +78,7 @@ def mssql_ping(timeout=5) }) ping_sock.put("\x02") - resp, _saddr, _sport = ping_sock.recvfrom(65535, timeout) + resp, = ping_sock.timed_recvfrom(65535, timeout) ping_sock.close return data if not resp diff --git a/lib/msf/core/exploit/remote/wdbrpc_client.rb b/lib/msf/core/exploit/remote/wdbrpc_client.rb index 607dd94687bee..277bbf65c38cd 100644 --- a/lib/msf/core/exploit/remote/wdbrpc_client.rb +++ b/lib/msf/core/exploit/remote/wdbrpc_client.rb @@ -39,7 +39,7 @@ def wdbrpc_client_connect wdbrpc_client_send_disconnect() udp_sock.sendto(wdbrpc_request_connect(rhost), rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 5) + res, = udp_sock.timed_recvfrom(65535, 5) if not res print_error("No response to TARGET_CONNECT (WDB4)") return @@ -84,7 +84,7 @@ def wdbrpc_client_connect2 wdbrpc_client_send_disconnect() udp_sock.sendto(wdbrpc_request_connect2(rhost), rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 5) + res, = udp_sock.timed_recvfrom(65535, 5) if not res print_error("No response to TARGET_CONNECT2") return @@ -115,12 +115,8 @@ def wdbrpc_client_memread(offset, length, params=0) begin udp_sock.sendto(pkt, rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 0.5) - if not res and src - raise RuntimeError, "no reply" - end - - if res.length <= 48 + res, = udp_sock.timed_recvfrom(65535, 0.5) + if res.nil? || res.length <= 48 raise RuntimeError, "short read" end @@ -142,9 +138,9 @@ def wdbrpc_client_memwrite(offset, buffer, params=0) res = nil udp_sock.sendto(pkt, rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 5.0) + res, = udp_sock.timed_recvfrom(65535, 5.0) - if not res and src + unless res raise RuntimeError, "no reply" end res[-4,4].unpack("N")[0] @@ -157,9 +153,9 @@ def wdbrpc_client_memscan(offset, depth, buffer, params=0) res = nil udp_sock.sendto(pkt, rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 5.0) + res, = udp_sock.timed_recvfrom(65535, 5.0) - if not res and src + unless res raise RuntimeError, "no reply" end p res @@ -173,7 +169,7 @@ def wdbrpc_client_context_kill(ctx_type=0, ctx=0) begin udp_sock.sendto(pkt, rhost, rport, 0) - res,src = udp_sock.recvfrom(65535, 0.5) + res, = udp_sock.timed_recvfrom(65535, 0.5) rescue ::Interrupt raise $! @@ -187,7 +183,7 @@ def wdbrpc_client_send_disconnect begin if self.udp_sock self.udp_sock.sendto(pkt, rhost, rport, 0) - self.udp_sock.recvfrom(65535, 5) + self.udp_sock.timed_recvfrom(65535, 5) end rescue ::Interrupt raise $! diff --git a/lib/msf/core/handler/reverse_udp.rb b/lib/msf/core/handler/reverse_udp.rb index ea99b2a16cabc..a33129c20b3f9 100644 --- a/lib/msf/core/handler/reverse_udp.rb +++ b/lib/msf/core/handler/reverse_udp.rb @@ -159,7 +159,8 @@ def start_handler loop do # Accept a client connection begin - inbound, peerhost, peerport = self.listener_sock.recvfrom + inbound, addr = self.listener_sock.recvfrom(65535) + peerhost, peerport = addr[3], addr[1] next if peerhost.nil? comm = self.listener_sock.channel.client if self.listener_sock.respond_to?(:channel) && self.listener_sock.channel.respond_to?(:client) diff --git a/lib/rex/post/meterpreter/channels/datagram.rb b/lib/rex/post/meterpreter/channels/datagram.rb index d80c8212f77b4..733f99c26b270 100644 --- a/lib/rex/post/meterpreter/channels/datagram.rb +++ b/lib/rex/post/meterpreter/channels/datagram.rb @@ -29,13 +29,16 @@ def cls module SocketInterface include Rex::Post::Meterpreter::SocketAbstraction::SocketInterface + + MAX_SOCKADDR_LENGTH = 128 + def type? 'udp' end def recvfrom_nonblock(length, flags = 0) data = super(length, flags)[0] - sockaddr = super(length, flags)[0] + sockaddr = super(MAX_SOCKADDR_LENGTH, flags)[0] [data, sockaddr] end diff --git a/lib/rex/proto/dhcp/server.rb b/lib/rex/proto/dhcp/server.rb index 12d28947b9b8b..a6d0aa81d9780 100644 --- a/lib/rex/proto/dhcp/server.rb +++ b/lib/rex/proto/dhcp/server.rb @@ -179,7 +179,8 @@ def monitor_socket r,_,_ = ::IO.select(rds,wds,eds,1) if (r != nil and r[0] == self.sock) - buf,host,port = self.sock.recvfrom(65535) + buf, addr = self.sock.recvfrom(65535) + host, port = addr[3], addr[1] # Lame compatabilitiy :-/ from = [host, port] dispatch_request(from, buf) diff --git a/lib/rex/proto/dns/resolver.rb b/lib/rex/proto/dns/resolver.rb index 53634ffa66708..885e108f935d4 100644 --- a/lib/rex/proto/dns/resolver.rb +++ b/lib/rex/proto/dns/resolver.rb @@ -341,7 +341,7 @@ def send_udp(packet,packet_data, nameservers) @logger.info "Contacting nameserver #{ns} port #{@config[:port]}" #socket.sendto(packet_data, ns.to_s, @config[:port].to_i, 0) socket.write(packet_data) - ans = socket.recvfrom(@config[:packet_size]) + ans = socket.timed_recvfrom(@config[:packet_size]) break if ans rescue Timeout::Error @logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one" diff --git a/lib/rex/proto/dns/server.rb b/lib/rex/proto/dns/server.rb index 03cb63a455173..5a74d9b8334b1 100644 --- a/lib/rex/proto/dns/server.rb +++ b/lib/rex/proto/dns/server.rb @@ -218,7 +218,8 @@ def monitor_listener r,_,_ = ::IO.select(rds,wds,eds,1) if (r != nil and r[0] == self.udp_sock) - buf,host,port = self.udp_sock.recvfrom(65535) + buf, addr = self.udp_sock.recvfrom(65535) + host, port = addr[3], addr[1] # Mock up a client object for sending back data cli = MockDnsClient.new(host, port, r[0]) dispatch_request(cli, buf) diff --git a/lib/rex/proto/iax2/client.rb b/lib/rex/proto/iax2/client.rb index 3cf38533cea6d..0a017e4cfb7e9 100644 --- a/lib/rex/proto/iax2/client.rb +++ b/lib/rex/proto/iax2/client.rb @@ -62,7 +62,7 @@ def create_call def monitor_socket while true begin - pkt, src = self.sock.recvfrom(65535) + pkt, = self.sock.recvfrom(65535) next if not pkt # Find the matching call object diff --git a/lib/rex/proto/ldap/server.rb b/lib/rex/proto/ldap/server.rb index af0d9f359232d..8297d0aa20252 100644 --- a/lib/rex/proto/ldap/server.rb +++ b/lib/rex/proto/ldap/server.rb @@ -375,7 +375,8 @@ def monitor_listener next unless (!r.nil? && (r[0] == udp_sock)) - buf, host, port = udp_sock.recvfrom(65535) + buf, addr = udp_sock.recvfrom(65535) + host, port = addr[3], addr[1] # Mock up a client object for sending back data cli = MockLdapClient.new(host, port, r[0]) cli.extend(LdapClient) diff --git a/lib/rex/proto/natpmp/packet.rb b/lib/rex/proto/natpmp/packet.rb index 85defac6b3c3c..83df24ecd96d8 100644 --- a/lib/rex/proto/natpmp/packet.rb +++ b/lib/rex/proto/natpmp/packet.rb @@ -18,7 +18,7 @@ def get_external_address(udp_sock, host, port, timeout=1) vprint_status("#{host}:#{port} - Probing NAT-PMP for external address") udp_sock.sendto(external_address_request, host, port, 0) external_address = nil - while (r = udp_sock.recvfrom(12, timeout) and r[1]) + while (r = udp_sock.timed_recvfrom(12, timeout)) (ver, op, result, epoch, external_address) = parse_external_address_response(r[0]) if external_address vprint_good("#{host}:#{port} - NAT-PMP external address is #{external_address}") @@ -43,7 +43,7 @@ def map_port(udp_sock, host, port, int_port, ext_port, protocol, lifetime, timeo # send it udp_sock.sendto(req, host, datastore['RPORT'], 0) # handle the reply - while (r = udp_sock.recvfrom(16, timeout) and r[1]) + while (r = udp_sock.timed_recvfrom(16, timeout)) (_, _, result, _, _, actual_ext_port, _) = parse_map_port_response(r[0]) return (result == 0 ? actual_ext_port : nil) end diff --git a/lib/rex/proto/tftp/client.rb b/lib/rex/proto/tftp/client.rb index 227c4f32d9565..30f39446423f5 100644 --- a/lib/rex/proto/tftp/client.rb +++ b/lib/rex/proto/tftp/client.rb @@ -84,7 +84,8 @@ def start_server_socket def monitor_server_sock yield "Listening for incoming ACKs" if block_given? - res = self.server_sock.recvfrom(65535) + res = self.server_sock.timed_recvfrom(65535) + res = res ? [res[0], res[1][3], res[1][1]] : ['', nil, nil] if res and res[0] code, type, data = parse_tftp_response(res[0]) if code == Constants::OpAck and self.action == :upload @@ -112,7 +113,8 @@ def monitor_server_sock end def monitor_client_sock - res = self.client_sock.recvfrom(65535) + res = self.client_sock.timed_recvfrom(65535) + res = res ? [res[0], res[1][3], res[1][1]] : ['', nil, nil] if res[1] # Got a response back, so that's never good; Acks come back on server_sock. code, type, data = parse_tftp_response(res[0]) yield("Aborting, got code:%d, type:%d, message:'%s'" % [code, type, data]) if block_given? @@ -190,7 +192,8 @@ def recv_data(host, port, first_block) end current_block = first_block while current_block.size == 512 - res = self.server_sock.recvfrom(65535) + res = self.server_sock.timed_recvfrom(65535) + res = res ? [res[0], res[1][3], res[1][1]] : ['', nil, nil] if res and res[0] code, block_num, current_block = parse_tftp_response(res[0]) if code == 3 @@ -313,7 +316,8 @@ def send_data(host,port) end end send_retries = 0 - res = self.server_sock.recvfrom(65535) + res = self.server_sock.timed_recvfrom(65535) + res = res ? [res[0], res[1][3], res[1][1]] : ['', nil, nil] if res code, type, msg = parse_tftp_response(res[0]) if code == 4 diff --git a/lib/rex/proto/tftp/server.rb b/lib/rex/proto/tftp/server.rb index dca24b1ec3627..8c69af69e2792 100644 --- a/lib/rex/proto/tftp/server.rb +++ b/lib/rex/proto/tftp/server.rb @@ -240,7 +240,8 @@ def monitor_socket r,w,e = ::IO.select(rds,wds,eds,1) if (r != nil and r[0] == self.sock) - buf,host,port = self.sock.recvfrom(65535) + buf, addr = self.sock.recvfrom(65535) + host, port = addr[3], addr[1] # Lame compatabilitiy :-/ from = [host, port] dispatch_request(from, buf) diff --git a/modules/auxiliary/dos/scada/allen_bradley_pccc.rb b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb index 50db48903519e..7b958f89d8207 100644 --- a/modules/auxiliary/dos/scada/allen_bradley_pccc.rb +++ b/modules/auxiliary/dos/scada/allen_bradley_pccc.rb @@ -136,7 +136,7 @@ def check connect_udp udp_sock.put(enip_list_identify_pkt) - res = udp_sock.recvfrom(90) + res = udp_sock.timed_recvfrom(90) disconnect_udp diff --git a/modules/auxiliary/dos/upnp/miniupnpd_dos.rb b/modules/auxiliary/dos/upnp/miniupnpd_dos.rb index 749181ee51e40..5d706cb9e4c2e 100644 --- a/modules/auxiliary/dos/upnp/miniupnpd_dos.rb +++ b/modules/auxiliary/dos/upnp/miniupnpd_dos.rb @@ -47,7 +47,7 @@ def initialize(info = {}) def send_probe(udp_sock, probe) udp_sock.put(probe) - data = udp_sock.recvfrom + data = udp_sock.timed_recvfrom(65535) if data && !data[0].empty? return data[0] else diff --git a/modules/auxiliary/dos/windows/games/kaillera.rb b/modules/auxiliary/dos/windows/games/kaillera.rb index 8861125c5b5f3..ee8ef3a70c08a 100644 --- a/modules/auxiliary/dos/windows/games/kaillera.rb +++ b/modules/auxiliary/dos/windows/games/kaillera.rb @@ -40,7 +40,7 @@ def run connect_udp print_status('Sending Crash request...') udp_sock.put("HELLO0.83\0") - res = udp_sock.recvfrom(15) + res = udp_sock.timed_recvfrom(15) || [''] disconnect_udp if res[0] =~ /HELLOD00D([0-9]{1,5})/ @@ -60,7 +60,7 @@ def run connect_udp print_status('Checking target...') udp_sock.put("HELLO0.83\0") - res = udp_sock.recvfrom(15) + res = udp_sock.timed_recvfrom(15) || [''] disconnect_udp if res[0] =~ /HELLO/ diff --git a/modules/auxiliary/fuzzers/dns/dns_fuzzer.rb b/modules/auxiliary/fuzzers/dns/dns_fuzzer.rb index b06ef9a8df0d5..5cc7d88b0f803 100644 --- a/modules/auxiliary/fuzzers/dns/dns_fuzzer.rb +++ b/modules/auxiliary/fuzzers/dns/dns_fuzzer.rb @@ -123,7 +123,7 @@ def dns_alive(method) if method == 'UDP' udp_sock.put(testing_pkt) - res, = udp_sock.recvfrom(65535) + res, = udp_sock.timed_recvfrom(65535) disconnect_udp elsif method == 'TCP' sock.put(testing_pkt) @@ -131,7 +131,7 @@ def dns_alive(method) disconnect end - if res && res.empty? + if res.nil? || res.empty? print_error("#{msg} The remote server is not responding to DNS requests.") return false end @@ -283,13 +283,13 @@ def dns_send(data, method) udp_sock.put(data) if method == 'UDP' sock.put(data) if method == 'TCP' - res, = udp_sock.recvfrom(65535, 1) if method == 'UDP' + res, = udp_sock.timed_recvfrom(65535, 1) if method == 'UDP' res, = sock.get_once(-1, 1) if method == 'TCP' disconnect_udp if method == 'UDP' disconnect if method == 'TCP' - if res && res.empty? + if res.nil? || res.empty? @fail_count += 1 if @fail_count == 1 @probably_vuln = @lastdata if !@lastdata.nil? diff --git a/modules/auxiliary/fuzzers/ntp/ntp_protocol_fuzzer.rb b/modules/auxiliary/fuzzers/ntp/ntp_protocol_fuzzer.rb index b6ab34e86f717..d43e1a4321110 100644 --- a/modules/auxiliary/fuzzers/ntp/ntp_protocol_fuzzer.rb +++ b/modules/auxiliary/fuzzers/ntp/ntp_protocol_fuzzer.rb @@ -189,10 +189,10 @@ def probe(host, port, message) rescue ::Errno::EISCONN udp_sock.write(message) end - reply = udp_sock.recvfrom(65535, datastore['WAIT'] / 1000.0) + reply = udp_sock.timed_recvfrom(65535, datastore['WAIT'] / 1000.0) while reply && reply[1] replies << reply - reply = udp_sock.recvfrom(65535, datastore['WAIT'] / 1000.0) + reply = udp_sock.timed_recvfrom(65535, datastore['WAIT'] / 1000.0) end replies end diff --git a/modules/auxiliary/scanner/chargen/chargen_probe.rb b/modules/auxiliary/scanner/chargen/chargen_probe.rb index 5cd56a434a5ea..6e27023e4ee1d 100644 --- a/modules/auxiliary/scanner/chargen/chargen_probe.rb +++ b/modules/auxiliary/scanner/chargen/chargen_probe.rb @@ -53,7 +53,7 @@ def run_host(rhost) begin connect_udp udp_sock.write(data) - r = udp_sock.recvfrom(65535, 0.1) + r = udp_sock.timed_recvfrom(65535, 0.1) if r and r[1] vprint_status("#{Rex::Socket.to_authority(rhost, rport)} - Response: #{r[0]}") diff --git a/modules/auxiliary/scanner/discovery/udp_probe.rb b/modules/auxiliary/scanner/discovery/udp_probe.rb index f35028ae3f59f..bc7c59c865a3f 100644 --- a/modules/auxiliary/scanner/discovery/udp_probe.rb +++ b/modules/auxiliary/scanner/discovery/udp_probe.rb @@ -86,8 +86,8 @@ def run_host(ip) udp_sock.put(data) - r = udp_sock.recvfrom(65535, 0.1) and r[1] - parse_reply(r) if r + r = udp_sock.timed_recvfrom(65535, 0.1) + parse_reply([r[0], r[1][3], r[1][1]]) if r rescue ::Interrupt raise $ERROR_INFO rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError diff --git a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb index 0b51f0b13137b..8c0b536a13132 100644 --- a/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb +++ b/modules/auxiliary/scanner/ipmi/ipmi_dumphashes.rb @@ -355,8 +355,10 @@ def udp_send(data) end def udp_recv(timeo) - r = udp_sock.recvfrom(65535, timeo) - r[1] ? r : nil + r = udp_sock.timed_recvfrom(65535, timeo) + return nil unless r + + [r[0], r[1][3], r[1][1]] end def rhost diff --git a/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb b/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb index cc6c0ef288172..9280e24618e04 100644 --- a/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb +++ b/modules/auxiliary/scanner/jenkins/jenkins_udp_broadcast_enum.rb @@ -68,8 +68,8 @@ def run # loop a few times to account for multiple or slow responders iter = 0 - while (r = udp_sock.recvfrom(65535, 0.1)) && (iter < 20) - parse_reply(r) + while (r = udp_sock.timed_recvfrom(65535, 0.1)) && (iter < 20) + parse_reply([r[0], r[1][3], r[1][1]]) iter += 1 end end diff --git a/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb b/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb index 40eeb712c9bc8..bfb4148fcecd4 100644 --- a/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb +++ b/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb @@ -52,11 +52,11 @@ def run_host(ip) udp_sock.put(target_mac + cmd) - res = udp_sock.recvfrom(65535, 0.5) and res[1] + res = udp_sock.timed_recvfrom(65535, 0.5) # Parse the reply if we get a response if res - password = parse_reply(res) + password = parse_reply([res[0], res[1][3], res[1][1]]) end rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError print_error("Connection error") diff --git a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb index 16e8ad6b541da..a5fb7fca3f93a 100644 --- a/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb +++ b/modules/auxiliary/scanner/natpmp/natpmp_portscan.rb @@ -48,8 +48,8 @@ def run_host(host) Rex::Socket.portspec_crack(datastore['PORTS']).each do |port| map_req = map_port_request(port, port, Rex::Proto::NATPMP.const_get(datastore['PROTOCOL']), 1) udp_sock.sendto(map_req, host, datastore['RPORT'], 0) - while (r = udp_sock.recvfrom(16, 1.0) and r[1]) - break if handle_reply(host, external_address, r) + while (r = udp_sock.timed_recvfrom(16, 1.0)) + break if handle_reply(host, external_address, [r[0], r[1][3], r[1][1]]) end end rescue ::Interrupt diff --git a/modules/auxiliary/scanner/ntp/timeroast.rb b/modules/auxiliary/scanner/ntp/timeroast.rb index eaf973f837c3f..457adf7bc2d02 100644 --- a/modules/auxiliary/scanner/ntp/timeroast.rb +++ b/modules/auxiliary/scanner/ntp/timeroast.rb @@ -65,12 +65,12 @@ def build_ntp_probe(rid) def recv_response(timeout: 0) begin - raw, = udp_sock.recvfrom(68, timeout) # 68 is always the number of bytes expected + raw, = udp_sock.timed_recvfrom(68, timeout) # 68 is always the number of bytes expected rescue ::Rex::SocketError, ::IOError return nil end - return nil if raw.empty? + return nil if raw.nil? || raw.empty? Rex::Proto::NTP::Header::NTPHeader.read(raw) end diff --git a/modules/auxiliary/scanner/scada/bacnet_l3.rb b/modules/auxiliary/scanner/scada/bacnet_l3.rb index b2901ee9d6dfa..bcf0d51df61a0 100644 --- a/modules/auxiliary/scanner/scada/bacnet_l3.rb +++ b/modules/auxiliary/scanner/scada/bacnet_l3.rb @@ -154,12 +154,12 @@ def broadcast_who_is # Collect responses with unicast or broadcast destination. loop do - data, host, port = lsocket.recvfrom(65535, datastore['TIMEOUT']) - data2, host2, port2 = ssocket.recvfrom(65535, datastore['TIMEOUT']) - break if host.nil? && host2.nil? + res1 = lsocket.timed_recvfrom(65535, datastore['TIMEOUT']) + res2 = ssocket.timed_recvfrom(65535, datastore['TIMEOUT']) + break if res1.nil? && res2.nil? - cap << [data, host, port] if host - cap << [data2, host2, port2] if host2 + cap << [res1[0], res1[1][3], res1[1][1]] if res1 + cap << [res2[0], res2[1][3], res2[1][1]] if res2 end lsocket.close cap @@ -292,10 +292,10 @@ def send_read_properties(messages, ip, instance_number) messages.each do |message| ssocket.sendto(message, ip, datastore['PORT'], 0) loop do - data, host, port = ssocket.recvfrom(65535, datastore['TIMEOUT']) - break if host.nil? + res = ssocket.timed_recvfrom(65535, datastore['TIMEOUT']) + break if res.nil? - cap << [data, host, port] + cap << [res[0], res[1][3], res[1][1]] end end ssocket.close diff --git a/modules/auxiliary/scanner/scada/koyo_login.rb b/modules/auxiliary/scanner/scada/koyo_login.rb index 28806771acf14..c50bf93a6933f 100644 --- a/modules/auxiliary/scanner/scada/koyo_login.rb +++ b/modules/auxiliary/scanner/scada/koyo_login.rb @@ -164,7 +164,7 @@ def unlock_check # # Another way to speed things up is to use fancy threading, but that's for another # day. - while (r = @udp_sock.recvfrom(65535, 0.1) and recvpacks < 2) + while (r = @udp_sock.timed_recvfrom(65535, 0.1) and recvpacks < 2) res = r[0] if res.length == 269 # auth reply packet if res[17, 1] == "\x00" and res[19, 1] == "\xD2" # Magic bytes diff --git a/modules/auxiliary/scanner/sip/enumerator.rb b/modules/auxiliary/scanner/sip/enumerator.rb index cafdd9c59c207..f843d2c4448cf 100644 --- a/modules/auxiliary/scanner/sip/enumerator.rb +++ b/modules/auxiliary/scanner/sip/enumerator.rb @@ -77,8 +77,8 @@ def run_batch(batch) end if (idx % 10 == 0) - while (r = udp_sock.recvfrom(65535, 0.01) and r[1]) - parse_reply(r, datastore['METHOD']) + while (r = udp_sock.timed_recvfrom(65535, 0.01)) + parse_reply([r[0], r[1][3], r[1][1]], datastore['METHOD']) end end @@ -86,8 +86,8 @@ def run_batch(batch) end end - while (r = udp_sock.recvfrom(65535, 3) and r[1]) - parse_reply(r, datastore['METHOD']) + while (r = udp_sock.timed_recvfrom(65535, 3)) + parse_reply([r[0], r[1][3], r[1][1]], datastore['METHOD']) end rescue ::Interrupt raise $! diff --git a/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb b/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb index 0159e691f125a..bf9c000b873bf 100644 --- a/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb +++ b/modules/auxiliary/scanner/sip/sipdroid_ext_enum.rb @@ -89,7 +89,8 @@ def run() udp_sock.put(data) while not rcv.nil? - msg = udp_sock.recvfrom(1024, 4) + msg = udp_sock.timed_recvfrom(1024, 4) + msg = msg ? [msg[0], msg[1][3], msg[1][1]] : ['', nil, nil] if not msg[0].eql?("") if msg[0].include?("SIP/2.0 180 Ringing") origin = /o=\w+\@[\w+\.]+/.match(msg[0]) diff --git a/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb b/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb index 294af9ef052e5..1f66efb064819 100644 --- a/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb +++ b/modules/auxiliary/scanner/telnet/lantronix_telnet_password.rb @@ -54,9 +54,9 @@ def run_host(ip) rem_sock = Rex::Socket::Udp.create(sock_opts) end rem_sock.put(setup_probe) - res = rem_sock.recvfrom(65535, 0.5) and res[1] + res = rem_sock.timed_recvfrom(65535, 0.5) - password = parse_reply(res) + password = res && parse_reply(res) rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError print_error("Connection error") rescue ::Interrupt diff --git a/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb b/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb index 9fa5dac232223..5886081655b87 100644 --- a/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb +++ b/modules/auxiliary/scanner/tftp/ipswitch_whatsupgold_tftp.rb @@ -72,7 +72,8 @@ def run_host(ip) file_data = '' udp_sock.sendto(pkt, ip, datastore['RPORT'].to_i) - while (r = udp_sock.recvfrom(65535, 0.1) and r[1]) + while (r = udp_sock.timed_recvfrom(65535, 0.1)) + r = [r[0], r[1][3], r[1][1]] opcode, block, data = r[0].unpack("nna*") # Parse reply if opcode != 3 # Check opcode: 3 => Data Packet diff --git a/modules/auxiliary/scanner/tftp/netdecision_tftp.rb b/modules/auxiliary/scanner/tftp/netdecision_tftp.rb index 997857b8512c2..f0d3ac775b4de 100644 --- a/modules/auxiliary/scanner/tftp/netdecision_tftp.rb +++ b/modules/auxiliary/scanner/tftp/netdecision_tftp.rb @@ -71,7 +71,8 @@ def run_host(ip) file_data = '' udp_sock.sendto(pkt, ip, datastore['RPORT'].to_i) - while (r = udp_sock.recvfrom(65535, 0.1) and r[1]) + while (r = udp_sock.timed_recvfrom(65535, 0.1)) + r = [r[0], r[1][3], r[1][1]] opcode, block, data = r[0].unpack("nna*") # Parse reply if opcode != 3 # Check opcode: 3 => Data Packet diff --git a/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb b/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb index 30d607e68807d..8f7dedb96fa1b 100644 --- a/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb +++ b/modules/auxiliary/scanner/vxworks/wdbrpc_bootline.rb @@ -58,8 +58,8 @@ def run_batch(batch) end if (idx % 10 == 0) - while (r = udp_sock.recvfrom(65535, 0.01) and r[1]) - parse_reply(r) + while (r = udp_sock.timed_recvfrom(65535, 0.01)) + parse_reply([r[0], r[1][3], r[1][1]]) end end @@ -69,8 +69,8 @@ def run_batch(batch) cnt = 0 del = 10 sts = Time.now.to_i - while (r = udp_sock.recvfrom(65535, del) and r[1]) - parse_reply(r) + while (r = udp_sock.timed_recvfrom(65535, del)) + parse_reply([r[0], r[1][3], r[1][1]]) # Prevent an indefinite loop if the targets keep replying cnt += 1 diff --git a/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb b/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb index ad752b47be892..d546b7bddd35f 100644 --- a/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb +++ b/modules/auxiliary/scanner/vxworks/wdbrpc_version.rb @@ -56,8 +56,8 @@ def run_batch(batch) end if (idx % 10 == 0) - while (r = udp_sock.recvfrom(65535, 0.01) and r[1]) - parse_reply(r) + while (r = udp_sock.timed_recvfrom(65535, 0.01)) + parse_reply([r[0], r[1][3], r[1][1]]) end end @@ -67,8 +67,8 @@ def run_batch(batch) cnt = 0 del = 10 sts = Time.now.to_i - while (r = udp_sock.recvfrom(65535, del) and r[1]) - parse_reply(r) + while (r = udp_sock.timed_recvfrom(65535, del)) + parse_reply([r[0], r[1][3], r[1][1]]) # Prevent an indefinite loop if the targets keep replying cnt += 1 diff --git a/modules/auxiliary/server/capture/sip.rb b/modules/auxiliary/server/capture/sip.rb index 2951c27092cf3..02c0373fbf192 100644 --- a/modules/auxiliary/server/capture/sip.rb +++ b/modules/auxiliary/server/capture/sip.rb @@ -147,12 +147,14 @@ def run server_ip = sip_sanitize_address(srvhost) while @run - res = @sock.recvfrom + res = @sock.timed_recvfrom(65535) + next unless res + @requestor = { - ip: res[1], - port: res[2] + ip: res[1][3], + port: res[1][1] } - client_ip = sip_sanitize_address(res[1]) + client_ip = sip_sanitize_address(res[1][3]) next if !res[0] || res[0].empty? request = sip_parse_request(res[0]) diff --git a/modules/auxiliary/spoof/dns/bailiwicked_domain.rb b/modules/auxiliary/spoof/dns/bailiwicked_domain.rb index 38bd5f71292b1..22a4e7582f392 100644 --- a/modules/auxiliary/spoof/dns/bailiwicked_domain.rb +++ b/modules/auxiliary/spoof/dns/bailiwicked_domain.rb @@ -100,7 +100,7 @@ def check req.rd = 1 srv_sock.put(req.encode) - res, = srv_sock.recvfrom(65535, 1.0) + res, = srv_sock.timed_recvfrom(65535, 1.0) if res && !res.empty? reps += 1 @@ -182,7 +182,7 @@ def run req.rd = 1 srv_sock.put(req.encode) - res, = srv_sock.recvfrom + res, = srv_sock.timed_recvfrom(65535) if res && !res.empty? res = Resolv::DNS::Message.decode(res) @@ -209,7 +209,7 @@ def run loop do cached = false srv_sock.put(query.encode) - answer, = srv_sock.recvfrom + answer, = srv_sock.timed_recvfrom(65535) if answer && !answer.empty? answer = Resolv::DNS::Message.decode(answer) @@ -367,7 +367,7 @@ def run query.rd = 0 srv_sock.put(query.encode) - answer, = srv_sock.recvfrom + answer, = srv_sock.timed_recvfrom(65535) if answer && !answer.empty? answer = Resolv::DNS::Message.decode(answer) @@ -419,7 +419,7 @@ def calculate_race(server, domain, num = 50) req.rd = 0 while (times.length < num) - res, = sock.recvfrom(65535, 0.01) + res, = sock.timed_recvfrom(65535, 0.01) if res && !res.empty? res = Resolv::DNS::Message.decode(res) diff --git a/modules/auxiliary/spoof/dns/bailiwicked_host.rb b/modules/auxiliary/spoof/dns/bailiwicked_host.rb index c06197e820ef3..5b53c59e4a1c3 100644 --- a/modules/auxiliary/spoof/dns/bailiwicked_host.rb +++ b/modules/auxiliary/spoof/dns/bailiwicked_host.rb @@ -96,7 +96,7 @@ def check req.rd = 1 srv_sock.put(req.encode) - res, = srv_sock.recvfrom(65535, 1.0) + res, = srv_sock.timed_recvfrom(65535, 1.0) if res && !res.empty? reps += 1 @@ -181,7 +181,7 @@ def run req.rd = 1 srv_sock.put(req.encode) - res, = srv_sock.recvfrom + res, = srv_sock.timed_recvfrom(65535) if res && !res.empty? res = Resolv::DNS::Message.decode(res) @@ -208,7 +208,7 @@ def run loop do cached = false srv_sock.put(query.encode) - answer, = srv_sock.recvfrom + answer, = srv_sock.timed_recvfrom(65535) if answer && !answer.empty? answer = Resolv::DNS::Message.decode(answer) @@ -366,7 +366,7 @@ def run query.rd = 0 srv_sock.put(query.encode) - answer, = srv_sock.recvfrom + answer, = srv_sock.timed_recvfrom(65535) if answer && !answer.empty? answer = Resolv::DNS::Message.decode(answer) @@ -418,7 +418,7 @@ def calculate_race(server, domain, num = 50) req.rd = 0 while (times.length < num) - res, = sock.recvfrom(65535, 0.01) + res, = sock.timed_recvfrom(65535, 0.01) if res && !res.empty? res = Resolv::DNS::Message.decode(res) diff --git a/modules/auxiliary/spoof/dns/compare_results.rb b/modules/auxiliary/spoof/dns/compare_results.rb index fcfb5300a62b6..2e111b3cca105 100644 --- a/modules/auxiliary/spoof/dns/compare_results.rb +++ b/modules/auxiliary/spoof/dns/compare_results.rb @@ -78,8 +78,8 @@ def run base_sock.put(buf) targ_sock.put(buf) - base_res, = base_sock.recvfrom(65535, 3.0) - targ_res, = targ_sock.recvfrom(65535, 3.0) + base_res, = base_sock.timed_recvfrom(65535, 3.0) + targ_res, = targ_sock.timed_recvfrom(65535, 3.0) if !(base_res && targ_res && !base_res.empty? && !targ_res.empty?) print_error(' Error: The baseline server did not respond to our request.') if !(base_res && !base_res.empty?) diff --git a/modules/auxiliary/spoof/llmnr/llmnr_response.rb b/modules/auxiliary/spoof/llmnr/llmnr_response.rb index e152d08d2de5c..2a4ada8d436a7 100644 --- a/modules/auxiliary/spoof/llmnr/llmnr_response.rb +++ b/modules/auxiliary/spoof/llmnr/llmnr_response.rb @@ -166,8 +166,8 @@ def monitor_socket r, = ::IO.select(rds, wds, eds, 0.25) if !r.nil? && (r[0] == sock) - packet, host, port = sock.recvfrom(65535) - dispatch_request(packet, host, port) + packet, addr = sock.recvfrom(65535) + dispatch_request(packet, addr[3], addr[1]) end end end diff --git a/modules/auxiliary/spoof/mdns/mdns_response.rb b/modules/auxiliary/spoof/mdns/mdns_response.rb index 09adf15590a81..6923e1224f38d 100644 --- a/modules/auxiliary/spoof/mdns/mdns_response.rb +++ b/modules/auxiliary/spoof/mdns/mdns_response.rb @@ -187,8 +187,8 @@ def monitor_socket r, = ::IO.select(rds, wds, eds, 0.25) if !r.nil? && (r[0] == sock) - packet, host, port = sock.recvfrom(65535) - dispatch_request(packet, host, port) + packet, addr = sock.recvfrom(65535) + dispatch_request(packet, addr[3], addr[1]) end end end diff --git a/modules/auxiliary/spoof/nbns/nbns_response.rb b/modules/auxiliary/spoof/nbns/nbns_response.rb index 51e9af41cfe86..5e2c8722cdb55 100644 --- a/modules/auxiliary/spoof/nbns/nbns_response.rb +++ b/modules/auxiliary/spoof/nbns/nbns_response.rb @@ -133,8 +133,8 @@ def monitor_socket r, = ::IO.select(rds, wds, eds, 0.25) if !r.nil? && (r[0] == sock) - packet, host, port = sock.recvfrom(65535) - dispatch_request(packet, host, port) + packet, addr = sock.recvfrom(65535) + dispatch_request(packet, addr[3], addr[1]) end end end diff --git a/modules/auxiliary/voip/sip_deregister.rb b/modules/auxiliary/voip/sip_deregister.rb index 8530ef247bebc..532e91c5f700f 100644 --- a/modules/auxiliary/voip/sip_deregister.rb +++ b/modules/auxiliary/voip/sip_deregister.rb @@ -83,8 +83,8 @@ def run_host(ip) udp_sock.put(req) response = false - while ((r = udp_sock.recvfrom(65535, 3))) && r[1] - response = parse_reply(r) + while ((r = udp_sock.timed_recvfrom(65535, 3))) + response = parse_reply([r[0], r[1][3], r[1][1]]) end # print error information if no response has been received diff --git a/modules/exploits/linux/games/ut2004_secure.rb b/modules/exploits/linux/games/ut2004_secure.rb index 5cea3f5b44a1c..0c9fbcabfa591 100644 --- a/modules/exploits/linux/games/ut2004_secure.rb +++ b/modules/exploits/linux/games/ut2004_secure.rb @@ -83,7 +83,7 @@ def exploit def ut_version connect_udp udp_sock.put('\\basic\\') - res = udp_sock.recvfrom(8192) + res, = udp_sock.timed_recvfrom(8192) disconnect_udp if res && (m = res.match(/\\gamever\\([0-9]{1,5})/)) diff --git a/modules/exploits/linux/misc/cve_2020_13160_anydesk.rb b/modules/exploits/linux/misc/cve_2020_13160_anydesk.rb index 494de025bcf69..fe34d040186dc 100644 --- a/modules/exploits/linux/misc/cve_2020_13160_anydesk.rb +++ b/modules/exploits/linux/misc/cve_2020_13160_anydesk.rb @@ -102,12 +102,13 @@ def discover timeout = 10 while timeout > 0 start_time = Time.now - response, host, = server_sock.recvfrom(8192, timeout) - break if host == datastore['RHOST'] + response, addr = server_sock.timed_recvfrom(8192, timeout) + break if addr && addr[3] == datastore['RHOST'] timeout = Time.now - start_time end + return nil if response.nil? return nil unless response[0..2].bytes == [0x3e, 0xd1, 0x01] return nil unless response[11] == "\x02" diff --git a/modules/exploits/linux/misc/igel_command_injection.rb b/modules/exploits/linux/misc/igel_command_injection.rb index 9a43126f4bcba..09149e85a8f40 100644 --- a/modules/exploits/linux/misc/igel_command_injection.rb +++ b/modules/exploits/linux/misc/igel_command_injection.rb @@ -85,7 +85,7 @@ def check connect_udp(true, 'RPORT' => 30005) udp_sock.put(probe) - res = udp_sock.recvfrom(65535, 0.5) + res = udp_sock.timed_recvfrom(65535, 0.5) disconnect_udp unless res && res[0] diff --git a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb index 914ad8a1a1c8f..c3181a1814479 100644 --- a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb +++ b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb @@ -418,7 +418,7 @@ def choose_target res = nil 1.upto(5) do - res, _, _ = udp_sock.recvfrom(65535, 1.0) + res, = udp_sock.timed_recvfrom(65535, 1.0) break if res and res =~ /^(Server|Location)/mi udp_sock.sendto(msearch, rhost, rport, 0) diff --git a/modules/exploits/windows/brightstor/discovery_udp.rb b/modules/exploits/windows/brightstor/discovery_udp.rb index 955b99454e512..9b80b9e385170 100644 --- a/modules/exploits/windows/brightstor/discovery_udp.rb +++ b/modules/exploits/windows/brightstor/discovery_udp.rb @@ -125,7 +125,7 @@ def exploit buf[1046, payload.encoded.length] = payload.encoded udp_sock.put(buf) - udp_sock.recvfrom(8192) + udp_sock.timed_recvfrom(8192) handler disconnect_udp diff --git a/modules/exploits/windows/games/ut2004_secure.rb b/modules/exploits/windows/games/ut2004_secure.rb index 298e5cc1292df..138e36a325694 100644 --- a/modules/exploits/windows/games/ut2004_secure.rb +++ b/modules/exploits/windows/games/ut2004_secure.rb @@ -79,7 +79,7 @@ def exploit def ut_version connect_udp udp_sock.put("\\basic\\") - res = udp_sock.recvfrom(8192) + res, = udp_sock.timed_recvfrom(8192) disconnect_udp if (res and (m = res.match(/\\gamever\\([0-9]{1,5})/))) diff --git a/modules/exploits/windows/license/sentinel_lm7_udp.rb b/modules/exploits/windows/license/sentinel_lm7_udp.rb index 27c7d8862091b..d45522b8b1e2b 100644 --- a/modules/exploits/windows/license/sentinel_lm7_udp.rb +++ b/modules/exploits/windows/license/sentinel_lm7_udp.rb @@ -63,7 +63,7 @@ def initialize(info = {}) def check connect_udp udp_sock.put("\x7a\x00\x00\x00\x00\x00") - res = udp_sock.recvfrom(8192) + res = udp_sock.timed_recvfrom(8192) disconnect_udp if (res and res[0] == 0x7a) @@ -89,7 +89,7 @@ def exploit buf[827, 5] = "\xe9" + [-829].pack('V') udp_sock.put(buf) - udp_sock.recvfrom(8192) + udp_sock.timed_recvfrom(8192) handler disconnect_udp diff --git a/modules/exploits/windows/misc/crosschex_device_bof.rb b/modules/exploits/windows/misc/crosschex_device_bof.rb index 60cc35dbbd5e7..70bb7cc53d2a7 100644 --- a/modules/exploits/windows/misc/crosschex_device_bof.rb +++ b/modules/exploits/windows/misc/crosschex_device_bof.rb @@ -70,8 +70,8 @@ def initialize(info = {}) def exploit connect_udp - res, host, port = udp_sock.recvfrom(PACKET_LEN, datastore['TIMEOUT'].to_i > 0 ? datastore['TIMEOUT'].to_i : nil) - if res.empty? + res, = udp_sock.timed_recvfrom(PACKET_LEN, datastore['TIMEOUT'].to_i > 0 ? datastore['TIMEOUT'].to_i : nil) + if res.nil? || res.empty? fail_with(Failure::TimeoutExpired, 'Module timed out waiting for CrossChex broadcast') end diff --git a/spec/lib/rex/post/meterpreter/channels/datagram_spec.rb b/spec/lib/rex/post/meterpreter/channels/datagram_spec.rb new file mode 100644 index 0000000000000..39a4d6f311f48 --- /dev/null +++ b/spec/lib/rex/post/meterpreter/channels/datagram_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'rex/socket/udp' +require 'rex/post/meterpreter/channels/datagram' + +RSpec.describe Rex::Post::Meterpreter::Datagram do + subject(:channel) { described_class.new(nil, nil, nil, 0, nil) } + + before do + channel.lsock.extend(Rex::Socket::Udp) + channel.lsock.initsock + channel.lsock.extend(described_class::SocketInterface) + channel.lsock.channel = channel + end + + after do + channel.lsock.close unless channel.lsock.closed? + channel.rsock.close unless channel.rsock.closed? + end + + describe 'SocketInterface#recvfrom_nonblock' do + it 'reads the synthetic sockaddr independently from the requested payload length' do + channel.rsock.syswrite('response') + channel.rsock.syswrite(Rex::Socket.to_sockaddr('192.0.2.53', 53)) + + data, addr = channel.lsock.recvfrom(1) + + expect(data).to eq('r') + expect(addr).to eq(['AF_INET', 53, '192.0.2.53', '192.0.2.53']) + end + end +end diff --git a/spec/modules/auxiliary/scanner/ipmi/ipmi_dumphashes_spec.rb b/spec/modules/auxiliary/scanner/ipmi/ipmi_dumphashes_spec.rb index 489756a75b25e..37cf14e4d8d0b 100644 --- a/spec/modules/auxiliary/scanner/ipmi/ipmi_dumphashes_spec.rb +++ b/spec/modules/auxiliary/scanner/ipmi/ipmi_dumphashes_spec.rb @@ -42,7 +42,7 @@ describe '#run_host' do it 'stops username enumeration when the host never answers the first open-session probe' do allow(udp_sock).to receive(:sendto) - allow(udp_sock).to receive(:recvfrom).and_return([nil, nil, nil]) + allow(udp_sock).to receive(:timed_recvfrom).and_return(nil) expect(udp_sock).to receive(:sendto).exactly(3).times diff --git a/spec/support/acceptance/session/java.rb b/spec/support/acceptance/session/java.rb index dccf63f8d77dd..5149ba8ab7a94 100644 --- a/spec/support/acceptance/session/java.rb +++ b/spec/support/acceptance/session/java.rb @@ -245,19 +245,16 @@ module Acceptance::Session::Java lines: { linux: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, osx: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, windows: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] } diff --git a/spec/support/acceptance/session/mettle.rb b/spec/support/acceptance/session/mettle.rb index 8618f3d4e15f7..76935197e4cff 100644 --- a/spec/support/acceptance/session/mettle.rb +++ b/spec/support/acceptance/session/mettle.rb @@ -327,19 +327,16 @@ module Acceptance::Session::Mettle lines: { linux: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, osx: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, windows: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] } diff --git a/spec/support/acceptance/session/php.rb b/spec/support/acceptance/session/php.rb index c4582d21779b5..cdb04ba9566e3 100644 --- a/spec/support/acceptance/session/php.rb +++ b/spec/support/acceptance/session/php.rb @@ -41,9 +41,9 @@ module Acceptance::Session::Php :windows, { skip: [ - :meterpreter_runtime_version, + :session_runtime_version, :==, - "php5.3" + "meterpreter/php5.3" ], reason: "Skip PHP 5.3 as the tests timeout - due to cmd_exec taking 15 seconds for each call. Caused by failure to detect feof correctly - https://github.com/rapid7/metasploit-payloads/blame/c7f7bc2fc0b86e17c3bc078149c71745c5e478b3/php/meterpreter/meterpreter.php#L1127-L1145" } @@ -206,9 +206,9 @@ module Acceptance::Session::Php :windows, { skip: [ - :meterpreter_runtime_version, + :session_runtime_version, :==, - "php5.3" + "meterpreter/php5.3" ], reason: "Skip PHP 5.3 as the tests timeout - due to cmd_exec taking 15 seconds for each call. Caused by failure to detect feof correctly - https://github.com/rapid7/metasploit-payloads/blame/c7f7bc2fc0b86e17c3bc078149c71745c5e478b3/php/meterpreter/meterpreter.php#L1127-L1145" } @@ -250,19 +250,22 @@ module Acceptance::Session::Php lines: { linux: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, osx: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, windows: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", + # PHP 5.3 Meterpreter on a Windows host raises Errno::ENOTSOCK + # (WSAENOTSOCK) from the UDP channel recvfrom; PHP 7.4/8.3 are fine. + ["[-] [[UDP] Has the correct peer information] FAILED: [UDP] Has the correct peer information", { if: [:session_runtime_version, :==, "meterpreter/php5.3"] }], + ["[-] [[UDP] Has the correct peer information] Exception: Errno::ENOTSOCK", { if: [:session_runtime_version, :==, "meterpreter/php5.3"] }], + ["[-] [[UDP] Receives data from the peer] FAILED: [UDP] Receives data from the peer", { if: [:session_runtime_version, :==, "meterpreter/php5.3"] }], + ["[-] [[UDP] Receives data from the peer] Exception: Errno::ENOTSOCK", { if: [:session_runtime_version, :==, "meterpreter/php5.3"] }], *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] } diff --git a/spec/support/acceptance/session/python.rb b/spec/support/acceptance/session/python.rb index cd60b1a1cf3b5..5df5196572c81 100644 --- a/spec/support/acceptance/session/python.rb +++ b/spec/support/acceptance/session/python.rb @@ -262,19 +262,16 @@ module Acceptance::Session::Python lines: { linux: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, osx: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] }, windows: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] } diff --git a/spec/support/acceptance/session/windows_meterpreter.rb b/spec/support/acceptance/session/windows_meterpreter.rb index 5a693447f4e5e..a223c0acb6c92 100644 --- a/spec/support/acceptance/session/windows_meterpreter.rb +++ b/spec/support/acceptance/session/windows_meterpreter.rb @@ -378,7 +378,6 @@ module Acceptance::Session::WindowsMeterpreter }, windows: { known_failures: [ - "[-] FAILED: [UDP] Has the correct peer information", *Acceptance::Session::Shared::SOCKET_CHANNEL_FLAKES ] } diff --git a/test/modules/post/test/socket_channels.rb b/test/modules/post/test/socket_channels.rb index 9d09b48d7bfe0..1f7e8387758fb 100644 --- a/test/modules/post/test/socket_channels.rb +++ b/test/modules/post/test/socket_channels.rb @@ -248,7 +248,6 @@ def test_udp_channel end it '[UDP] Has the correct peer information' do - # this one is expected to fail because #recvfrom just returns a string address which is inconsistent client, server_client = udp_socket_pair data = Random.new.bytes(rand(10..100)) # Now server can send to the client's address