app/models/mdm/workspace.rb in metasploit_data_models-0.24.4 vs app/models/mdm/workspace.rb in metasploit_data_models-0.24.5

- old
+ new

@@ -1,142 +1,62 @@ -# Workspace to separate different collections of {#hosts}. Can be used to separate pentests against different networks -# or different clients as reports are normally generated against all records in a workspace. class Mdm::Workspace < ActiveRecord::Base # + # Callbacks + # + + before_save :normalize + + # # CONSTANTS # DEFAULT = 'default' # - # Associations + # Relations # - # Automatic exploitation runs against this workspace. has_many :automatic_exploitation_runs, class_name: 'MetasploitDataModels::AutomaticExploitation::Run', inverse_of: :workspace - # Automatic exploitation match sets generated against {#hosts} and {#services} in this workspace. has_many :automatic_exploitation_match_sets, class_name: 'MetasploitDataModels::AutomaticExploitation:MatchSet', inverse_of: :workspace - # @deprecated Use `Mdm::Workspace#core_credentials` defined by `Metasploit::Credential::Engine` to get - # `Metasploit::Credential::Core`s gathered from this workspace's {#hosts} and {#services}. - # - # Creds gathered from this workspace's {#hosts} and {#services}. has_many :creds, :through => :services, :class_name => 'Mdm::Cred' - - # Events that occurred in this workspace. has_many :events, :class_name => 'Mdm::Event' - - # Hosts in this workspace. has_many :hosts, :dependent => :destroy, :class_name => 'Mdm::Host' - - # Listeners running for this workspace. has_many :listeners, :dependent => :destroy, :class_name => 'Mdm::Listener' - - # Notes about this workspace. has_many :notes, :class_name => 'Mdm::Note' - - # User that owns this workspace and has full permissions within this workspace even if they are not an - # {Mdm::User#admin administrator}. belongs_to :owner, :class_name => 'Mdm::User', :foreign_key => 'owner_id' - - # Tasks run inside this workspace. has_many :tasks, :dependent => :destroy, :class_name => 'Mdm::Task', :order => 'created_at DESC' - - # Users that are allowed to use this workspace. Does not necessarily include all users, as an {Mdm::User#admin - # administrator} can access any workspace, even ones where they are not a member. has_and_belongs_to_many :users, :join_table => 'workspace_members', :uniq => true, :class_name => 'Mdm::User' # - # through: :hosts + # Through :hosts # - - # Social engineering campaign or browser autopwn clients from {#hosts} in this workspace. has_many :clients, :through => :hosts, :class_name => 'Mdm::Client' - - # Hosts exploited in this workspace. has_many :exploited_hosts, :through => :hosts, :class_name => 'Mdm::ExploitedHost' - - # Loot gathered from {#hosts} in this workspace. has_many :loots, :through => :hosts, :class_name => 'Mdm::Loot' - - # Services running on {#hosts} in this workspace. - has_many :services, - class_name: 'Mdm::Service', - foreign_key: :service_id, - through: :hosts - - # Vulnerabilities found on {#hosts} in this workspace. has_many :vulns, :through => :hosts, :class_name => 'Mdm::Vuln' - - # Sessions opened on {#hosts} in this workspace. + has_many :services, :through => :hosts, :class_name => 'Mdm::Service', :foreign_key => 'service_id' has_many :sessions, :through => :hosts, :class_name => 'Mdm::Session' # - # Attributes - # - - # @!attribute boundary - # Comma separated list of IP ranges (in various formats) and IP addresses that users of this workspace are allowed - # to interact with if {#limit_to_network} is `true`. - # - # @return [String] - - # @!attribute description - # Long description (beyond {#name}) that explains the purpose of this workspace. - # - # @return [String] - - # @!attribute limit_to_network - # Whether {#boundary} is respected. - # - # @return [false] do not limit interactions to {#boundary}. - # @return [true] limit interactions to {#boundary}. - - # @!attribute name - # Name of this workspace. - # - # @return [String] - - # @!attribute created_at - # When this workspace was created. - # - # @return [DateTime] - - # @!attribute updated_at - # The last time this workspace was updated. - # - # @return [DateTime] - - # - # Callbacks - # - - before_save :normalize - - # # Validations # validates :name, :presence => true, :uniqueness => true, :length => {:maximum => 255} validates :description, :length => {:maximum => 4096} validate :boundary_must_be_ip_range # - # Instance Methods + # If limit_to_network is disabled, this will always return true. + # Otherwise, return true only if all of the given IPs are within the project + # boundaries. # - - # If {#limit_to_network} is disabled, this will always return `true`. Otherwise, return `true` only if all of the - # given IPs are within the project {#boundary boundaries}. - # - # @param ips [String] IP range(s) - # @return [true] if actions on ips are allowed. - # @return [false] if actions are not allowed on ips. def allow_actions_on?(ips) return true unless limit_to_network return true unless boundary return true if boundary.empty? boundaries = Shellwords.split(boundary) @@ -149,87 +69,54 @@ allowed = true if ok_range.include_range? given_range end return allowed end - # Validates that {#boundary} is {#valid_ip_or_range? a valid IP address or IP address range}. - # - # @return [void] def boundary_must_be_ip_range errors.add(:boundary, "must be a valid IP range") unless valid_ip_or_range?(boundary) end - # @deprecated Use `Mdm::Workspace#credential_cores` when `Metasploit::Credential::Engine` is installed to get - # `Metasploit::Credential::Core`s. Use `Mdm::Service#logins` when `Metasploit::Credential::Engine` is installed to - # get `Metasploit::Credential::Login`s. - # - # @return [ActiveRecord::Relation<Mdm::Cred>] def creds Mdm::Cred.find( :all, :include => {:service => :host}, :conditions => ["hosts.workspace_id = ?", self.id] ) end - # Returns default {Mdm::Workspace}. - # - # @return [Mdm::Workspace] def self.default where(name: DEFAULT).first_or_create end - # Whether this is the {default} workspace. - # - # @return [true] if this is the {default} workspace. - # @return [false] if this is not the {default} workspace. def default? name == DEFAULT end - # @deprecated Use `workspace.credential_cores.each` when `Metasploit::Credential::Engine` is installed to enumerate - # `Metasploit::Credential::Core`s. Use `service.logins.each` when `Metasploit::Credential::Engine` is installed to - # enumerate `Metasploit::Credential::Login`s. # - # Enumerates each element of {#creds}. + # This method iterates the creds table calling the supplied block with the + # cred instance of each entry. # - # @yield [cred] - # @yieldparam cred [Mdm::Cred] Cred associated with {#hosts a host} or {#services a service} in this workspace. - # @yieldreturn [void] - # @return [void] def each_cred(&block) creds.each do |cred| block.call(cred) end end - # Enumerates each element of {#host_tags}. - # - # @yield [tag] - # @yieldparam tag [Mdm::Tag] a tag on {#hosts}. - # @yieldreturn [void] - # @return [void] def each_host_tag(&block) host_tags.each do |host_tag| block.call(host_tag) end end - # Tags on {#hosts}. - # - # @return [ActiveRecord::Relation<Mdm::Tag>] def host_tags Mdm::Tag.find( :all, :include => :hosts, :conditions => ["hosts.workspace_id = ?", self.id] ) end - # Web forms found on {#web_sites}. - # - # @return [ActiveRecord::Relation<Mdm::WebForm>] def web_forms query = <<-EOQ SELECT DISTINCT web_forms.* FROM hosts, services, web_sites, web_forms WHERE hosts.workspace_id = #{id} AND @@ -238,14 +125,10 @@ web_forms.web_site_id = web_sites.id EOQ Mdm::WebForm.find_by_sql(query) end - - # Web pages found on {#web_sites}. - # - # @return [ActiveRecord::Relation<Mdm::WebPage>] def web_pages query = <<-EOQ SELECT DISTINCT web_pages.* FROM hosts, services, web_sites, web_pages WHERE hosts.workspace_id = #{id} AND @@ -254,13 +137,10 @@ web_pages.web_site_id = web_sites.id EOQ Mdm::WebPage.find_by_sql(query) end - # Web sites running on {#services}. - # - # @return [ActiveRecord::Relation<Mdm::WebSite>] def web_sites query = <<-EOQ SELECT DISTINCT web_sites.* FROM hosts, services, web_sites WHERE hosts.workspace_id = #{id} AND @@ -268,13 +148,10 @@ web_sites.service_id = services.id EOQ Mdm::WebSite.find_by_sql(query) end - # Web vulnerability found on {#web_sites}. - # - # @return [ActiveRecord::Relation<Mdm::WebVuln>] def web_vulns query = <<-EOQ SELECT DISTINCT web_vulns.* FROM hosts, services, web_sites, web_vulns WHERE hosts.workspace_id = #{id} AND @@ -283,13 +160,10 @@ web_vulns.web_site_id = web_sites.id EOQ Mdm::WebVuln.find_by_sql(query) end - # Web forms on {#web_sites}. - # - # @return [ActiveRecord::Relation<Mdm::WebForm>] def unique_web_forms query = <<-EOQ SELECT DISTINCT web_forms.web_site_id, web_forms.path, web_forms.method, web_forms.query FROM hosts, services, web_sites, web_forms WHERE hosts.workspace_id = #{id} AND @@ -298,35 +172,23 @@ web_forms.web_site_id = web_sites.id EOQ Mdm::WebForm.find_by_sql(query) end - # {#unique_web_forms} hosted on `addrs`. - # - # @param addrs [Array<IPAddr, String>] {Mdm::Host#address} for the {Mdm::Service#host} for the {Mdm::WebSite#service} - # for the {Mdm::WebForm#web_site}. - # @return [Array<Mdm::WebForm>] def web_unique_forms(addrs=nil) forms = unique_web_forms if addrs forms.reject! { |f| not addrs.include?(f.web_site.service.host.address) } end forms end private - # Strips {#boundary}. - # - # @return [void] def normalize boundary.strip! if boundary end - # Returns whether `string` is a valid IP address or IP address range. - # - # @return [true] if valid IP address or IP address range. - # @return [false] otherwise. def valid_ip_or_range?(string) begin Rex::Socket::RangeWalker.new(string) rescue return false