@@ -48,4 +48,6 @@ group :test do
|
||||
# code coverage for tests
|
||||
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
|
||||
gem 'simplecov', '0.5.4', :require => false
|
||||
# Manipulate Time.now in specs
|
||||
gem 'timecop'
|
||||
end
|
||||
|
||||
@@ -52,6 +52,7 @@ GEM
|
||||
multi_json (~> 1.0.3)
|
||||
simplecov-html (~> 0.5.3)
|
||||
simplecov-html (0.5.3)
|
||||
timecop (0.6.1)
|
||||
tzinfo (0.3.37)
|
||||
yard (0.8.5.2)
|
||||
|
||||
@@ -75,4 +76,5 @@ DEPENDENCIES
|
||||
rspec (>= 2.12)
|
||||
shoulda-matchers
|
||||
simplecov (= 0.5.4)
|
||||
timecop
|
||||
yard
|
||||
|
||||
+61
-6
@@ -645,12 +645,69 @@ class DBManager
|
||||
}
|
||||
end
|
||||
|
||||
# Record a new session in the database
|
||||
# @note The Mdm::Session#desc will be truncated to 255 characters.
|
||||
# @todo https://www.pivotaltracker.com/story/show/48249739
|
||||
#
|
||||
# opts MUST contain either
|
||||
# +:session+:: the Msf::Session object we are reporting
|
||||
# +:host+:: the Host object we are reporting a session on.
|
||||
# @overload report_session(opts)
|
||||
# Creates an Mdm::Session from Msf::Session. If +via_exploit+ is set on the
|
||||
# +session+, then an Mdm::Vuln and Mdm::ExploitAttempt is created for the
|
||||
# session's host. The Mdm::Host for the +session_host+ is created using
|
||||
# The session.session_host, +session.arch+ (if +session+ responds to arch),
|
||||
# and the workspace derived from opts or the +session+. The Mdm::Session is
|
||||
# assumed to be +last_seen+ and +opened_at+ at the time report_session is
|
||||
# called. +session.exploit_datastore['ParentModule']+ is used for the
|
||||
# Mdm::Session#via_exploit if +session.via_exploit+ is
|
||||
# 'exploit/multi/handler'.
|
||||
#
|
||||
# @param opts [Hash{Symbol => Object}] options
|
||||
# @option opt [Msf::Session, #datastore, #platform, #type, #via_exploit, #via_payload] :session
|
||||
# The in-memory session to persist to the database.
|
||||
# @option opts [Mdm::Workspace] :workspace The workspace for in which the
|
||||
# :session host is contained. Also used as the workspace for the
|
||||
# Mdm::ExploitAttempt and Mdm::Vuln. Defaults to Mdm::Worksapce with
|
||||
# Mdm::Workspace#name equal to +session.workspace+.
|
||||
# @return [nil] if {Msf::DBManager#active} is +false+.
|
||||
# @return [Mdm::Session] if session is saved
|
||||
# @raise [ArgumentError] if :session is not an {Msf::Session}.
|
||||
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
|
||||
# saved, in which case, the Mdm::ExploitAttempt and Mdm::Vuln will not be
|
||||
# created, but the Mdm::Host will have been. (There is no transaction
|
||||
# to rollback the Mdm::Host creation.)
|
||||
# @see #find_or_create_host
|
||||
# @see #normalize_host
|
||||
# @see #report_exploit_success
|
||||
# @see #report_vuln
|
||||
#
|
||||
# @overload report_session(opts)
|
||||
# Creates an Mdm::Session from Mdm::Host.
|
||||
#
|
||||
# @param opts [Hash{Symbol => Object}] options
|
||||
# @option opts [DateTime, Time] :closed_at The date and time the sesion was
|
||||
# closed.
|
||||
# @option opts [String] :close_reason Reason the session was closed.
|
||||
# @option opts [Hash] :datastore {Msf::DataStore#to_h}.
|
||||
# @option opts [String] :desc Session description. Will be truncated to 255
|
||||
# characters.
|
||||
# @option opts [Mdm::Host] :host The host on which the session was opened.
|
||||
# @option opts [DateTime, Time] :last_seen The last date and time the
|
||||
# session was seen to be open. Defaults to :closed_at's value.
|
||||
# @option opts [DateTime, Time] :opened_at The date and time that the
|
||||
# session was opened.
|
||||
# @option opts [String] :platform The platform of the host.
|
||||
# @option opts [Array] :routes ([]) The routes through the session for
|
||||
# pivoting.
|
||||
# @option opts [String] :stype Session type.
|
||||
# @option opts [String] :via_exploit The {Msf::Module#fullname} of the
|
||||
# exploit that was used to open the session.
|
||||
# @option option [String] :via_payload the {MSf::Module#fullname} of the
|
||||
# payload sent to the host when the exploit was successful.
|
||||
# @return [nil] if {Msf::DBManager#active} is +false+.
|
||||
# @return [Mdm::Session] if session is saved.
|
||||
# @raise [ArgumentError] if :host is not an Mdm::Host.
|
||||
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
|
||||
# saved.
|
||||
#
|
||||
# @raise ArgumentError if :host and :session is +nil+
|
||||
def report_session(opts)
|
||||
return if not active
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
@@ -719,8 +776,6 @@ class DBManager
|
||||
|
||||
# If this is a live session, we know the host is vulnerable to something.
|
||||
if opts[:session] and session.via_exploit
|
||||
return unless host
|
||||
|
||||
mod = framework.modules.create(session.via_exploit)
|
||||
|
||||
if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule']
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
FactoryGirl.define do
|
||||
factory :mdm_route, :class => Mdm::Route do
|
||||
netmask { generate :mdm_route_netmask }
|
||||
subnet { generate :mdm_route_subnet }
|
||||
|
||||
#
|
||||
# Associations
|
||||
#
|
||||
association :session, :factory => :mdm_session
|
||||
end
|
||||
|
||||
sequence :mdm_route_netmask do |n|
|
||||
bits = 32
|
||||
bitmask = n % bits
|
||||
|
||||
[ (~((2 ** (bits - bitmask)) - 1)) & 0xffffffff ].pack('N').unpack('CCCC').join('.')
|
||||
|
||||
bits = 32
|
||||
shift = n % bits
|
||||
mask_range = 2 ** bits
|
||||
full_mask = mask_range - 1
|
||||
|
||||
integer_netmask = (full_mask << shift)
|
||||
formatted_netmask = [integer_netmask].pack('N').unpack('CCCC').join('.')
|
||||
|
||||
formatted_netmask
|
||||
end
|
||||
|
||||
sequence :mdm_route_subnet do |n|
|
||||
class_c_network = n % 255
|
||||
|
||||
"192.168.#{class_c_network}.0"
|
||||
end
|
||||
end
|
||||
@@ -19,4 +19,665 @@ describe Msf::DBManager do
|
||||
end
|
||||
|
||||
it_should_behave_like 'Msf::DBManager::ImportMsfXml'
|
||||
|
||||
context '#report_session' do
|
||||
include_context 'DatabaseCleaner'
|
||||
|
||||
let(:options) do
|
||||
{}
|
||||
end
|
||||
|
||||
subject(:report_session) do
|
||||
db_manager.report_session(options)
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
configurations = Metasploit::Framework::Database.configurations
|
||||
spec = configurations[Metasploit::Framework.env]
|
||||
|
||||
# Need to connect or ActiveRecord::Base.connection_pool will raise an
|
||||
# error.
|
||||
db_manager.connect(spec)
|
||||
|
||||
db_manager.stub(:active => active)
|
||||
end
|
||||
|
||||
context 'with active' do
|
||||
let(:active) do
|
||||
true
|
||||
end
|
||||
|
||||
it 'should create connection' do
|
||||
# 1st time from with_established_connection
|
||||
# 2nd time from report_session
|
||||
ActiveRecord::Base.connection_pool.should_receive(:with_connection).exactly(2).times
|
||||
|
||||
report_session
|
||||
end
|
||||
|
||||
context 'with :session' do
|
||||
before(:each) do
|
||||
options[:session] = session
|
||||
end
|
||||
|
||||
context 'with Msf::Session' do
|
||||
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'
|
||||
|
||||
mock(
|
||||
'Msf::Module',
|
||||
:fullname => "exploit/#{name}",
|
||||
:framework => framework,
|
||||
:name => name
|
||||
)
|
||||
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_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 :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(:each) 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 :workspace' do
|
||||
before(:each) do
|
||||
options[:workspace] = options_workspace
|
||||
end
|
||||
|
||||
it 'should not find workspace from session' do
|
||||
db_manager.should_not_receive(:find_workspace)
|
||||
|
||||
report_session
|
||||
end
|
||||
end
|
||||
|
||||
context 'without :workspace' do
|
||||
it 'should find workspace from session' do
|
||||
db_manager.should_receive(:find_workspace).with(session.workspace).and_call_original
|
||||
|
||||
report_session
|
||||
end
|
||||
|
||||
it 'should pass session.workspace to #find_or_create_host' do
|
||||
db_manager.should_receive(:find_or_create_host).with(
|
||||
hash_including(
|
||||
:workspace => session_workspace
|
||||
)
|
||||
).and_return(host)
|
||||
|
||||
report_session
|
||||
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 = mock('Normalized Host')
|
||||
db_manager.stub(: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.
|
||||
db_manager.stub(:report_vuln)
|
||||
|
||||
db_manager.should_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
|
||||
'Arch'
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
session.stub(:arch => arch)
|
||||
end
|
||||
|
||||
it 'should pass :arch to #find_or_create_host' do
|
||||
db_manager.should_receive(:find_or_create_host).with(
|
||||
hash_including(
|
||||
:arch => arch
|
||||
)
|
||||
).and_call_original
|
||||
|
||||
report_session
|
||||
end
|
||||
end
|
||||
|
||||
context 'without session responds to arch' do
|
||||
it 'should not pass :arch to #find_or_create_host' do
|
||||
db_manager.should_receive(:find_or_create_host).with(
|
||||
hash_excluding(
|
||||
:arch
|
||||
)
|
||||
).and_call_original
|
||||
|
||||
report_session
|
||||
end
|
||||
end
|
||||
|
||||
it 'should create an Mdm::Session' do
|
||||
expect {
|
||||
report_session
|
||||
}.to change(Mdm::Session, :count).by(1)
|
||||
end
|
||||
|
||||
it { should be_an Mdm::Session }
|
||||
|
||||
it 'should set session.db_record to created Mdm::Session' do
|
||||
mdm_session = report_session
|
||||
|
||||
session.db_record.should == mdm_session
|
||||
end
|
||||
|
||||
context 'with session.via_exploit' do
|
||||
it 'should create session.via_exploit module' do
|
||||
framework.modules.should_receive(:create).with(session.via_exploit).and_call_original
|
||||
|
||||
report_session
|
||||
end
|
||||
|
||||
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(:each) do
|
||||
Timecop.freeze
|
||||
|
||||
session.exploit_datastore['RPORT'] = rport
|
||||
|
||||
report_session
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
subject(:vuln) do
|
||||
Mdm::Vuln.last
|
||||
end
|
||||
|
||||
its(:host) { should == Mdm::Host.last }
|
||||
its(:refs) { should == [] }
|
||||
its(:exploited_at) { should == Time.now.utc }
|
||||
|
||||
context "with session.via_exploit 'exploit/multi/handler'" do
|
||||
context "with session.exploit_datastore['ParentModule']" do
|
||||
its(:info) { should == "Exploited by #{parent_module_fullname} to create Session #{mdm_session.id}" }
|
||||
its(:name) { should == 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(:each) 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
|
||||
|
||||
its(:info) { should == "Exploited by #{session.via_exploit} to create Session #{mdm_session.id}"}
|
||||
its(:name) { should == 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
|
||||
|
||||
its(:service) { should == service }
|
||||
end
|
||||
|
||||
context 'without RPORT' do
|
||||
its(:service) { should be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'created Mdm::ExploitAttempt' do
|
||||
let(:rport) do
|
||||
nil
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
Timecop.freeze
|
||||
|
||||
session.exploit_datastore['RPORT'] = rport
|
||||
|
||||
report_session
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
Timecop.return
|
||||
end
|
||||
|
||||
subject(:exploit_attempt) do
|
||||
Mdm::ExploitAttempt.last
|
||||
end
|
||||
|
||||
its(:attempted_at) { should == Time.now.utc }
|
||||
# @todo https://www.pivotaltracker.com/story/show/48362615
|
||||
its(:session_id) { should == Mdm::Session.last.id }
|
||||
its(:exploited) { should == true }
|
||||
# @todo https://www.pivotaltracker.com/story/show/48362615
|
||||
its(:vuln_id) { should == Mdm::Vuln.last.id }
|
||||
|
||||
context "with session.via_exploit 'exploit/multi/handler'" do
|
||||
context "with session.datastore['ParentModule']" do
|
||||
its(:module) { should == parent_module_fullname }
|
||||
end
|
||||
end
|
||||
|
||||
context "without session.via_exploit 'exploit/multi/handler'" do
|
||||
before(:each) do
|
||||
session.via_exploit = parent_module_fullname
|
||||
end
|
||||
|
||||
its(:module) { should == session.via_exploit }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'returned Mdm::Session' do
|
||||
before(:each) do
|
||||
Timecop.freeze
|
||||
end
|
||||
|
||||
after(:each) 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
|
||||
session.info.should be_present
|
||||
end
|
||||
|
||||
it 'should have session.sid present' do
|
||||
session.sid.should be_present
|
||||
end
|
||||
|
||||
it 'should have session.platform present' do
|
||||
session.platform.should be_present
|
||||
end
|
||||
|
||||
it 'should have session.type present' do
|
||||
session.type.should be_present
|
||||
end
|
||||
|
||||
it 'should have session.via_exploit present' do
|
||||
session.via_exploit.should be_present
|
||||
end
|
||||
|
||||
it 'should have session.via_payload present' do
|
||||
session.via_exploit.should be_present
|
||||
end
|
||||
|
||||
its(:datastore) { should == session.exploit_datastore.to_h }
|
||||
its(:desc) { should == session.info }
|
||||
its(:host_id) { should == Mdm::Host.last.id }
|
||||
its(:last_seen) { should == Time.now.utc }
|
||||
its(:local_id) { should == session.sid }
|
||||
its(:opened_at) { should == Time.now.utc }
|
||||
its(:platform) { should == session.platform }
|
||||
its(:routes) { should == [] }
|
||||
its(:stype) { should == session.type }
|
||||
its(:via_payload) { should == session.via_payload }
|
||||
|
||||
context "with session.via_exploit 'exploit/multi/handler'" do
|
||||
it "should have session.via_exploit of 'exploit/multi/handler'" do
|
||||
session.via_exploit.should == 'exploit/multi/handler'
|
||||
end
|
||||
|
||||
context "with session.exploit_datastore['ParentModule']" do
|
||||
it "should have session.exploit_datastore['ParentModule']" do
|
||||
session.exploit_datastore['ParentModule'].should_not be_nil
|
||||
end
|
||||
|
||||
its(:via_exploit) { should == parent_module_fullname }
|
||||
end
|
||||
end
|
||||
|
||||
context "without session.via_exploit 'exploit/multi/handler'" do
|
||||
before(:each) 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
|
||||
session.via_exploit.should_not == 'exploit/multi/handler'
|
||||
end
|
||||
|
||||
its(:via_exploit) { should == session.via_exploit }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'without Msf::Session' do
|
||||
let(:session) do
|
||||
mock('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(:each) 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(:each) 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
|
||||
|
||||
its(:close_reason) { should == close_reason }
|
||||
its(:desc) { should == description }
|
||||
its(:host) { should == host }
|
||||
its(:platform) { should == platform }
|
||||
its(:stype) { should == session_type }
|
||||
its(:via_exploit) { should == exploit_full_name }
|
||||
its(:via_payload) { should == payload_full_name }
|
||||
|
||||
context 'with :last_seen' do
|
||||
let(:last_seen) do
|
||||
opened_at
|
||||
end
|
||||
|
||||
its(:last_seen) { should == last_seen }
|
||||
end
|
||||
|
||||
context 'with :closed_at' do
|
||||
let(:closed_at) do
|
||||
opened_at + 1.minute
|
||||
end
|
||||
|
||||
its(:closed_at) { should == closed_at }
|
||||
end
|
||||
|
||||
context 'without :closed_at' do
|
||||
its(:closed_at) { should == nil }
|
||||
end
|
||||
|
||||
context 'without :last_seen' do
|
||||
context 'with :closed_at' do
|
||||
let(:closed_at) do
|
||||
opened_at + 1.minute
|
||||
end
|
||||
|
||||
its(:last_seen) { should == closed_at }
|
||||
end
|
||||
|
||||
context 'without :closed_at' do
|
||||
its(:last_seen) { should be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with :routes' do
|
||||
let(:routes) do
|
||||
FactoryGirl.build_list(
|
||||
:mdm_route,
|
||||
1,
|
||||
:session => nil
|
||||
)
|
||||
end
|
||||
|
||||
its(:routes) { should == routes }
|
||||
end
|
||||
|
||||
context 'without :routes' do
|
||||
its(:routes) { should == [] }
|
||||
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 { should be_nil }
|
||||
|
||||
it 'should not create a connection' do
|
||||
# 1st time for with_established_connection
|
||||
ActiveRecord::Base.connection_pool.should_receive(:with_connection).once
|
||||
|
||||
report_session
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user