app/models/mdm/loot.rb
# Loot gathered from {#host} or {#service} such as files to prove you were on the system or to crack later to gain
# sessions on other machines in the network.
class Mdm::Loot < ApplicationRecord
#
# CONSTANTS
#
RELATIVE_SEARCH_FIELDS = [
'ltype',
'name',
'info',
'data'
]
#
# Associations
#
# @!attribute exploit_attempt
# Exploit attempt where this loot was gathered.
#
# @return [Mdm::ExploitAttempt]
has_one :exploit_attempt,
class_name: 'Mdm::ExploitAttempt',
inverse_of: :loot
# @!attribute [rw] host
# The host from which the loot was gathered.
#
# @return [Mdm::Host]
belongs_to :host,
class_name: 'Mdm::Host',
optional: true, # allow for manually stored loot
inverse_of: :loots
# @!attribute [rw] module_run
# The run of Metasploit content that acquired the loot
#
# @return [MetasploitDataModels::ModuleRun]
belongs_to :module_run,
class_name: 'MetasploitDataModels::ModuleRun',
foreign_key: :module_run_id,
optional: true, # allow for manually stored loot?
inverse_of: :loots
# @!attribute [rw] service
# The service running on the {#host} from which the loot was gathered.
#
# @return [Mdm::Service]
belongs_to :service,
class_name: 'Mdm::Service',
optional: true,
inverse_of: :loots
# @!attribute vuln_attempt
# Vuln attempt that gathered this loot.
#
# @return [Mdm::VulnAttempt]
has_one :vuln_attempt,
class_name: 'Mdm::VulnAttempt',
inverse_of: :loot
# @!attribute [rw] workspace
# The workspace in which the loot is stored and the {#host} exists.
#
# @return [Mdm::Workspace]
belongs_to :workspace,
class_name: 'Mdm::Workspace',
inverse_of: :loots
#
# Attributes
#
# @!attribute [rw] content_type
# The mime/content type of the file at {#path}. Used to server the file correctly so browsers understand whether
# to render or download the file.
#
# @return [String]
# @!attribute [rw] created_at
# When the loot was created.
#
# @return [DateTime]
# @!attribute [rw] data
# Loot data not stored in file at {#path}.
#
# @return [String]
# @!attribute [rw] ltype
# The type of loot
#
# @return [String]
# @!attribute [rw] info
# Information about the loot.
#
# @return [String]
# @!attribute [rw] name
# The name of the loot.
#
# @return [String]
# @!attribute [rw] path
# The on-disk path to the loot file.
#
# @return [String]
# @!attribute [rw] updated_at
# The last time the loot was updated.
#
# @return [DateTime]
#
# Callbacks
#
before_destroy :delete_file
#
# Scopes
#
scope :search, lambda { |*args|
joins(:host).
where(
'loots.ltype ILIKE ? ' +
'OR loots.name ILIKE ? ' +
'OR loots.info ILIKE ? ' +
'OR loots.data ILIKE ? ' +
'OR COALESCE(hosts.name, CAST(hosts.address AS TEXT)) ILIKE ?',
"%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%", "%#{args[0]}%"
)
}
#
# Serializations
#
serialize :data, coder: MetasploitDataModels::Base64Serializer.new
private
# Deletes {#path} from disk.
#
# @todo https://www.pivotaltracker.com/story/show/49023795
# @return [void]
def delete_file
c = Pro::Client.get rescue nil
if c
c.loot_delete_file(self[:id])
else
::File.unlink(self.path) rescue nil
end
end
public
Metasploit::Concern.run(self)
end