Skip to content

Commit e5befb7

Browse files
committed
Msf::DBManager#report_session specs
[#47979793]
1 parent 2c68100 commit e5befb7

File tree

5 files changed

+762
-8
lines changed

5 files changed

+762
-8
lines changed

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,6 @@ group :test do
4848
# code coverage for tests
4949
# any version newer than 0.5.4 gives an Encoding error when trying to read the source files.
5050
gem 'simplecov', '0.5.4', :require => false
51+
# Manipulate Time.now in specs
52+
gem 'timecop'
5153
end

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ GEM
5252
multi_json (~> 1.0.3)
5353
simplecov-html (~> 0.5.3)
5454
simplecov-html (0.5.3)
55+
timecop (0.6.1)
5556
tzinfo (0.3.37)
5657
yard (0.8.5.2)
5758

@@ -75,4 +76,5 @@ DEPENDENCIES
7576
rspec (>= 2.12)
7677
shoulda-matchers
7778
simplecov (= 0.5.4)
79+
timecop
7880
yard

lib/msf/core/db.rb

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,69 @@ def get_session(opts)
645645
}
646646
end
647647

648-
# Record a new session in the database
649-
#
650-
# opts MUST contain either
651-
# +:session+:: the Msf::Session object we are reporting
652-
# +:host+:: the Host object we are reporting a session on.
653-
#
648+
# @note The Mdm::Session#desc will be truncated to 255 characters.
649+
# @todo https://www.pivotaltracker.com/story/show/48249739
650+
#
651+
# @overload report_session(opts)
652+
# Creates an Mdm::Session from Msf::Session. If +via_exploit+ is set on the
653+
# +session+, then an Mdm::Vuln and Mdm::ExploitAttempt is created for the
654+
# session's host. The Mdm::Host for the +session_host+ is created using
655+
# The session.session_host, +session.arch+ (if +session+ responds to arch),
656+
# and the workspace derived from opts or the +session+. The Mdm::Session is
657+
# assumed to be +last_seen+ and +opened_at+ at the time report_session is
658+
# called. +session.exploit_datastore['ParentModule']+ is used for the
659+
# Mdm::Session#via_exploit if +session.via_exploit+ is
660+
# 'exploit/multi/handler'.
661+
#
662+
# @param opts [Hash{Symbol => Object}] options
663+
# @option opt [Msf::Session, #datastore, #platform, #type, #via_exploit, #via_payload] :session
664+
# The in-memory session to persist to the database.
665+
# @option opts [Mdm::Workspace] :workspace The workspace for in which the
666+
# :session host is contained. Also used as the workspace for the
667+
# Mdm::ExploitAttempt and Mdm::Vuln. Defaults to Mdm::Worksapce with
668+
# Mdm::Workspace#name equal to +session.workspace+.
669+
# @return [nil] if {Msf::DBManager#active} is +false+.
670+
# @return [Mdm::Session] if session is saved
671+
# @raise [ArgumentError] if :session is not an {Msf::Session}.
672+
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
673+
# saved, in which case, the Mdm::ExploitAttempt and Mdm::Vuln will not be
674+
# created, but the Mdm::Host will have been. (There is no transaction
675+
# to rollback the Mdm::Host creation.)
676+
# @see #find_or_create_host
677+
# @see #normalize_host
678+
# @see #report_exploit_success
679+
# @see #report_vuln
680+
#
681+
# @overload report_session(opts)
682+
# Creates an Mdm::Session from Mdm::Host.
683+
#
684+
# @param opts [Hash{Symbol => Object}] options
685+
# @option opts [DateTime, Time] :closed_at The date and time the sesion was
686+
# closed.
687+
# @option opts [String] :close_reason Reason the session was closed.
688+
# @option opts [Hash] :datastore {Msf::DataStore#to_h}.
689+
# @option opts [String] :desc Session description. Will be truncated to 255
690+
# characters.
691+
# @option opts [Mdm::Host] :host The host on which the session was opened.
692+
# @option opts [DateTime, Time] :last_seen The last date and time the
693+
# session was seen to be open. Defaults to :closed_at's value.
694+
# @option opts [DateTime, Time] :opened_at The date and time that the
695+
# session was opened.
696+
# @option opts [String] :platform The platform of the host.
697+
# @option opts [Array] :routes ([]) The routes through the session for
698+
# pivoting.
699+
# @option opts [String] :stype Session type.
700+
# @option opts [String] :via_exploit The {Msf::Module#fullname} of the
701+
# exploit that was used to open the session.
702+
# @option option [String] :via_payload the {MSf::Module#fullname} of the
703+
# payload sent to the host when the exploit was successful.
704+
# @return [nil] if {Msf::DBManager#active} is +false+.
705+
# @return [Mdm::Session] if session is saved.
706+
# @raise [ArgumentError] if :host is not an Mdm::Host.
707+
# @raise [ActiveRecord::RecordInvalid] if session is invalid and cannot be
708+
# saved.
709+
#
710+
# @raise ArgumentError if :host and :session is +nil+
654711
def report_session(opts)
655712
return if not active
656713
::ActiveRecord::Base.connection_pool.with_connection {
@@ -719,8 +776,6 @@ def report_session(opts)
719776

720777
# If this is a live session, we know the host is vulnerable to something.
721778
if opts[:session] and session.via_exploit
722-
return unless host
723-
724779
mod = framework.modules.create(session.via_exploit)
725780

726781
if session.via_exploit == "exploit/multi/handler" and sess_data[:datastore]['ParentModule']

spec/factories/mdm/routes.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
FactoryGirl.define do
2+
factory :mdm_route, :class => Mdm::Route do
3+
netmask { generate :mdm_route_netmask }
4+
subnet { generate :mdm_route_subnet }
5+
6+
#
7+
# Associations
8+
#
9+
association :session, :factory => :mdm_session
10+
end
11+
12+
sequence :mdm_route_netmask do |n|
13+
bits = 32
14+
bitmask = n % bits
15+
16+
[ (~((2 ** (bits - bitmask)) - 1)) & 0xffffffff ].pack('N').unpack('CCCC').join('.')
17+
18+
bits = 32
19+
shift = n % bits
20+
mask_range = 2 ** bits
21+
full_mask = mask_range - 1
22+
23+
integer_netmask = (full_mask << shift)
24+
formatted_netmask = [integer_netmask].pack('N').unpack('CCCC').join('.')
25+
26+
formatted_netmask
27+
end
28+
29+
sequence :mdm_route_subnet do |n|
30+
class_c_network = n % 255
31+
32+
"192.168.#{class_c_network}.0"
33+
end
34+
end

0 commit comments

Comments
 (0)