refactoring conditional logic
the class works but the conditional logic needs refactoring to be smoothed out more.bug/bundler_fix
parent
4e76330643
commit
f84d763382
|
@ -1,4 +1,5 @@
|
|||
require 'metasploit/framework/tcp/client'
|
||||
require 'rex/proto/rfb'
|
||||
require 'metasploit/framework/login_scanner/base'
|
||||
require 'metasploit/framework/login_scanner/rex_socket'
|
||||
|
||||
|
@ -13,7 +14,84 @@ module Metasploit
|
|||
include Metasploit::Framework::LoginScanner::RexSocket
|
||||
include Metasploit::Framework::Tcp::Client
|
||||
|
||||
# This method attempts a single login with a single credential against the target
|
||||
# @param credential [Credential] The credential object to attmpt to login with
|
||||
# @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object
|
||||
def attempt_login(credential)
|
||||
result_options = {
|
||||
credential: credential
|
||||
}
|
||||
|
||||
begin
|
||||
# Make our initial socket to the target
|
||||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
# Create our VNC client overtop of the socket
|
||||
vnc = Rex::Proto::RFB::Client.new(sock, :allow_none => false)
|
||||
|
||||
|
||||
if vnc.handshake
|
||||
if vnc_auth(vnc,credential.private)
|
||||
result_options[:status] = :success
|
||||
else
|
||||
result_options.merge!({
|
||||
status: :failed,
|
||||
proof: vnc.error
|
||||
})
|
||||
end
|
||||
else
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: vnc.error
|
||||
})
|
||||
end
|
||||
rescue ::EOFError, Rex::AddressInUse, Rex::ConnectionError, Rex::ConnectionTimeout, ::Timeout::Error => e
|
||||
result_options.merge!({
|
||||
status: :connection_error,
|
||||
proof: e.message
|
||||
})
|
||||
end
|
||||
::Metasploit::Framework::LoginScanner::Result.new(result_options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# This method checks the VNC error to see if we should wait and retry
|
||||
# @param error [String] The VNC error message received
|
||||
# @return [Boolean] whether or not we should attempt the retry
|
||||
def retry?(error)
|
||||
return true if error =~ /connection has been rejected/ # UltraVNC
|
||||
return true if error =~ /Too many security failures/ # vnc4server
|
||||
false
|
||||
end
|
||||
|
||||
# This method sets the sane defaults for things
|
||||
# like timeouts and TCP evasion options
|
||||
def set_sane_defaults
|
||||
self.max_send_size = 0 if self.max_send_size.nil?
|
||||
self.send_delay = 0 if self.send_delay.nil?
|
||||
end
|
||||
|
||||
# This method attempts the actual VNC authentication. It has built in retries to handle
|
||||
# delays built into the VNC RFB authentication.
|
||||
# @param client [Rex::Proto::RFB::Client] The VNC client object to authenticate through
|
||||
# @param password [String] the password to attempt the authentication with
|
||||
def vnc_auth(client,password)
|
||||
success = false
|
||||
5.times do |n|
|
||||
if client.authenticate(password)
|
||||
success = true
|
||||
break
|
||||
end
|
||||
break unless retry?(client.error)
|
||||
|
||||
# Wait for an increasing ammount of time before retrying
|
||||
delay = (2**(n+1)) + 1
|
||||
select(nil, nil, nil, delay)
|
||||
end
|
||||
success
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2,10 +2,70 @@ require 'spec_helper'
|
|||
require 'metasploit/framework/login_scanner/vnc'
|
||||
|
||||
describe Metasploit::Framework::LoginScanner::VNC do
|
||||
|
||||
let(:private) { 'password' }
|
||||
let(:blank) { '' }
|
||||
let(:test_cred) {
|
||||
Metasploit::Framework::LoginScanner::Credential.new( paired: false, private: private )
|
||||
}
|
||||
let(:blank_cred) {
|
||||
Metasploit::Framework::LoginScanner::Credential.new( paired: false, private: blank )
|
||||
}
|
||||
subject(:login_scanner) { described_class.new }
|
||||
|
||||
it_behaves_like 'Metasploit::Framework::LoginScanner::Base'
|
||||
it_behaves_like 'Metasploit::Framework::LoginScanner::RexSocket'
|
||||
|
||||
|
||||
context '#attempt_login' do
|
||||
it 'creates a new RFB client' do
|
||||
Rex::Proto::RFB::Client.should_receive(:new).and_call_original
|
||||
login_scanner.attempt_login(test_cred)
|
||||
end
|
||||
|
||||
context 'when the socket errors' do
|
||||
it 'returns a connection_error result for an EOFError' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:connect).and_raise ::EOFError
|
||||
result = my_scanner.attempt_login(test_cred)
|
||||
expect(result.status).to eq :connection_error
|
||||
expect(result.proof).to eq ::EOFError.new.to_s
|
||||
end
|
||||
|
||||
it 'returns a connection_error result for an Rex::AddressInUse' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:connect).and_raise ::Rex::AddressInUse
|
||||
result = my_scanner.attempt_login(test_cred)
|
||||
expect(result.status).to eq :connection_error
|
||||
expect(result.proof).to eq ::Rex::AddressInUse.new.to_s
|
||||
end
|
||||
|
||||
it 'returns a connection_error result for an Rex::ConnectionError' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:connect).and_raise ::Rex::ConnectionError
|
||||
result = my_scanner.attempt_login(test_cred)
|
||||
expect(result.status).to eq :connection_error
|
||||
expect(result.proof).to eq ::Rex::ConnectionError.new.to_s
|
||||
end
|
||||
|
||||
it 'returns a connection_error result for an Rex::ConnectionTimeout' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:connect).and_raise ::Rex::ConnectionTimeout
|
||||
result = my_scanner.attempt_login(test_cred)
|
||||
expect(result.status).to eq :connection_error
|
||||
expect(result.proof).to eq ::Rex::ConnectionTimeout.new.to_s
|
||||
end
|
||||
|
||||
it 'returns a connection_error result for an ::Timeout::Error' do
|
||||
my_scanner = login_scanner
|
||||
my_scanner.should_receive(:connect).and_raise ::Timeout::Error
|
||||
result = my_scanner.attempt_login(test_cred)
|
||||
expect(result.status).to eq :connection_error
|
||||
expect(result.proof).to eq ::Timeout::Error.new.to_s
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue