CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/spec/modules/auxiliary/scanner/ssh/ssh_login_spec.rb
Views: 1904
require 'rspec'1require 'metasploit/framework/login_scanner/ssh'23RSpec.describe 'SSH Login Check Scanner' do4include_context 'Msf::Simple::Framework#modules loading'56subject do7load_and_create_module(8module_type: 'auxiliary',9reference_name: 'scanner/ssh/ssh_login'10)11end1213describe '#rport' do14it 'returns the defined RPORT option' do15subject.options.add_options([Msf::Opt::RPORT(99)])16subject.import_defaults(false)1718expect(subject.rport).to eql 9919end20end2122describe '#session_setup' do23let(:credential) do24Metasploit::Framework::Credential.new(private: password, public: username)25end26let(:datastore) { Msf::ModuleDataStoreWithFallbacks.new(subject) }27let(:host) { '10.10.10.10' }28let(:module_manager) { instance_double(Msf::ModuleManager) }29let(:password) { 'secret' }30let(:platform) { 'unifi' }31let(:proof) { 'this is the proof' }32let(:result) do33Metasploit::Framework::LoginScanner::Result.new(34credential: credential,35proof: proof36)37end38let(:scanner) do39instance_double(40Metasploit::Framework::LoginScanner::SSH,41ssh_socket: ssh_session,42get_platform: platform,43host: host44)45end46let(:session_manager) do47instance_double(Msf::SessionManager, register: nil)48end49let(:ssh_command_shell_bind) do50instance_double(51Msf::Sessions::SshCommandShellBind,52alive: true,53arch: nil,54exploit_datastore: datastore,55exploit_task: nil,56exploit_uuid: nil,57info: nil,58platform: platform,59register?: true,60rstream: ssh_commandstream,61session_host: host,62session_port: nil,63set_from_exploit: nil,64sid: nil,65tunnel_peer: nil,66type: nil,67username: nil,68uuid: nil,69via_exploit: nil,70via_payload: nil,71workspace: 'default'72).as_null_object.tap do |mock|73allow(mock).to receive(:kind_of?) { |args| args == Msf::Session }74end75end76let(:ssh_commandstream) { instance_double(Net::SSH::CommandStream) }77let(:ssh_session) do78instance_double(Net::SSH::Connection::Session, transport: transport_session)79end80let(:socket) do81double(Object)82end83let(:transport_session) do84instance_double(Net::SSH::Transport::Session).tap do |mock|85allow(mock).to receive(:socket).and_return(socket)86end87end88let(:username) { 'root' }8990before(:each) do91allow(Msf::Sessions::SshCommandShellBind).to receive(:new).and_return(ssh_command_shell_bind)92# This is mocked as SessionManager appears to be directly or indirectly triggering the93# error for too many threads94allow(subject.framework).to receive(:sessions).and_return(session_manager)95end9697it 'requests the platform from the scanner' do98expect(scanner).to receive(:get_platform).with(proof)99100subject.session_setup(result, scanner)101end102103it 'instantiates a SshCommandShellBind instance' do104expect(Msf::Sessions::SshCommandShellBind).to receive(:new).with(ssh_session)105106subject.session_setup(result, scanner)107end108109it 'configures the SshCommandShellBind instance' do110expect(ssh_command_shell_bind).to receive(:set_from_exploit).with(subject)111112subject.session_setup(result, scanner)113end114115it 'updates the exploit datastore for the session' do116subject.session_setup(result, scanner)117118expect(datastore.search_for('USERNAME').value).to eql username119expect(datastore.search_for('PASSWORD').value).to eql password120end121122it 'deletes the ssh session from the collection of sockets' do123subject.add_socket(ssh_commandstream)124125subject.session_setup(result, scanner)126127expect(subject.send(:sockets)).to be_empty128end129130it 'registers the session' do131expect(session_manager).to receive(:register).with(ssh_command_shell_bind)132133subject.session_setup(result, scanner)134end135136it 'passes module datastore to bootstrap method of the SshCommandShellBind instance' do137expect(ssh_command_shell_bind).to receive(:bootstrap).with(subject.datastore)138139subject.session_setup(result, scanner)140end141142it 'processes any autoruns defined for the module' do143expect(ssh_command_shell_bind).to receive(:process_autoruns).with(subject.datastore)144145subject.session_setup(result, scanner)146end147148it 'registers the session open event' do149expect(ssh_command_shell_bind).to receive(:db_record=).with(an_instance_of(Mdm::Session))150151subject.session_setup(result, scanner)152end153154it 'deletes the ssh transport socket from the collection of sockets' do155subject.add_socket(socket)156157subject.session_setup(result, scanner)158159expect(subject.send(:sockets)).to be_empty160end161162it 'sets the platform on the SshCommandShellBind instance' do163expect(ssh_command_shell_bind).to receive(:platform=).with(platform)164165subject.session_setup(result, scanner)166end167168it 'returns a SshCommandShellBind instance' do169expect(subject.session_setup(result, scanner)).to eql ssh_command_shell_bind170end171172it 'reports the host' do173expect do174subject.session_setup(result, scanner)175end.to change(Mdm::Host, :count).by(1)176177expect(Mdm::Host.last.os_name).to eql platform178end179180context 'when scanner does not have an ssh connection' do181before(:each) do182allow(scanner).to receive(:ssh_socket).and_return(nil)183end184185it 'returns nil' do186expect(subject.session_setup(result, scanner)).to be_nil187end188end189190context 'when the scanner platform is set to `unknown`' do191let(:platform) { 'unknown' }192193it 'does not set the os_name for the Host record' do194subject.session_setup(result, scanner)195196expect(Mdm::Host.last.os_name).to be_nil197end198end199end200end201202203