Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@ GEM
metasm
rex-core
rex-text
rex-socket (0.1.69)
rex-socket (0.1.70)
dnsruby
rex-core
rex-sslscan (0.1.13)
Expand Down
8 changes: 4 additions & 4 deletions lib/msf/core/auxiliary/udp_scanner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ def scanner_send(data, ip, port)

retry

rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ECONNRESET
# This fires for host unreachable, net unreachable, and broadcast sends
# We can safely ignore all of these for UDP sends
end
Expand All @@ -175,9 +175,9 @@ def scanner_recv(timeout = 0.1)
for sock in readable
begin
res = sock.recvfrom(65535)
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED
# A connected UDP socket surfaces ICMP port-unreachable as ECONNREFUSED
# on recvfrom; skip this socket and keep processing the others.
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ECONNRESET
# A connected UDP socket surfaces ICMP port-unreachable differently
# by platform; skip this socket and keep processing the others.
next
end

Expand Down
2 changes: 1 addition & 1 deletion lib/msf/core/handler/bind_udp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def start_handler
client.close()
client = nil
end
rescue Errno::ECONNREFUSED
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
client.close()
client = nil
wlog("Connection failed in udp bind handler continuing attempts: #{$!.class} #{$!}")
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/admin/netbios/netbios_spoof.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def netbios_spam
if pps > @targ_rate
sleep(0.01)
end
rescue Errno::ECONNREFUSED
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
print_error('Error: Target sent us an ICMP port unreachable, port is likely closed')
live = false
break
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def phase1_dtls_handshake(silent: false)
print_status('DTLS handshake succeeded (self-signed cert accepted)') unless silent

[ssl, ctx, udp_sock, rbio, wbio]
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED => e
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ECONNRESET => e
print_error("Connection failed: #{e.message}") unless silent
cleanup_dtls(ssl, ctx, udp_sock)
[nil, nil, nil, nil, nil]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ def phase1_dtls_handshake(silent: false)
print_status('DTLS handshake succeeded (self-signed cert accepted)') unless silent

[ssl, ctx, udp_sock, rbio, wbio]
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED => e
rescue ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ECONNRESET => e
print_error("Connection failed: #{e.message}") unless silent
cleanup_dtls(ssl, ctx, udp_sock)
[nil, nil, nil, nil, nil]
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/dos/rpc/rpcbomb.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def scan_host(ip)
while count < datastore['COUNT']
begin
s.send(pkt, 0)
rescue ::Errno::ENOBUFS, ::Rex::ConnectionError, ::Errno::ECONNREFUSED
rescue ::Errno::ENOBUFS, ::Rex::ConnectionError, ::Errno::ECONNREFUSED, ::Errno::ECONNRESET
vprint_error("Host #{ip} unreachable")
break
end
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/scanner/snmp/snmp_enum_hp_laserjet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def run_host(ip)
disconnect_snmp
rescue SNMP::RequestTimeout
print_error("#{ip}, SNMP request timeout.")
rescue Errno::ECONNREFUSED
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
print_error("#{ip}, Connection refused.")
rescue SNMP::InvalidIpAddress
print_error("#{ip}, Invalid IP address. Check it with 'snmpwalk tool'.")
Expand Down
2 changes: 1 addition & 1 deletion modules/auxiliary/server/netbios_spoof_nat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def netbios_spam
if pps > @targ_rate
sleep(0.01)
end
rescue Errno::ECONNREFUSED
rescue Errno::ECONNREFUSED, Errno::ECONNRESET
print_error("Error: Target sent us an ICMP port unreachable, port is likely closed")
live = false
break
Expand Down
52 changes: 38 additions & 14 deletions spec/lib/msf/core/auxiliary/udp_scanner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@
mod.extend described_class
mod.instance_variable_set(:@udp_sockets, {})
mod.instance_variable_set(:@udp_sockets_mutex, Mutex.new)
mod.instance_variable_set(:@udp_send_count, 0)
mod.instance_variable_set(:@interval_mutex, Mutex.new)
mod.instance_variable_set(:@results, {})
mod.define_singleton_method(:datastore) { { 'ScannerRecvQueueLimit' => 100 } }
mod.define_singleton_method(:datastore) do
{
'ScannerMaxResends' => 10,
'ScannerRecvInterval' => 30,
'ScannerRecvQueueLimit' => 100
}
end
mod.define_singleton_method(:inside_workspace_boundary?) { |_host| true }
allow(mod).to receive(:cleanup_udp_sockets)
mod
end

# A socket whose recvfrom raises, mimicking a connected UDP socket that received an
# ICMP port-unreachable for a closed port.
let(:refused_socket) do
# A socket whose recvfrom raises, mimicking a connected UDP socket that received
# an ICMP port-unreachable for a closed port.
def error_socket(error_class)
sock = double('refused_socket')
allow(sock).to receive(:recvfrom).and_raise(::Errno::ECONNREFUSED)
allow(sock).to receive(:recvfrom).and_raise(error_class)
sock
end

Expand All @@ -31,20 +39,36 @@
sock
end

describe '#scanner_send' do
[::Errno::ECONNREFUSED, ::Errno::ECONNRESET].each do |error_class|
it "swallows #{error_class} raised while sending UDP probes" do
sock = double('send_socket')
allow(sock).to receive(:send).and_raise(error_class)
allow(subject).to receive(:udp_socket).and_return(sock)

expect { subject.scanner_send('probe', '192.0.2.5', 161) }.not_to raise_error
end
end
end

describe '#scanner_recv' do
it 'swallows ECONNREFUSED raised by recvfrom instead of propagating it' do
allow(::IO).to receive(:select).and_return([[refused_socket], [], []], nil)
[::Errno::ECONNREFUSED, ::Errno::ECONNRESET].each do |error_class|
it "swallows #{error_class} raised by recvfrom instead of propagating it" do
allow(::IO).to receive(:select).and_return([[error_socket(error_class)], [], []], nil)

expect { subject.scanner_recv(0.1) }.not_to raise_error
expect(subject.scanner_recv(0.1)).to eq(0)
expect(subject.results).to be_empty
expect { subject.scanner_recv(0.1) }.not_to raise_error
expect(subject.scanner_recv(0.1)).to eq(0)
expect(subject.results).to be_empty
end
end

it 'continues processing other readable sockets after one raises ECONNREFUSED' do
allow(::IO).to receive(:select).and_return([[refused_socket, responding_socket], [], []], nil)
[::Errno::ECONNREFUSED, ::Errno::ECONNRESET].each do |error_class|
it "continues processing other readable sockets after one raises #{error_class}" do
allow(::IO).to receive(:select).and_return([[error_socket(error_class), responding_socket], [], []], nil)

expect(subject.scanner_recv(0.1)).to eq(1)
expect(subject.results['192.0.2.5']).to eq(['response-data'])
expect(subject.scanner_recv(0.1)).to eq(1)
expect(subject.results['192.0.2.5']).to eq(['response-data'])
end
end
end
end
Loading