Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ gemspec
# Metasploit::Credential::SSHKey validation and helper methods
gem 'net-ssh'

# Patching inverse association in Mdm models.
gem 'metasploit-concern', github: 'crmaxx/metasploit-concern', branch: 'staging/rails-4.2'

# Metasploit::Model::Search
gem 'metasploit-model', github: 'crmaxx/metasploit-model', branch: 'staging/rails-4.2'

# Various Metasploit::Credential records have associations to Mdm records
gem 'metasploit_data_models', github: 'crmaxx/metasploit_data_models', branch: 'staging/rails-4.2'

group :development do
# markdown formatting for yard
gem 'kramdown', platforms: :jruby
Expand All @@ -25,7 +34,7 @@ end
group :development, :test do
# Hash password for Metasploit::Credential::PasswordHash factories
gem 'bcrypt'
# Uploads simplecov reports to coveralls.io
# Uploads simplecov reports to coveralls.io
gem 'coveralls', require: false
# supplies factories for producing model instance for specs
# Version 4.1.0 or newer is needed to support generate calls without the 'FactoryGirl.' in factory definitions syntax.
Expand All @@ -38,9 +47,9 @@ group :development, :test do
# for testing database columns and indicies.
gem 'shoulda-matchers'
# code coverage of tests
gem 'simplecov', :require => false
gem 'simplecov', require: false
# dummy app
gem 'rails', '>= 4.0.9', '< 4.1.0'
gem 'rails', '>= 4.2.1'
# unit testing framework with rails integration
gem 'rspec-rails', '~> 3.1'
end
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ module Mdm::Session::MetasploitCredentialOriginSession
dependent: :destroy,
inverse_of: :session
end
end
end
6 changes: 3 additions & 3 deletions app/concerns/mdm/task/metasploit_credential_core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ module Mdm::Task::MetasploitCredentialCore
# The {Metasploit::Credential::Core credential origins} from this import task.
#
# @return [ActiveRecord::Relation<Metasploit::Credential::Core>]
has_and_belongs_to_many :credential_cores,
has_and_belongs_to_many :credential_cores,
-> { uniq },
class_name: "Metasploit::Credential::Core",
class_name: "Metasploit::Credential::Core",
join_table: "credential_cores_tasks"
end
end
end
6 changes: 3 additions & 3 deletions app/concerns/mdm/task/metasploit_credential_login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ module Mdm::Task::MetasploitCredentialLogin
# The {Metasploit::Credential::Core credential origins} from this import task.
#
# @return [ActiveRecord::Relation<Metasploit::Credential::Core>]
has_and_belongs_to_many :credential_logins,
has_and_belongs_to_many :credential_logins,
-> { uniq },
class_name: "Metasploit::Credential::Login",
class_name: "Metasploit::Credential::Login",
join_table: "credential_logins_tasks"
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ module Mdm::Task::MetasploitCredentialOriginImport
dependent: :destroy,
inverse_of: :task
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ module Mdm::User::MetasploitCredentialOriginManual
dependent: :destroy,
inverse_of: :user
end
end
end
2 changes: 1 addition & 1 deletion app/concerns/mdm/workspace/metasploit_credential_core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ module Mdm::Workspace::MetasploitCredentialCore
inverse_of: :workspace

end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ module MetasploitDataModels::Search::Visitor::Where::MetasploitCredential
attribute.eq(operation.value)
end
end
end
end
5 changes: 2 additions & 3 deletions app/models/metasploit/credential/blank_password.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Metasploit::Credential::BlankPassword < Metasploit::Credential::Password
# Validations
#

validates :data,
uniqueness: true
validates :data, uniqueness: true

#
# Instance Methods
Expand All @@ -25,4 +24,4 @@ def blank_data
end

Metasploit::Concern.run(self)
end
end
5 changes: 2 additions & 3 deletions app/models/metasploit/credential/blank_username.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class Metasploit::Credential::BlankUsername < Metasploit::Credential::Public
# Validations
#

validates :username,
uniqueness: true
validates :username, uniqueness: true

#
# Instance Methods
Expand All @@ -25,4 +24,4 @@ def blank_username
end

Metasploit::Concern.run(self)
end
end
78 changes: 33 additions & 45 deletions app/models/metasploit/credential/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ class Metasploit::Credential::Core < ActiveRecord::Base
# @return [Metasploit::Credential::Origin::Session] if this core credential was gathered using a
# {Metasploit::Credential::Origin::Session#post_reference_name post module} attached to a
# {Metasploit::Credential::Origin::Session#session session}.
belongs_to :origin,
polymorphic: true
belongs_to :origin, polymorphic: true

# @!attribute private
# The {Metasploit::Credential::Private} either gathered from {#realm} or used to
Expand Down Expand Up @@ -105,8 +104,7 @@ class Metasploit::Credential::Core < ActiveRecord::Base
#

validate :consistent_workspaces
validates :origin,
presence: true
validates :origin, presence: true

#
# Scopes
Expand All @@ -130,7 +128,7 @@ class Metasploit::Credential::Core < ActiveRecord::Base
# @param origin_class [ActiveRecord::Base] the Origin class to look up
# @param table_alias [String] an alias for the JOINed table, defaults to the table name
# @return [ActiveRecord::Relation] scoped to that origin
scope :origins, lambda { |origin_class, table_alias=nil|
scope :origins, lambda { |origin_class, table_alias = nil|
core_table = Metasploit::Credential::Core.arel_table
origin_table = origin_class.arel_table.alias(table_alias || origin_class.table_name)
origin_joins = core_table.join(origin_table).on(origin_table[:id].eq(core_table[:origin_id])
Expand Down Expand Up @@ -214,41 +212,31 @@ class Metasploit::Credential::Core < ActiveRecord::Base
# @scope Metasploit::Credential::Core
# @param id [Integer] the workspace to look in
# @return [ActiveRecord::Relation] scoped to the workspace
scope :workspace_id, ->(id) {
where(workspace_id: id)
}
scope :workspace_id, ->(id) { where(workspace_id: id) }

# Eager loads {Metasploit::Credential::Login} objects associated to Cores
#
# @method with_logins
# @return [ActiveRecord::Relation]
scope :with_logins, ->() {
includes(:logins)
}
scope :with_logins, -> { includes(:logins) }

# Eager loads {Metasploit::Credential::Public} objects associated to Cores
#
# @method with_public
# @return [ActiveRecord::Relation]
scope :with_public, ->() {
includes(:public)
}
scope :with_public, -> { includes(:public) }

# Eager loads {Metasploit::Credential::Private} objects associated to Cores
#
# @method with_private
# @return [ActiveRecord::Relation]
scope :with_private, ->() {
includes(:private)
}
scope :with_private, -> { includes(:private) }

# Eager loads {Metasploit::Credential::Realm} objects associated to Cores
#
# @method with_realm
# @return [ActiveRecord::Relation]
scope :with_realm, ->() {
includes(:realm)
}
scope :with_realm, -> { includes(:realm) }

#
#
Expand Down Expand Up @@ -307,31 +295,31 @@ def self.cores_from_host_sql(host_id)
# @return [void]
def consistent_workspaces
case origin
when Metasploit::Credential::Origin::Manual
user = origin.user

# admins can access any workspace so there's no inconsistent workspace
unless user &&
(
user.admin ||
# use database query when possible
(
user.persisted? &&
user.workspaces.exists?(self.workspace.id)
) ||
# otherwise fall back to in-memory query
user.workspaces.include?(self.workspace)
)
errors.add(:workspace, :origin_user_workspaces)
end
when Metasploit::Credential::Origin::Service
unless self.workspace == origin.service.try(:host).try(:workspace)
errors.add(:workspace, :origin_service_host_workspace)
end
when Metasploit::Credential::Origin::Session
unless self.workspace == origin.session.try(:host).try(:workspace)
errors.add(:workspace, :origin_session_host_workspace)
end
when Metasploit::Credential::Origin::Manual
user = origin.user

# admins can access any workspace so there's no inconsistent workspace
unless user &&
(
user.admin ||
# use database query when possible
(
user.persisted? &&
user.workspaces.exists?(workspace.id)
) ||
# otherwise fall back to in-memory query
user.workspaces.include?(workspace)
)
errors.add(:workspace, :origin_user_workspaces)
end
when Metasploit::Credential::Origin::Service
unless workspace == origin.service.try(:host).try(:workspace)
errors.add(:workspace, :origin_service_host_workspace)
end
when Metasploit::Credential::Origin::Session
unless workspace == origin.session.try(:host).try(:workspace)
errors.add(:workspace, :origin_session_host_workspace)
end
end
end

Expand Down
33 changes: 10 additions & 23 deletions app/models/metasploit/credential/login.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ class Metasploit::Credential::Login < ActiveRecord::Base
#
# Associations
#

# @!attribute tasks
# The `Mdm::Task`s using this to track what tasks interacted with a given core.
#
# @return [ActiveRecord::Relation<Mdm::Task>]
has_and_belongs_to_many :tasks,
-> { uniq },
class_name: "Mdm::Task",
class_name: "Mdm::Task",
join_table: "credential_logins_tasks"

# @!attribute core
Expand Down Expand Up @@ -111,12 +111,8 @@ class Metasploit::Credential::Login < ActiveRecord::Base
# Search Attributes
#

search_attribute :access_level,
type: :string
search_attribute :status,
type: {
set: :string
}
search_attribute :access_level, type: :string
search_attribute :status, type: { set: :string }

#
#
Expand All @@ -137,17 +133,10 @@ class Metasploit::Credential::Login < ActiveRecord::Base

validates :core,
presence: true
validates :core_id,
uniqueness: {
scope: :service_id
}
validates :core_id, uniqueness: { scope: :service_id }
validates :service,
presence: true
validates :status,
inclusion: {
in: Metasploit::Model::Login::Status::ALL
}

validates :status, inclusion: { in: Metasploit::Model::Login::Status::ALL }

#
# Scopes
Expand Down Expand Up @@ -185,7 +174,7 @@ def self.failed_logins_by_public(host_id)
Metasploit::Credential::Public[:username]
]
).order(:last_attempted_at).
joins(
joins(
Metasploit::Credential::Login.join_association(:core),
Metasploit::Credential::Core.join_association(:public, Arel::Nodes::OuterJoin)
).where(
Expand All @@ -198,13 +187,12 @@ def self.failed_logins_by_public(host_id)
[
Metasploit::Model::Login::Status::DENIED_ACCESS,
Metasploit::Model::Login::Status::DISABLED,
Metasploit::Model::Login::Status::INCORRECT,
Metasploit::Model::Login::Status::INCORRECT
]
))
).group_by(&:username)
end


# The valid values for search {#status}.
#
# @return [Set<String>] `Metasploit::Model::Login::Status::ALL` as a `Set`.
Expand All @@ -224,9 +212,8 @@ def self.status_set
#
# @return [void]
def blank_to_nil
if access_level.blank?
self.access_level = nil
end
return unless access_level.blank?
self.access_level = nil
end

# Validates that {#last_attempted_at} is `nil` when {#status} is {Metasploit:Credential::Login::Status::UNTRIED} and
Expand Down
1 change: 0 additions & 1 deletion app/models/metasploit/credential/nonreplayable_hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
# Contrast with {Metasploit::Credential::ReplayableHash}. {#data} is any password hash, such as those recovered from
# `/etc/passwd` or `/etc/shadow`.
class Metasploit::Credential::NonreplayableHash < Metasploit::Credential::PasswordHash

#
# Constants
#
Expand Down
Loading