c6656e4031
not strictly required, these conversions keep us up to date with latest rspec conventions and best practices which will prevent use from having to convert them when they become deprecated later
1008 lines
34 KiB
Ruby
1008 lines
34 KiB
Ruby
RSpec.shared_examples_for 'Msf::DBManager::Session' do
|
|
it { is_expected.to respond_to :get_session }
|
|
|
|
context '#report_session' do
|
|
let(:options) do
|
|
{}
|
|
end
|
|
|
|
subject(:report_session) do
|
|
db_manager.report_session(options)
|
|
end
|
|
|
|
context 'with active' do
|
|
let(:active) do
|
|
true
|
|
end
|
|
|
|
context 'with :session' do
|
|
before(:example) do
|
|
options[:session] = session
|
|
end
|
|
|
|
context 'with Msf::Session' do
|
|
include_context 'Metasploit::Framework::Spec::Constants cleaner'
|
|
|
|
let(:exploit_datastore) do
|
|
Msf::ModuleDataStore.new(module_instance).tap do |datastore|
|
|
datastore['ParentModule'] = parent_module_fullname
|
|
|
|
remote_port = rand(2 ** 16 - 1)
|
|
datastore['RPORT'] = remote_port
|
|
end
|
|
end
|
|
|
|
let(:host) do
|
|
FactoryGirl.create(:mdm_host, :workspace => session_workspace)
|
|
end
|
|
|
|
let(:module_instance) do
|
|
name = 'multi/handler'
|
|
|
|
d = double(
|
|
'Msf::Exploit',
|
|
user_data: user_data,
|
|
fullname: "exploit/#{name}",
|
|
framework: framework,
|
|
name: name
|
|
)
|
|
d
|
|
end
|
|
|
|
let(:options_workspace) do
|
|
FactoryGirl.create(:mdm_workspace)
|
|
end
|
|
|
|
let(:parent_module_fullname) do
|
|
"exploit/#{parent_module_name}"
|
|
end
|
|
|
|
let(:parent_module_name) do
|
|
'windows/smb/ms08_067_netapi'
|
|
end
|
|
|
|
let(:parent_path) do
|
|
Metasploit::Framework.root.join('modules').to_path
|
|
end
|
|
|
|
let(:session) do
|
|
session_class.new.tap do |session|
|
|
session.exploit = module_instance
|
|
session.exploit_datastore = exploit_datastore
|
|
session.info = 'Info'
|
|
session.platform = 'Platform'
|
|
session.session_host = host.address
|
|
session.sid = rand(100)
|
|
session.type = 'Session Type'
|
|
session.via_exploit = 'exploit/multi/handler'
|
|
session.via_payload = 'payload/single/windows/metsvc_bind_tcp'
|
|
session.workspace = session_workspace.name
|
|
end
|
|
end
|
|
|
|
let(:session_class) do
|
|
Class.new do
|
|
include Msf::Session
|
|
|
|
attr_accessor :arch
|
|
attr_accessor :exploit
|
|
attr_accessor :datastore
|
|
attr_accessor :platform
|
|
attr_accessor :type
|
|
attr_accessor :via_exploit
|
|
attr_accessor :via_payload
|
|
end
|
|
end
|
|
|
|
let(:session_workspace) do
|
|
FactoryGirl.create(:mdm_workspace)
|
|
end
|
|
|
|
before(:example) do
|
|
reference_name = 'multi/handler'
|
|
path = File.join(parent_path, 'exploits', reference_name)
|
|
|
|
# fake cache data for exploit/multi/handler so it can be loaded
|
|
framework.modules.send(
|
|
:module_info_by_path=,
|
|
{
|
|
path =>
|
|
{
|
|
:parent_path => parent_path,
|
|
:reference_name => reference_name,
|
|
:type => 'exploit',
|
|
}
|
|
}
|
|
)
|
|
|
|
FactoryGirl.create(
|
|
:mdm_module_detail,
|
|
:fullname => parent_module_fullname,
|
|
:name => parent_module_name
|
|
)
|
|
end
|
|
|
|
context 'with a run_id in user_data' do
|
|
before(:example) do
|
|
allow(db_manager).to receive(:create_match_for_vuln).and_return(nil)
|
|
end
|
|
|
|
let(:match_set) do
|
|
FactoryGirl.create(:automatic_exploitation_match_set, user: session_workspace.owner,workspace:session_workspace)
|
|
end
|
|
|
|
let(:run) do
|
|
FactoryGirl.create(:automatic_exploitation_run, workspace: session_workspace, match_set_id: match_set.id)
|
|
end
|
|
|
|
let(:user_data) do
|
|
{
|
|
run_id: run.id
|
|
}
|
|
end
|
|
|
|
context 'with :workspace' do
|
|
before(:example) do
|
|
options[:workspace] = options_workspace
|
|
end
|
|
|
|
it 'should not find workspace from session' do
|
|
expect(db_manager).not_to receive(:find_workspace)
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'without :workspace' do
|
|
it 'should find workspace from session' do
|
|
expect(db_manager).to receive(:find_workspace).with(session.workspace).and_call_original
|
|
|
|
report_session
|
|
end
|
|
|
|
it 'should pass session.workspace to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:workspace => session_workspace
|
|
)
|
|
).and_return(host)
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'with workspace from either :workspace or session' do
|
|
it 'should pass normalized host from session as :host to #find_or_create_host' do
|
|
normalized_host = double('Normalized Host')
|
|
expect(db_manager).to receive(:normalize_host).with(session).and_return(normalized_host)
|
|
# stub report_vuln so its use of find_or_create_host and normalize_host doesn't interfere.
|
|
expect(db_manager).to receive(:report_vuln)
|
|
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:host => normalized_host
|
|
)
|
|
).and_return(host)
|
|
|
|
report_session
|
|
end
|
|
|
|
context 'with session responds to arch' do
|
|
let(:arch) do
|
|
FactoryGirl.generate :mdm_host_arch
|
|
end
|
|
|
|
before(:example) do
|
|
allow(session).to receive(:arch).and_return(arch)
|
|
end
|
|
|
|
it 'should pass :arch to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:arch => arch
|
|
)
|
|
).and_call_original
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'without session responds to arch' do
|
|
it 'should not pass :arch to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_excluding(
|
|
:arch
|
|
)
|
|
).and_call_original
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
it 'should create an Mdm::Session' do
|
|
expect {
|
|
report_session
|
|
}.to change(Mdm::Session, :count).by(1)
|
|
end
|
|
|
|
it { is_expected.to be_an Mdm::Session }
|
|
|
|
it 'should set session.db_record to created Mdm::Session' do
|
|
mdm_session = report_session
|
|
|
|
expect(session.db_record).to eq mdm_session
|
|
end
|
|
|
|
context 'with session.via_exploit' do
|
|
|
|
it 'should create Mdm::Vuln' do
|
|
expect {
|
|
report_session
|
|
}.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
|
|
context 'created Mdm::Vuln' do
|
|
let(:mdm_session) do
|
|
Mdm::Session.last
|
|
end
|
|
|
|
let(:rport) do
|
|
nil
|
|
end
|
|
|
|
before(:example) do
|
|
Timecop.freeze
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
report_session
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:vuln) do
|
|
Mdm::Vuln.last
|
|
end
|
|
|
|
it { expect(subject.host).to eq(Mdm::Host.last) }
|
|
it { expect(subject.refs).to eq([]) }
|
|
it { expect(subject.exploited_at).to be_within(1.second).of(Time.now.utc) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
context "with session.exploit_datastore['ParentModule']" do
|
|
it { expect(subject.info).to eq("Exploited by #{parent_module_fullname} to create Session #{mdm_session.id}") }
|
|
it { expect(subject.name).to eq(parent_module_name) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
let(:reference_name) do
|
|
'windows/smb/ms08_067_netapi'
|
|
end
|
|
|
|
before(:example) do
|
|
path = File.join(
|
|
parent_path,
|
|
'exploits',
|
|
"#{reference_name}.rb"
|
|
)
|
|
type = 'exploit'
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
framework.modules.send(
|
|
:module_info_by_path=,
|
|
{
|
|
path =>
|
|
{
|
|
:parent_path => parent_path,
|
|
:reference_name => reference_name,
|
|
:type => type,
|
|
}
|
|
}
|
|
)
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
end
|
|
|
|
it { expect(subject.info).to eq("Exploited by #{session.via_exploit} to create Session #{mdm_session.id}") }
|
|
it { expect(subject.name).to eq(reference_name) }
|
|
end
|
|
|
|
context 'with RPORT' do
|
|
let(:rport) do
|
|
# use service.port instead of having service use rport so
|
|
# that service is forced to exist before call to
|
|
# report_service, which happens right after using rport in
|
|
# outer context's before(:each)
|
|
service.port
|
|
end
|
|
|
|
let(:service) do
|
|
FactoryGirl.create(
|
|
:mdm_service,
|
|
:host => host
|
|
)
|
|
end
|
|
|
|
it { expect(subject.service).to eq(service) }
|
|
end
|
|
|
|
context 'without RPORT' do
|
|
it { expect(subject.service).to be_nil }
|
|
end
|
|
end
|
|
|
|
context 'created Mdm::ExploitAttempt' do
|
|
let(:rport) do
|
|
nil
|
|
end
|
|
|
|
before(:example) do
|
|
Timecop.freeze
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
report_session
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:exploit_attempt) do
|
|
Mdm::ExploitAttempt.last
|
|
end
|
|
|
|
it { expect(subject.attempted_at).to be_within(1.second).of(Time.now.utc) }
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
|
it { expect(subject.session_id).to eq(Mdm::Session.last.id) }
|
|
it { expect(subject.exploited).to be_truthy }
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
|
it { expect(subject.vuln_id).to eq(Mdm::Vuln.last.id) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
context "with session.datastore['ParentModule']" do
|
|
it { expect(subject.module).to eq(parent_module_fullname) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
before(:example) do
|
|
session.via_exploit = parent_module_fullname
|
|
end
|
|
|
|
it { expect(subject.module).to eq(session.via_exploit) }
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'returned Mdm::Session' do
|
|
before(:example) do
|
|
Timecop.freeze
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:mdm_session) do
|
|
report_session
|
|
end
|
|
|
|
#
|
|
# Ensure session has attributes present so its on mdm_session are
|
|
# not just comparing nils.
|
|
#
|
|
|
|
it 'should have session.info present' do
|
|
expect(session.info).to be_present
|
|
end
|
|
|
|
it 'should have session.sid present' do
|
|
expect(session.sid).to be_present
|
|
end
|
|
|
|
it 'should have session.platform present' do
|
|
expect(session.platform).to be_present
|
|
end
|
|
|
|
it 'should have session.type present' do
|
|
expect(session.type).to be_present
|
|
end
|
|
|
|
it 'should have session.via_exploit present' do
|
|
expect(session.via_exploit).to be_present
|
|
end
|
|
|
|
it 'should have session.via_payload present' do
|
|
expect(session.via_exploit).to be_present
|
|
end
|
|
|
|
it { expect(subject.datastore).to eq(session.exploit_datastore.to_h) }
|
|
it { expect(subject.desc).to eq(session.info) }
|
|
it { expect(subject.host_id).to eq(Mdm::Host.last.id) }
|
|
it { expect(subject.last_seen).to be_within(1.second).of(Time.now.utc) }
|
|
it { expect(subject.local_id).to eq(session.sid) }
|
|
it { expect(subject.opened_at).to be_within(1.second).of(Time.now.utc) }
|
|
it { expect(subject.platform).to eq(session.platform) }
|
|
it { expect(subject.routes).to eq([]) }
|
|
it { expect(subject.stype).to eq(session.type) }
|
|
it { expect(subject.via_payload).to eq(session.via_payload) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
it "should have session.via_exploit of 'exploit/multi/handler'" do
|
|
expect(session.via_exploit).to eq 'exploit/multi/handler'
|
|
end
|
|
|
|
context "with session.exploit_datastore['ParentModule']" do
|
|
it "should have session.exploit_datastore['ParentModule']" do
|
|
expect(session.exploit_datastore['ParentModule']).not_to be_nil
|
|
end
|
|
|
|
it { expect(subject.via_exploit).to eq(parent_module_fullname) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
before(:example) do
|
|
reference_name = 'windows/smb/ms08_067_netapi'
|
|
path = File.join(
|
|
parent_path,
|
|
'exploits',
|
|
"#{reference_name}.rb"
|
|
)
|
|
type = 'exploit'
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
framework.modules.send(
|
|
:module_info_by_path=,
|
|
{
|
|
path =>
|
|
{
|
|
:parent_path => parent_path,
|
|
:reference_name => reference_name,
|
|
:type => type,
|
|
}
|
|
}
|
|
)
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
end
|
|
|
|
it "should not have session.via_exploit of 'exploit/multi/handler'" do
|
|
expect(session.via_exploit).not_to eq 'exploit/multi/handler'
|
|
end
|
|
|
|
it { expect(subject.via_exploit).to eq(session.via_exploit) }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without user_data' do
|
|
let(:user_data) { nil }
|
|
|
|
context 'with :workspace' do
|
|
before(:example) do
|
|
options[:workspace] = options_workspace
|
|
end
|
|
|
|
it 'should not find workspace from session' do
|
|
expect(db_manager).not_to receive(:find_workspace)
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'without :workspace' do
|
|
it 'should find workspace from session' do
|
|
expect(db_manager).to receive(:find_workspace).with(session.workspace).and_call_original
|
|
|
|
report_session
|
|
end
|
|
|
|
it 'should pass session.workspace to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:workspace => session_workspace
|
|
)
|
|
).and_return(host)
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'with workspace from either :workspace or session' do
|
|
it 'should pass normalized host from session as :host to #find_or_create_host' do
|
|
normalized_host = double('Normalized Host')
|
|
allow(db_manager).to receive(:normalize_host).with(session).and_return(normalized_host)
|
|
# stub report_vuln so its use of find_or_create_host and normalize_host doesn't interfere.
|
|
allow(db_manager).to receive(:report_vuln)
|
|
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:host => normalized_host
|
|
)
|
|
).and_return(host)
|
|
|
|
report_session
|
|
end
|
|
|
|
context 'with session responds to arch' do
|
|
let(:arch) do
|
|
FactoryGirl.generate :mdm_host_arch
|
|
end
|
|
|
|
before(:example) do
|
|
allow(session).to receive(:arch).and_return(arch)
|
|
end
|
|
|
|
it 'should pass :arch to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_including(
|
|
:arch => arch
|
|
)
|
|
).and_call_original
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
context 'without session responds to arch' do
|
|
it 'should not pass :arch to #find_or_create_host' do
|
|
expect(db_manager).to receive(:find_or_create_host).with(
|
|
hash_excluding(
|
|
:arch
|
|
)
|
|
).and_call_original
|
|
|
|
expect { report_session }.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
end
|
|
|
|
it 'should create an Mdm::Session' do
|
|
expect {
|
|
report_session
|
|
}.to change(Mdm::Session, :count).by(1)
|
|
end
|
|
|
|
it { is_expected.to be_an Mdm::Session }
|
|
|
|
it 'should set session.db_record to created Mdm::Session' do
|
|
mdm_session = report_session
|
|
|
|
expect(session.db_record).to eq mdm_session
|
|
end
|
|
|
|
context 'with session.via_exploit' do
|
|
|
|
it 'should create Mdm::Vuln' do
|
|
expect {
|
|
report_session
|
|
}.to change(Mdm::Vuln, :count).by(1)
|
|
end
|
|
|
|
context 'created Mdm::Vuln' do
|
|
let(:mdm_session) do
|
|
Mdm::Session.last
|
|
end
|
|
|
|
let(:rport) do
|
|
nil
|
|
end
|
|
|
|
before(:example) do
|
|
Timecop.freeze
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
report_session
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:vuln) do
|
|
Mdm::Vuln.last
|
|
end
|
|
|
|
it { expect(subject.host).to eq(Mdm::Host.last) }
|
|
it { expect(subject.refs).to eq([]) }
|
|
it { expect(subject.exploited_at).to be_within(1.second).of(Time.now.utc) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
context "with session.exploit_datastore['ParentModule']" do
|
|
it { expect(subject.info).to eq("Exploited by #{parent_module_fullname} to create Session #{mdm_session.id}") }
|
|
it { expect(subject.name).to eq(parent_module_name) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
let(:reference_name) do
|
|
'windows/smb/ms08_067_netapi'
|
|
end
|
|
|
|
before(:example) do
|
|
path = File.join(
|
|
parent_path,
|
|
'exploits',
|
|
"#{reference_name}.rb"
|
|
)
|
|
type = 'exploit'
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
framework.modules.send(
|
|
:module_info_by_path=,
|
|
{
|
|
path =>
|
|
{
|
|
:parent_path => parent_path,
|
|
:reference_name => reference_name,
|
|
:type => type,
|
|
}
|
|
}
|
|
)
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
end
|
|
|
|
it { expect(subject.info).to eq("Exploited by #{session.via_exploit} to create Session #{mdm_session.id}") }
|
|
it { expect(subject.name).to eq(reference_name) }
|
|
end
|
|
|
|
context 'with RPORT' do
|
|
let(:rport) do
|
|
# use service.port instead of having service use rport so
|
|
# that service is forced to exist before call to
|
|
# report_service, which happens right after using rport in
|
|
# outer context's before(:each)
|
|
service.port
|
|
end
|
|
|
|
let(:service) do
|
|
FactoryGirl.create(
|
|
:mdm_service,
|
|
:host => host
|
|
)
|
|
end
|
|
|
|
it { expect(subject.service).to eq(service) }
|
|
end
|
|
|
|
context 'without RPORT' do
|
|
it { expect(subject.service).to be_nil }
|
|
end
|
|
end
|
|
|
|
context 'created Mdm::ExploitAttempt' do
|
|
let(:rport) do
|
|
nil
|
|
end
|
|
|
|
before(:example) do
|
|
Timecop.freeze
|
|
|
|
session.exploit_datastore['RPORT'] = rport
|
|
|
|
report_session
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:exploit_attempt) do
|
|
Mdm::ExploitAttempt.last
|
|
end
|
|
|
|
it { expect(subject.attempted_at).to be_within(1.second).of(Time.now.utc) }
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
|
it { expect(subject.session_id).to eq(Mdm::Session.last.id) }
|
|
it { expect(subject.exploited).to be_truthy }
|
|
# @todo https://www.pivotaltracker.com/story/show/48362615
|
|
it { expect(subject.vuln_id).to eq(Mdm::Vuln.last.id) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
context "with session.datastore['ParentModule']" do
|
|
it { expect(subject.module).to eq(parent_module_fullname) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
before(:example) do
|
|
session.via_exploit = parent_module_fullname
|
|
end
|
|
|
|
it { expect(subject.module).to eq(session.via_exploit) }
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'returned Mdm::Session' do
|
|
before(:example) do
|
|
Timecop.freeze
|
|
end
|
|
|
|
after(:example) do
|
|
Timecop.return
|
|
end
|
|
|
|
subject(:mdm_session) do
|
|
report_session
|
|
end
|
|
|
|
#
|
|
# Ensure session has attributes present so its on mdm_session are
|
|
# not just comparing nils.
|
|
#
|
|
|
|
it 'should have session.info present' do
|
|
expect(session.info).to be_present
|
|
end
|
|
|
|
it 'should have session.sid present' do
|
|
expect(session.sid).to be_present
|
|
end
|
|
|
|
it 'should have session.platform present' do
|
|
expect(session.platform).to be_present
|
|
end
|
|
|
|
it 'should have session.type present' do
|
|
expect(session.type).to be_present
|
|
end
|
|
|
|
it 'should have session.via_exploit present' do
|
|
expect(session.via_exploit).to be_present
|
|
end
|
|
|
|
it 'should have session.via_payload present' do
|
|
expect(session.via_exploit).to be_present
|
|
end
|
|
|
|
it { expect(subject.datastore).to eq(session.exploit_datastore.to_h) }
|
|
it { expect(subject.desc).to eq(session.info) }
|
|
it { expect(subject.host_id).to eq(Mdm::Host.last.id) }
|
|
it { expect(subject.last_seen).to be_within(1.second).of(Time.now.utc) }
|
|
it { expect(subject.local_id).to eq(session.sid) }
|
|
it { expect(subject.opened_at).to be_within(1.second).of(Time.now.utc) }
|
|
it { expect(subject.platform).to eq(session.platform) }
|
|
it { expect(subject.routes).to eq([]) }
|
|
it { expect(subject.stype).to eq(session.type) }
|
|
it { expect(subject.via_payload).to eq(session.via_payload) }
|
|
|
|
context "with session.via_exploit 'exploit/multi/handler'" do
|
|
it "should have session.via_exploit of 'exploit/multi/handler'" do
|
|
expect(session.via_exploit).to eq 'exploit/multi/handler'
|
|
end
|
|
|
|
context "with session.exploit_datastore['ParentModule']" do
|
|
it "should have session.exploit_datastore['ParentModule']" do
|
|
expect(session.exploit_datastore['ParentModule']).not_to be_nil
|
|
end
|
|
|
|
it { expect(subject.via_exploit).to eq(parent_module_fullname) }
|
|
end
|
|
end
|
|
|
|
context "without session.via_exploit 'exploit/multi/handler'" do
|
|
before(:example) do
|
|
reference_name = 'windows/smb/ms08_067_netapi'
|
|
path = File.join(
|
|
parent_path,
|
|
'exploits',
|
|
"#{reference_name}.rb"
|
|
)
|
|
type = 'exploit'
|
|
|
|
# fake cache data for ParentModule so it can be loaded
|
|
framework.modules.send(
|
|
:module_info_by_path=,
|
|
{
|
|
path =>
|
|
{
|
|
:parent_path => parent_path,
|
|
:reference_name => reference_name,
|
|
:type => type,
|
|
}
|
|
}
|
|
)
|
|
|
|
session.via_exploit = "#{type}/#{reference_name}"
|
|
end
|
|
|
|
it "should not have session.via_exploit of 'exploit/multi/handler'" do
|
|
expect(session.via_exploit).not_to eq 'exploit/multi/handler'
|
|
end
|
|
|
|
it { expect(subject.via_exploit).to eq(session.via_exploit) }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without Msf::Session' do
|
|
let(:session) do
|
|
double('Not a Msf::Session')
|
|
end
|
|
|
|
it 'should raise ArgumentError' do
|
|
expect {
|
|
report_session
|
|
}.to raise_error(ArgumentError, "Invalid :session, expected Msf::Session")
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without :session' do
|
|
context 'with :host' do
|
|
before(:example) do
|
|
options[:host] = host
|
|
end
|
|
|
|
context 'with Mdm::Host' do
|
|
let(:host) do
|
|
FactoryGirl.create(:mdm_host)
|
|
end
|
|
|
|
context 'created Mdm::Session' do
|
|
let(:closed_at) do
|
|
nil
|
|
end
|
|
|
|
let(:close_reason) do
|
|
'Closed because...'
|
|
end
|
|
|
|
let(:description) do
|
|
'Session Description'
|
|
end
|
|
|
|
let(:exploit_full_name) do
|
|
'exploit/windows/smb/ms08_067_netapi'
|
|
end
|
|
|
|
let(:last_seen) do
|
|
nil
|
|
end
|
|
|
|
let(:opened_at) do
|
|
Time.now.utc - 5.minutes
|
|
end
|
|
|
|
let(:payload_full_name) do
|
|
'payload/singles/windows/metsvc_reverse_tcp'
|
|
end
|
|
|
|
let(:platform) do
|
|
'Host Platform'
|
|
end
|
|
|
|
let(:routes) do
|
|
nil
|
|
end
|
|
|
|
let(:session_type) do
|
|
'Session Type'
|
|
end
|
|
|
|
before(:example) do
|
|
options[:closed_at] = closed_at
|
|
options[:close_reason] = close_reason
|
|
options[:desc] = description
|
|
options[:last_seen] = last_seen
|
|
options[:opened_at] = opened_at
|
|
options[:platform] = platform
|
|
options[:routes] = routes
|
|
options[:stype] = session_type
|
|
options[:via_payload] = payload_full_name
|
|
options[:via_exploit] = exploit_full_name
|
|
end
|
|
|
|
subject(:mdm_session) do
|
|
report_session
|
|
end
|
|
|
|
it { expect(subject.close_reason).to eq(close_reason) }
|
|
it { expect(subject.desc).to eq(description) }
|
|
it { expect(subject.host).to eq(host) }
|
|
it { expect(subject.platform).to eq(platform) }
|
|
it { expect(subject.stype).to eq(session_type) }
|
|
it { expect(subject.via_exploit).to eq(exploit_full_name) }
|
|
it { expect(subject.via_payload).to eq(payload_full_name) }
|
|
|
|
context 'with :last_seen' do
|
|
let(:last_seen) do
|
|
opened_at
|
|
end
|
|
|
|
it { expect(subject.last_seen).to eq(last_seen) }
|
|
end
|
|
|
|
context 'with :closed_at' do
|
|
let(:closed_at) do
|
|
opened_at + 1.minute
|
|
end
|
|
|
|
it { expect(subject.closed_at).to eq(closed_at) }
|
|
end
|
|
|
|
context 'without :closed_at' do
|
|
it { expect(subject.closed_at).to be_nil }
|
|
end
|
|
|
|
context 'without :last_seen' do
|
|
context 'with :closed_at' do
|
|
let(:closed_at) do
|
|
opened_at + 1.minute
|
|
end
|
|
|
|
it { expect(subject.last_seen).to eq(closed_at) }
|
|
end
|
|
|
|
context 'without :closed_at' do
|
|
it { expect(subject.last_seen).to be_nil }
|
|
end
|
|
end
|
|
|
|
context 'with :routes' do
|
|
let(:routes) do
|
|
FactoryGirl.build_list(
|
|
:mdm_route,
|
|
1,
|
|
:session => nil
|
|
)
|
|
end
|
|
|
|
it { expect(subject.routes.to_a).to eq(routes) }
|
|
end
|
|
|
|
context 'without :routes' do
|
|
it { expect(subject.routes).to eq([]) }
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without Mdm::Host' do
|
|
let(:host) do
|
|
'192.168.0.1'
|
|
end
|
|
|
|
it 'should raise ArgumentError' do
|
|
expect {
|
|
report_session
|
|
}.to raise_error(ArgumentError, "Invalid :host, expected Host object")
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without :host' do
|
|
it 'should raise ArgumentError' do
|
|
expect {
|
|
report_session
|
|
}.to raise_error(ArgumentError)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'without active' do
|
|
let(:active) do
|
|
false
|
|
end
|
|
|
|
it { is_expected.to be_nil }
|
|
|
|
it 'should not create a connection' do
|
|
expect(ActiveRecord::Base.connection_pool).not_to receive(:with_connection)
|
|
|
|
report_session
|
|
end
|
|
end
|
|
end
|
|
end
|