metasploit-credential 0.14.3 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3caf1e01c95c4947f2c603797a4654900e229504
4
- data.tar.gz: 2de5cef5ee46f4de3ad2f2f0f7a43721141109f8
3
+ metadata.gz: fbe2434217b52c3bac09f0768a85e6b18fd12b8e
4
+ data.tar.gz: 29a368a665d73fc777b043f87fcfb8743a18792e
5
5
  SHA512:
6
- metadata.gz: dc65764ac31197bf9bf972ecf67366d95862806a5e812b27dec64b5d083fdd4538f262a5a70f0386be8159aa9a2467bdf1db6761bf15ad0758f1b4b83220f746
7
- data.tar.gz: c56fdbf1b7c4536195effa385260f59cbf5a1f4e8e59e32e17e0c05ae1f1865afd91ca3ec7909ec676af28de3fc6b84b0539f61630f637b7e7714853398e8ac9
6
+ metadata.gz: 7cf0f29712e070a36008dd3080eb2dcccb496cd0dfd63977d096615a09575d01f4da8fa6039efbe955aa93b5248e0090cc03e0405648c6abfbceb65c68236151
7
+ data.tar.gz: 4335440dec2ea65b8be23d68019f50a7900cf33562cdfd01be166958f1c5de437738be0d4f8d2aade5b65fda436e013a040976db45aa79ef7eced976f12979ba
@@ -16,6 +16,8 @@ require 'zip'
16
16
  # Project
17
17
  #
18
18
 
19
+ autoload :NonNilValidator, 'non_nil_validator'
20
+
19
21
  # Shared namespace for metasploit gems; used in {https://github.com/rapid7/metasploit-credential metasploit-credential},
20
22
  # {https://github.com/rapid7/metasploit-framework metasploit-framework}, and
21
23
  # {https://github.com/rapid7/metasploit-model metasploit-model}
@@ -24,13 +26,31 @@ module Metasploit
24
26
  module Credential
25
27
  extend ActiveSupport::Autoload
26
28
 
29
+ autoload :BlankPassword
30
+ autoload :BlankUsername
31
+ autoload :Core
32
+ autoload :CoreValidations
27
33
  autoload :Creation
34
+ autoload :Engine
28
35
  autoload :EntityRelationshipDiagram
29
36
  autoload :Exporter
30
37
  autoload :Importer
38
+ autoload :Login
31
39
  autoload :Migrator
40
+ autoload :NonreplayableHash
41
+ autoload :NTLMHash
32
42
  autoload :Origin
43
+ autoload :Password
44
+ autoload :PasswordHash
45
+ autoload :PostgresMD5
46
+ autoload :Private
47
+ autoload :Public
48
+ autoload :Realm
49
+ autoload :ReplayableHash
50
+ autoload :Search
51
+ autoload :SSHKey
33
52
  autoload :Text
53
+ autoload :Username
34
54
 
35
55
  # The prefix for all `ActiveRecord::Base#table_name`s for `ActiveRecord::Base` subclasses under this namespace.
36
56
  #
@@ -1,119 +1,115 @@
1
- module Metasploit
2
- module Credential
3
- # This mixin is intended to provide all of the common validations sued by {Metasploit::Credential::Core} and
4
- # anything that mimics it's behaviour by tying together {Metasploit::Credential::Public}, {Metasploit::Credential::Private},
5
- # and {Metasploit::Credential::Realm} objects.
6
- module CoreValidations
7
- extend ActiveSupport::Concern
1
+ # This mixin is intended to provide all of the common validations sued by {Metasploit::Credential::Core} and anything
2
+ # that mimics it's behaviour by tying together {Metasploit::Credential::Public}, {Metasploit::Credential::Private},
3
+ # and {Metasploit::Credential::Realm} objects.
4
+ module Metasploit::Credential::CoreValidations
5
+ extend ActiveSupport::Concern
8
6
 
9
- included do
7
+ included do
10
8
 
11
- validate :minimum_presence
12
- validate :public_for_ssh_key
9
+ validate :minimum_presence
10
+ validate :public_for_ssh_key
13
11
 
14
- #
15
- # Attribute Validations
16
- #
12
+ #
13
+ # Attribute Validations
14
+ #
17
15
 
18
16
 
19
- # replicates 'unique_private_metasploit_credential_cores' index
20
- validates :private_id,
21
- uniqueness: {
22
- message: 'is already taken for credential cores with only a private credential',
23
- scope: [
24
- :workspace_id,
25
- # realm_id and public_id need to be included in scope so validator uses IS NULL.
26
- :realm_id,
27
- :public_id
28
- ]
29
- },
30
- if: '!realm.present? && !public.present? && private.present?'
31
- # replicates 'unique_public_metasploit_credential_cores' index
32
- validates :public_id,
33
- uniqueness: {
34
- message: 'is already taken for credential cores with only a public credential',
35
- scope: [
36
- :workspace_id,
37
- # realm_id and private_id need to be included in scope so validator uses IS NULL.
38
- :realm_id,
39
- :private_id
40
- ]
41
- },
42
- if: '!realm.present? && public.present? && !private.present?'
43
- # replicates 'unique_realmless_metasploit_credential_cores' index
44
- validates :private_id,
45
- uniqueness: {
46
- message: 'is already taken for credential cores without a credential realm',
47
- scope: [
48
- :workspace_id,
49
- # realm_id needs to be included in scope so validator uses IS NULL.
50
- :realm_id,
51
- :public_id
52
- ]
53
- },
54
- if: '!realm.present? && public.present? && private.present?'
55
- # replicates 'unique_publicless_metasploit_credential_cores' index
56
- validates :private_id,
57
- uniqueness: {
58
- message: 'is already taken for credential cores without a public credential',
59
- scope: [
60
- :workspace_id,
61
- :realm_id,
62
- # public_id needs to be included in scope so validator uses IS NULL.
63
- :public_id
64
- ]
65
- },
66
- if: 'realm.present? && !public.present? && private.present?'
67
- # replicates 'unique_privateless_metasploit_credential_cores' index
68
- validates :public_id,
69
- uniqueness: {
70
- message: 'is already taken for credential cores without a private credential',
71
- scope: [
72
- :workspace_id,
73
- :realm_id,
74
- # private_id needs to be included in scope so validator uses IS NULL.
75
- :private_id
76
- ]
77
- },
78
- if: 'realm.present? && public.present? && !private.present?'
79
- # replicates 'unique_complete_metasploit_credential_cores' index
80
- validates :private_id,
81
- uniqueness: {
82
- message: 'is already taken for complete credential cores',
83
- scope: [
84
- :workspace_id,
85
- :realm_id,
86
- :public_id
87
- ]
88
- },
89
- if: 'realm.present? && public.present? && private.present?'
90
- validates :workspace,
91
- presence: true
17
+ # replicates 'unique_private_metasploit_credential_cores' index
18
+ validates :private_id,
19
+ uniqueness: {
20
+ message: 'is already taken for credential cores with only a private credential',
21
+ scope: [
22
+ :workspace_id,
23
+ # realm_id and public_id need to be included in scope so validator uses IS NULL.
24
+ :realm_id,
25
+ :public_id
26
+ ]
27
+ },
28
+ if: '!realm.present? && !public.present? && private.present?'
29
+ # replicates 'unique_public_metasploit_credential_cores' index
30
+ validates :public_id,
31
+ uniqueness: {
32
+ message: 'is already taken for credential cores with only a public credential',
33
+ scope: [
34
+ :workspace_id,
35
+ # realm_id and private_id need to be included in scope so validator uses IS NULL.
36
+ :realm_id,
37
+ :private_id
38
+ ]
39
+ },
40
+ if: '!realm.present? && public.present? && !private.present?'
41
+ # replicates 'unique_realmless_metasploit_credential_cores' index
42
+ validates :private_id,
43
+ uniqueness: {
44
+ message: 'is already taken for credential cores without a credential realm',
45
+ scope: [
46
+ :workspace_id,
47
+ # realm_id needs to be included in scope so validator uses IS NULL.
48
+ :realm_id,
49
+ :public_id
50
+ ]
51
+ },
52
+ if: '!realm.present? && public.present? && private.present?'
53
+ # replicates 'unique_publicless_metasploit_credential_cores' index
54
+ validates :private_id,
55
+ uniqueness: {
56
+ message: 'is already taken for credential cores without a public credential',
57
+ scope: [
58
+ :workspace_id,
59
+ :realm_id,
60
+ # public_id needs to be included in scope so validator uses IS NULL.
61
+ :public_id
62
+ ]
63
+ },
64
+ if: 'realm.present? && !public.present? && private.present?'
65
+ # replicates 'unique_privateless_metasploit_credential_cores' index
66
+ validates :public_id,
67
+ uniqueness: {
68
+ message: 'is already taken for credential cores without a private credential',
69
+ scope: [
70
+ :workspace_id,
71
+ :realm_id,
72
+ # private_id needs to be included in scope so validator uses IS NULL.
73
+ :private_id
74
+ ]
75
+ },
76
+ if: 'realm.present? && public.present? && !private.present?'
77
+ # replicates 'unique_complete_metasploit_credential_cores' index
78
+ validates :private_id,
79
+ uniqueness: {
80
+ message: 'is already taken for complete credential cores',
81
+ scope: [
82
+ :workspace_id,
83
+ :realm_id,
84
+ :public_id
85
+ ]
86
+ },
87
+ if: 'realm.present? && public.present? && private.present?'
88
+ validates :workspace,
89
+ presence: true
92
90
 
93
- private
91
+ private
94
92
 
95
- # Validates that at least one of {#private}, {#public}, or {#realm} is present.
96
- #
97
- # @return [void]
98
- def minimum_presence
99
- any_present = [:private, :public, :realm].any? { |attribute|
100
- send(attribute).present?
101
- }
102
-
103
- unless any_present
104
- errors.add(:base, :minimum_presence)
105
- end
106
- end
107
-
108
- # Validates that a Core's Private of type {Metasploit::Credential::SSHKey} has a {Metasploit::Credential::Public}
109
- def public_for_ssh_key
110
- if private.present? && private.type == Metasploit::Credential::SSHKey.name
111
- errors.add(:base, :public_for_ssh_key) unless public.present?
112
- end
113
- end
93
+ # Validates that at least one of {#private}, {#public}, or {#realm} is present.
94
+ #
95
+ # @return [void]
96
+ def minimum_presence
97
+ any_present = [:private, :public, :realm].any? { |attribute|
98
+ send(attribute).present?
99
+ }
114
100
 
101
+ unless any_present
102
+ errors.add(:base, :minimum_presence)
103
+ end
104
+ end
115
105
 
106
+ # Validates that a Core's Private of type {Metasploit::Credential::SSHKey} has a {Metasploit::Credential::Public}
107
+ def public_for_ssh_key
108
+ if private.present? && private.type == Metasploit::Credential::SSHKey.name
109
+ errors.add(:base, :public_for_ssh_key) unless public.present?
116
110
  end
117
111
  end
112
+
113
+
118
114
  end
119
- end
115
+ end
@@ -1,549 +1,542 @@
1
1
  # Implements a set of "convenience methods" for creating credentials and related portions of the object graph. Creates
2
2
  # {Metasploit::Credential::Core} objects and their attendant relationships as well as {Metasploit::Credential::Login}
3
3
  # objects and their attendant {Mdm::Host} and {Mdm::Service} objects.
4
- module Metasploit
5
- module Credential
6
- # Helper methods for finding or creating a tree of credentials. The method ensure that duplicate credentials are
7
- # not created.
8
- module Creation
9
-
10
- # Returns true if ActiveRecord has an active database connection, false otherwise.
11
- # @return [Boolean]
12
- def active_db?
13
- ActiveRecord::Base.connected?
14
- end
4
+ module Metasploit::Credential::Creation
15
5
 
16
- # This method takes a few simple parameters and creates a new username/password
17
- # credential that was obtained by cracking a hash. It reuses the relevant
18
- # components form the originating {Metasploit::Credential::Core} and builds new
19
- # {Metasploit::Credential::Login} objects based on the ones attached to the originating
20
- # {Metasploit::Credential::Core}
21
- #
22
- # @option opts [String] :username the username to find or create the {Metasploit::Credential::Public} from
23
- # @option opts [String] :password the password to find or create the {Metasploit::Credential::Password} from
24
- # @option opts [Fixnum] :core_id the id for the originating {Metasploit::Credential::Core}
25
- def create_cracked_credential(opts={})
26
- return nil unless active_db?
27
-
28
- if self.respond_to?(:[]) and self[:task]
29
- opts[:task_id] ||= self[:task].record.id
30
- end
6
+ # Returns true if ActiveRecord has an active database connection, false otherwise.
7
+ # @return [Boolean]
8
+ def active_db?
9
+ ActiveRecord::Base.connected?
10
+ end
31
11
 
32
- username = opts.fetch(:username)
33
- password = opts.fetch(:password)
34
- core_id = opts.fetch(:core_id)
12
+ # This method takes a few simple parameters and creates a new username/password
13
+ # credential that was obtained by cracking a hash. It reuses the relevant
14
+ # components form the originating {Metasploit::Credential::Core} and builds new
15
+ # {Metasploit::Credential::Login} objects based on the ones attached to the originating
16
+ # {Metasploit::Credential::Core}
17
+ #
18
+ # @option opts [String] :username the username to find or create the {Metasploit::Credential::Public} from
19
+ # @option opts [String] :password the password to find or create the {Metasploit::Credential::Password} from
20
+ # @option opts [Fixnum] :core_id the id for the originating {Metasploit::Credential::Core}
21
+ def create_cracked_credential(opts={})
22
+ return nil unless active_db?
23
+
24
+ if self.respond_to?(:[]) and self[:task]
25
+ opts[:task_id] ||= self[:task].record.id
26
+ end
35
27
 
36
- private = nil
37
- public = nil
38
- old_core = nil
39
- old_realm_id = nil
28
+ username = opts.fetch(:username)
29
+ password = opts.fetch(:password)
30
+ core_id = opts.fetch(:core_id)
40
31
 
41
- retry_transaction do
42
- private = Metasploit::Credential::Password.where(data: password).first_or_create!
43
- public = Metasploit::Credential::Public.where(username: username).first_or_create!
44
- old_core = Metasploit::Credential::Core.find(core_id)
45
- old_realm_id = old_core.realm.id if old_core.realm
46
- end
32
+ private = nil
33
+ public = nil
34
+ old_core = nil
35
+ old_realm_id = nil
47
36
 
48
- core = nil
37
+ retry_transaction do
38
+ private = Metasploit::Credential::Password.where(data: password).first_or_create!
39
+ public = Metasploit::Credential::Public.where(username: username).first_or_create!
40
+ old_core = Metasploit::Credential::Core.find(core_id)
41
+ old_realm_id = old_core.realm.id if old_core.realm
42
+ end
49
43
 
50
- retry_transaction do
51
- core = Metasploit::Credential::Core.where(public_id: public.id, private_id: private.id, realm_id: old_realm_id, workspace_id: old_core.workspace_id).first_or_initialize
52
- if core.origin_id.nil?
53
- origin = Metasploit::Credential::Origin::CrackedPassword.where(metasploit_credential_core_id: core_id).first_or_create!
54
- core.origin = origin
55
- end
56
- if opts[:task_id]
57
- core.tasks << Mdm::Task.find(opts[:task_id])
58
- end
59
- core.save!
60
- end
44
+ core = nil
61
45
 
62
- old_core.logins.each do |login|
63
- service_id = login.service_id
64
- new_login = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_id).first_or_initialize
65
- if new_login.status.blank?
66
- new_login.status = Metasploit::Model::Login::Status::UNTRIED
67
- end
68
- new_login.save!
69
- end
70
- core
46
+ retry_transaction do
47
+ core = Metasploit::Credential::Core.where(public_id: public.id, private_id: private.id, realm_id: old_realm_id, workspace_id: old_core.workspace_id).first_or_initialize
48
+ if core.origin_id.nil?
49
+ origin = Metasploit::Credential::Origin::CrackedPassword.where(metasploit_credential_core_id: core_id).first_or_create!
50
+ core.origin = origin
51
+ end
52
+ if opts[:task_id]
53
+ core.tasks << Mdm::Task.find(opts[:task_id])
71
54
  end
55
+ core.save!
56
+ end
72
57
 
58
+ old_core.logins.each do |login|
59
+ service_id = login.service_id
60
+ new_login = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_id).first_or_initialize
61
+ if new_login.status.blank?
62
+ new_login.status = Metasploit::Model::Login::Status::UNTRIED
63
+ end
64
+ new_login.save!
65
+ end
66
+ core
67
+ end
73
68
 
74
- # This method is responsible for creation {Metasploit::Credential::Core} objects
75
- # and all sub-objects that it is dependent upon.
76
- #
77
- # @option opts [String] :jtr_format The format for John the ripper to use to try and crack this
78
- # @option opts [Symbol] :origin_type The Origin type we are trying to create
79
- # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
80
- # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
81
- # @option opts [String] :service_name The service name to use for the `Mdm::Service`
82
- # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
83
- # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
84
- # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
85
- # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Origin and Core to
86
- # @option opts [String] :filename The filename of the file that was imported
87
- # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
88
- # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
89
- # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
90
- # @option opts [String] :private_data The actual data for the private (e.g. password, hash, key etc)
91
- # @option opts [Symbol] :private_type The type of {Metasploit::Credential::Private} to create
92
- # @option opts [String] :username The username to use for the {Metasploit::Credential::Public}
93
- # @raise [KeyError] if a required option is missing
94
- # @raise [ArgumentError] if an invalid :private_type is specified
95
- # @raise [ArgumentError] if an invalid :origin_type is specified
96
- # @return [NilClass] if there is no active database connection
97
- # @return [Metasploit::Credential::Core]
98
- # @example Reporting a Bruteforced Credential
99
- # create_credential(
100
- # origin_type: :service,
101
- # address: '192.168.1.100',
102
- # port: 445,
103
- # service_name: 'smb',
104
- # protocol: 'tcp',
105
- # module_fullname: 'auxiliary/scanner/smb/smb_login',
106
- # workspace_id: myworkspace.id,
107
- # private_data: 'password1',
108
- # private_type: :password,
109
- # username: 'Administrator'
110
- # )
111
- def create_credential(opts={})
112
- return nil unless active_db?
113
-
114
- if self.respond_to?(:[]) and self[:task]
115
- opts[:task_id] ||= self[:task].record.id
116
- end
117
69
 
118
- if opts[:origin]
119
- origin = opts[:origin]
120
- else
121
- origin = create_credential_origin(opts)
122
- end
70
+ # This method is responsible for creation {Metasploit::Credential::Core} objects
71
+ # and all sub-objects that it is dependent upon.
72
+ #
73
+ # @option opts [String] :jtr_format The format for John the ripper to use to try and crack this
74
+ # @option opts [Symbol] :origin_type The Origin type we are trying to create
75
+ # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
76
+ # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
77
+ # @option opts [String] :service_name The service name to use for the `Mdm::Service`
78
+ # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
79
+ # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
80
+ # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
81
+ # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Origin and Core to
82
+ # @option opts [String] :filename The filename of the file that was imported
83
+ # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
84
+ # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
85
+ # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
86
+ # @option opts [String] :private_data The actual data for the private (e.g. password, hash, key etc)
87
+ # @option opts [Symbol] :private_type The type of {Metasploit::Credential::Private} to create
88
+ # @option opts [String] :username The username to use for the {Metasploit::Credential::Public}
89
+ # @raise [KeyError] if a required option is missing
90
+ # @raise [ArgumentError] if an invalid :private_type is specified
91
+ # @raise [ArgumentError] if an invalid :origin_type is specified
92
+ # @return [NilClass] if there is no active database connection
93
+ # @return [Metasploit::Credential::Core]
94
+ # @example Reporting a Bruteforced Credential
95
+ # create_credential(
96
+ # origin_type: :service,
97
+ # address: '192.168.1.100',
98
+ # port: 445,
99
+ # service_name: 'smb',
100
+ # protocol: 'tcp',
101
+ # module_fullname: 'auxiliary/scanner/smb/smb_login',
102
+ # workspace_id: myworkspace.id,
103
+ # private_data: 'password1',
104
+ # private_type: :password,
105
+ # username: 'Administrator'
106
+ # )
107
+ def create_credential(opts={})
108
+ return nil unless active_db?
109
+
110
+ if self.respond_to?(:[]) and self[:task]
111
+ opts[:task_id] ||= self[:task].record.id
112
+ end
123
113
 
124
- core_opts = {
125
- origin: origin,
126
- workspace_id: opts.fetch(:workspace_id)
127
- }
114
+ if opts[:origin]
115
+ origin = opts[:origin]
116
+ else
117
+ origin = create_credential_origin(opts)
118
+ end
128
119
 
129
- if opts.has_key?(:realm_key) && opts.has_key?(:realm_value)
130
- core_opts[:realm] = create_credential_realm(opts)
131
- end
120
+ core_opts = {
121
+ origin: origin,
122
+ workspace_id: opts.fetch(:workspace_id)
123
+ }
132
124
 
133
- if opts.has_key?(:private_type) && opts.has_key?(:private_data)
134
- core_opts[:private] = create_credential_private(opts)
135
- end
125
+ if opts.has_key?(:realm_key) && opts.has_key?(:realm_value)
126
+ core_opts[:realm] = create_credential_realm(opts)
127
+ end
136
128
 
137
- if opts.has_key?(:username)
138
- core_opts[:public] = create_credential_public(opts)
139
- end
129
+ if opts.has_key?(:private_type) && opts.has_key?(:private_data)
130
+ core_opts[:private] = create_credential_private(opts)
131
+ end
140
132
 
141
- if opts.has_key?(:task_id)
142
- core_opts[:task_id] = opts[:task_id]
143
- end
133
+ if opts.has_key?(:username)
134
+ core_opts[:public] = create_credential_public(opts)
135
+ end
144
136
 
145
- create_credential_core(core_opts)
146
- end
137
+ if opts.has_key?(:task_id)
138
+ core_opts[:task_id] = opts[:task_id]
139
+ end
147
140
 
148
- # This method is responsible for creating {Metasploit::Credential::Core} objects.
149
- #
150
- # @option opts [Metasploit::Credential::Origin] :origin The origin object to tie the core to
151
- # @option opts [Metasploit::Credential::Public] :public The {Metasploit::Credential::Public} component
152
- # @option opts [Metasploit::Credential::Private] :private The {Metasploit::Credential::Private} component
153
- # @option opts [Metasploit::Credential::Realm] :realm The {Metasploit::Credential::Realm} component
154
- # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to tie the Core to
155
- # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Core to
156
- # @return [NilClass] if there is no active database connection
157
- # @return [Metasploit::Credential::Core]
158
- def create_credential_core(opts={})
159
- return nil unless active_db?
160
-
161
- if self.respond_to?(:[]) and self[:task]
162
- opts[:task_id] ||= self[:task].record.id
163
- end
141
+ create_credential_core(core_opts)
142
+ end
164
143
 
165
- origin = opts.fetch(:origin)
166
- workspace_id = opts.fetch(:workspace_id)
144
+ # This method is responsible for creating {Metasploit::Credential::Core} objects.
145
+ #
146
+ # @option opts [Metasploit::Credential::Origin] :origin The origin object to tie the core to
147
+ # @option opts [Metasploit::Credential::Public] :public The {Metasploit::Credential::Public} component
148
+ # @option opts [Metasploit::Credential::Private] :private The {Metasploit::Credential::Private} component
149
+ # @option opts [Metasploit::Credential::Realm] :realm The {Metasploit::Credential::Realm} component
150
+ # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to tie the Core to
151
+ # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Core to
152
+ # @return [NilClass] if there is no active database connection
153
+ # @return [Metasploit::Credential::Core]
154
+ def create_credential_core(opts={})
155
+ return nil unless active_db?
156
+
157
+ if self.respond_to?(:[]) and self[:task]
158
+ opts[:task_id] ||= self[:task].record.id
159
+ end
167
160
 
168
- private_id = opts[:private].try(:id)
169
- public_id = opts[:public].try(:id)
170
- realm_id = opts[:realm].try(:id)
161
+ origin = opts.fetch(:origin)
162
+ workspace_id = opts.fetch(:workspace_id)
171
163
 
172
- core = nil
173
- retry_transaction do
174
- core = Metasploit::Credential::Core.where(private_id: private_id, public_id: public_id, realm_id: realm_id, workspace_id: workspace_id).first_or_initialize
175
- if core.origin_id.nil?
176
- core.origin = origin
177
- end
178
- if opts[:task_id]
179
- core.tasks << Mdm::Task.find(opts[:task_id])
180
- end
181
- core.save!
182
- end
164
+ private_id = opts[:private].try(:id)
165
+ public_id = opts[:public].try(:id)
166
+ realm_id = opts[:realm].try(:id)
183
167
 
184
- core
168
+ core = nil
169
+ retry_transaction do
170
+ core = Metasploit::Credential::Core.where(private_id: private_id, public_id: public_id, realm_id: realm_id, workspace_id: workspace_id).first_or_initialize
171
+ if core.origin_id.nil?
172
+ core.origin = origin
185
173
  end
174
+ if opts[:task_id]
175
+ core.tasks << Mdm::Task.find(opts[:task_id])
176
+ end
177
+ core.save!
178
+ end
186
179
 
187
- # This method is responsible for creating a {Metasploit::Credential::Login} object
188
- # which ties a {Metasploit::Credential::Core} to the `Mdm::Service` it is a valid
189
- # credential for.
190
- #
191
- # @option opts [String] :access_level The access level to assign to this login if we know it
192
- # @option opts [String] :address The address of the `Mdm::Host` to link this Login to
193
- # @option opts [DateTime] :last_attempted_at The last time this Login was attempted
194
- # @option opts [Metasploit::Credential::Core] :core The {Metasploit::Credential::Core} to link this login to
195
- # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Login to
196
- # @option opts [String] :service_name The service name to use for the `Mdm::Service`
197
- # @option opts [String] :status The status for the Login object
198
- # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Login to
199
- # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
200
- # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Login to
201
- # @raise [KeyError] if a required option is missing
202
- # @return [NilClass] if there is no active database connection
203
- # @return [Metasploit::Credential::Login]
204
- def create_credential_login(opts={})
205
- return nil unless active_db?
206
-
207
- if self.respond_to?(:[]) and self[:task]
208
- opts[:task_id] ||= self[:task].record.id
209
- end
180
+ core
181
+ end
210
182
 
211
- core = opts.fetch(:core)
212
- access_level = opts.fetch(:access_level, nil)
213
- last_attempted_at = opts.fetch(:last_attempted_at, nil)
214
- status = opts.fetch(:status, Metasploit::Model::Login::Status::UNTRIED)
183
+ # This method is responsible for creating a {Metasploit::Credential::Login} object
184
+ # which ties a {Metasploit::Credential::Core} to the `Mdm::Service` it is a valid
185
+ # credential for.
186
+ #
187
+ # @option opts [String] :access_level The access level to assign to this login if we know it
188
+ # @option opts [String] :address The address of the `Mdm::Host` to link this Login to
189
+ # @option opts [DateTime] :last_attempted_at The last time this Login was attempted
190
+ # @option opts [Metasploit::Credential::Core] :core The {Metasploit::Credential::Core} to link this login to
191
+ # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Login to
192
+ # @option opts [String] :service_name The service name to use for the `Mdm::Service`
193
+ # @option opts [String] :status The status for the Login object
194
+ # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Login to
195
+ # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
196
+ # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Login to
197
+ # @raise [KeyError] if a required option is missing
198
+ # @return [NilClass] if there is no active database connection
199
+ # @return [Metasploit::Credential::Login]
200
+ def create_credential_login(opts={})
201
+ return nil unless active_db?
202
+
203
+ if self.respond_to?(:[]) and self[:task]
204
+ opts[:task_id] ||= self[:task].record.id
205
+ end
215
206
 
216
- login_object = nil
217
- retry_transaction do
218
- service_object = create_credential_service(opts)
219
- login_object = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_object.id).first_or_initialize
207
+ core = opts.fetch(:core)
208
+ access_level = opts.fetch(:access_level, nil)
209
+ last_attempted_at = opts.fetch(:last_attempted_at, nil)
210
+ status = opts.fetch(:status, Metasploit::Model::Login::Status::UNTRIED)
220
211
 
221
- if opts[:task_id]
222
- login_object.tasks << Mdm::Task.find(opts[:task_id])
223
- end
212
+ login_object = nil
213
+ retry_transaction do
214
+ service_object = create_credential_service(opts)
215
+ login_object = Metasploit::Credential::Login.where(core_id: core.id, service_id: service_object.id).first_or_initialize
224
216
 
225
- login_object.access_level = access_level if access_level
226
- login_object.last_attempted_at = last_attempted_at if last_attempted_at
227
- if status == Metasploit::Model::Login::Status::UNTRIED
228
- if login_object.last_attempted_at.nil?
229
- login_object.status = status
230
- end
231
- else
232
- login_object.status = status
233
- end
234
- login_object.save!
235
- end
236
-
237
- login_object
217
+ if opts[:task_id]
218
+ login_object.tasks << Mdm::Task.find(opts[:task_id])
238
219
  end
239
220
 
240
- # This method is responsible for creating the various Credential::Origin objects.
241
- # It takes a key for the Origin type and delegates to the correct sub-method.
242
- #
243
- # @option opts [Symbol] :origin_type The Origin type we are trying to create
244
- # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
245
- # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
246
- # @option opts [String] :service_name The service name to use for the `Mdm::Service`
247
- # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
248
- # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
249
- # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
250
- # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Origin to
251
- # @option opts [String] :filename The filename of the file that was imported
252
- # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
253
- # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
254
- # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
255
- # @raise [ArgumentError] if an invalid origin_type was provided
256
- # @raise [KeyError] if a required option is missing
257
- # @return [NilClass] if there is no connected database
258
- # @return [Metasploit::Credential::Origin::Manual] if :origin_type was :manual
259
- # @return [Metasploit::Credential::Origin::Import] if :origin_type was :import
260
- # @return [Metasploit::Credential::Origin::Service] if :origin_type was :service
261
- # @return [Metasploit::Credential::Origin::Session] if :origin_type was :session
262
- def create_credential_origin(opts={})
263
- return nil unless active_db?
264
- case opts[:origin_type]
265
- when :cracked_password
266
- create_credential_origin_cracked_password(opts)
267
- when :import
268
- create_credential_origin_import(opts)
269
- when :manual
270
- create_credential_origin_manual(opts)
271
- when :service
272
- create_credential_origin_service(opts)
273
- when :session
274
- create_credential_origin_session(opts)
275
- else
276
- raise ArgumentError, "Unknown Origin Type #{opts[:origin_type]}"
221
+ login_object.access_level = access_level if access_level
222
+ login_object.last_attempted_at = last_attempted_at if last_attempted_at
223
+ if status == Metasploit::Model::Login::Status::UNTRIED
224
+ if login_object.last_attempted_at.nil?
225
+ login_object.status = status
277
226
  end
227
+ else
228
+ login_object.status = status
278
229
  end
230
+ login_object.save!
231
+ end
279
232
 
280
- # This method is responsible for creating {Metasploit::Credential::Origin::CrackedPassword} objects.
281
- # These are the origins that show that a password Credential was obtained by cracking a hash Credential
282
- # that previously existed in the database.
283
- #
284
- # @option opts [Fixnum] :originating_core_id The ID of the originating Credential core.
285
- # @return [NilClass] if there is no connected database
286
- # @return [Metasploit::Credential::Origin::CrackedPassword] The created {Metasploit::Credential::Origin::CrackedPassword} object
287
- def create_credential_origin_cracked_password(opts={})
288
- return nil unless active_db?
289
- originating_core_id = opts.fetch(:originating_core_id)
290
-
291
- retry_transaction do
292
- Metasploit::Credential::Origin::CrackedPassword.where(metasploit_credential_core_id: originating_core_id ).first_or_create!
293
- end
294
- end
233
+ login_object
234
+ end
295
235
 
296
- # This method is responsible for creating {Metasploit::Credential::Origin::Import} objects.
297
- #
298
- # @option opts [String] :filename The filename of the file that was imported
299
- # @raise [KeyError] if a required option is missing
300
- # @return [NilClass] if there is no connected database
301
- # @return [Metasploit::Credential::Origin::Manual] The created {Metasploit::Credential::Origin::Import} object
302
- def create_credential_origin_import(opts={})
303
- return nil unless active_db?
304
- filename = opts.fetch(:filename)
305
-
306
- retry_transaction do
307
- Metasploit::Credential::Origin::Import.where(filename: filename).first_or_create!
308
- end
309
- end
236
+ # This method is responsible for creating the various Credential::Origin objects.
237
+ # It takes a key for the Origin type and delegates to the correct sub-method.
238
+ #
239
+ # @option opts [Symbol] :origin_type The Origin type we are trying to create
240
+ # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
241
+ # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
242
+ # @option opts [String] :service_name The service name to use for the `Mdm::Service`
243
+ # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
244
+ # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
245
+ # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
246
+ # @option opts [Fixnum] :task_id The ID of the `Mdm::Task` to link this Origin to
247
+ # @option opts [String] :filename The filename of the file that was imported
248
+ # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
249
+ # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
250
+ # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
251
+ # @raise [ArgumentError] if an invalid origin_type was provided
252
+ # @raise [KeyError] if a required option is missing
253
+ # @return [NilClass] if there is no connected database
254
+ # @return [Metasploit::Credential::Origin::Manual] if :origin_type was :manual
255
+ # @return [Metasploit::Credential::Origin::Import] if :origin_type was :import
256
+ # @return [Metasploit::Credential::Origin::Service] if :origin_type was :service
257
+ # @return [Metasploit::Credential::Origin::Session] if :origin_type was :session
258
+ def create_credential_origin(opts={})
259
+ return nil unless active_db?
260
+ case opts[:origin_type]
261
+ when :cracked_password
262
+ create_credential_origin_cracked_password(opts)
263
+ when :import
264
+ create_credential_origin_import(opts)
265
+ when :manual
266
+ create_credential_origin_manual(opts)
267
+ when :service
268
+ create_credential_origin_service(opts)
269
+ when :session
270
+ create_credential_origin_session(opts)
271
+ else
272
+ raise ArgumentError, "Unknown Origin Type #{opts[:origin_type]}"
273
+ end
274
+ end
310
275
 
311
- # This method is responsible for creating {Metasploit::Credential::Origin::Manual} objects.
312
- #
313
- # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
314
- # @raise [KeyError] if a required option is missing
315
- # @return [NilClass] if there is no connected database
316
- # @return [Metasploit::Credential::Origin::Manual] The created {Metasploit::Credential::Origin::Manual} object
317
- def create_credential_origin_manual(opts={})
318
- return nil unless active_db?
319
- user_id = opts.fetch(:user_id)
320
-
321
- retry_transaction do
322
- Metasploit::Credential::Origin::Manual.where(user_id: user_id).first_or_create!
323
- end
324
- end
276
+ # This method is responsible for creating {Metasploit::Credential::Origin::CrackedPassword} objects.
277
+ # These are the origins that show that a password Credential was obtained by cracking a hash Credential
278
+ # that previously existed in the database.
279
+ #
280
+ # @option opts [Fixnum] :originating_core_id The ID of the originating Credential core.
281
+ # @return [NilClass] if there is no connected database
282
+ # @return [Metasploit::Credential::Origin::CrackedPassword] The created {Metasploit::Credential::Origin::CrackedPassword} object
283
+ def create_credential_origin_cracked_password(opts={})
284
+ return nil unless active_db?
285
+ originating_core_id = opts.fetch(:originating_core_id)
286
+
287
+ retry_transaction do
288
+ Metasploit::Credential::Origin::CrackedPassword.where(metasploit_credential_core_id: originating_core_id ).first_or_create!
289
+ end
290
+ end
325
291
 
326
- # This method is responsible for creating {Metasploit::Credential::Origin::Service} objects.
327
- # If there is not a matching `Mdm::Host` it will create it. If there is not a matching
328
- # `Mdm::Service` it will create that too.
329
- #
330
- # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
331
- # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
332
- # @option opts [String] :service_name The service name to use for the `Mdm::Service`
333
- # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
334
- # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
335
- # @raise [KeyError] if a required option is missing
336
- # @return [NilClass] if there is no connected database
337
- # @return [Metasploit::Credential::Origin::Service] The created {Metasploit::Credential::Origin::Service} object
338
- def create_credential_origin_service(opts={})
339
- return nil unless active_db?
340
- module_fullname = opts.fetch(:module_fullname)
341
-
342
- service_object = create_credential_service(opts)
343
-
344
- retry_transaction do
345
- Metasploit::Credential::Origin::Service.where(service_id: service_object.id, module_full_name: module_fullname).first_or_create!
346
- end
292
+ # This method is responsible for creating {Metasploit::Credential::Origin::Import} objects.
293
+ #
294
+ # @option opts [String] :filename The filename of the file that was imported
295
+ # @raise [KeyError] if a required option is missing
296
+ # @return [NilClass] if there is no connected database
297
+ # @return [Metasploit::Credential::Origin::Manual] The created {Metasploit::Credential::Origin::Import} object
298
+ def create_credential_origin_import(opts={})
299
+ return nil unless active_db?
300
+ filename = opts.fetch(:filename)
301
+
302
+ retry_transaction do
303
+ Metasploit::Credential::Origin::Import.where(filename: filename).first_or_create!
304
+ end
305
+ end
347
306
 
348
- end
307
+ # This method is responsible for creating {Metasploit::Credential::Origin::Manual} objects.
308
+ #
309
+ # @option opts [Fixnum] :user_id The ID of the `Mdm::User` to link this Origin to
310
+ # @raise [KeyError] if a required option is missing
311
+ # @return [NilClass] if there is no connected database
312
+ # @return [Metasploit::Credential::Origin::Manual] The created {Metasploit::Credential::Origin::Manual} object
313
+ def create_credential_origin_manual(opts={})
314
+ return nil unless active_db?
315
+ user_id = opts.fetch(:user_id)
316
+
317
+ retry_transaction do
318
+ Metasploit::Credential::Origin::Manual.where(user_id: user_id).first_or_create!
319
+ end
320
+ end
349
321
 
350
- # This method is responsible for creating {Metasploit::Credential::Origin::Session} objects.
351
- #
352
- # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
353
- # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
354
- # @raise [KeyError] if a required option is missing
355
- # @return [NilClass] if there is no connected database
356
- # @return [Metasploit::Credential::Origin::Session] The created {Metasploit::Credential::Origin::Session} object
357
- def create_credential_origin_session(opts={})
358
- return nil unless active_db?
359
- session_id = opts.fetch(:session_id)
360
- post_reference_name = opts.fetch(:post_reference_name)
361
-
362
- retry_transaction do
363
- Metasploit::Credential::Origin::Session.where(session_id: session_id, post_reference_name: post_reference_name).first_or_create!
364
- end
365
- end
322
+ # This method is responsible for creating {Metasploit::Credential::Origin::Service} objects.
323
+ # If there is not a matching `Mdm::Host` it will create it. If there is not a matching
324
+ # `Mdm::Service` it will create that too.
325
+ #
326
+ # @option opts [String] :address The address of the `Mdm::Host` to link this Origin to
327
+ # @option opts [Fixnum] :port The port number of the `Mdm::Service` to link this Origin to
328
+ # @option opts [String] :service_name The service name to use for the `Mdm::Service`
329
+ # @option opts [String] :protocol The protocol type of the `Mdm::Service` to link this Origin to
330
+ # @option opts [String] :module_fullname The fullname of the Metasploit Module to link this Origin to
331
+ # @raise [KeyError] if a required option is missing
332
+ # @return [NilClass] if there is no connected database
333
+ # @return [Metasploit::Credential::Origin::Service] The created {Metasploit::Credential::Origin::Service} object
334
+ def create_credential_origin_service(opts={})
335
+ return nil unless active_db?
336
+ module_fullname = opts.fetch(:module_fullname)
337
+
338
+ service_object = create_credential_service(opts)
339
+
340
+ retry_transaction do
341
+ Metasploit::Credential::Origin::Service.where(service_id: service_object.id, module_full_name: module_fullname).first_or_create!
342
+ end
366
343
 
367
- # This method is responsible for the creation of {Metasploit::Credential::Private} objects.
368
- # It will create the correct subclass based on the type.
369
- #
370
- # @option opts [String] :jtr_format The format for John the ripper to use to try and crack this
371
- # @option opts [String] :private_data The actual data for the private (e.g. password, hash, key etc)
372
- # @option opts [Symbol] :private_type The type of {Metasploit::Credential::Private} to create
373
- # @raise [ArgumentError] if a valid type is not supplied
374
- # @raise [KeyError] if a required option is missing
375
- # @return [NilClass] if there is no active database connection
376
- # @return [Metasploit::Credential::Password] if the private_type was :password
377
- # @return [Metasploit::Credential::SSHKey] if the private_type was :ssh_key
378
- # @return [Metasploit::Credential::NTLMHash] if the private_type was :ntlm_hash
379
- # @return [Metasploit::Credential::NonreplayableHash] if the private_type was :nonreplayable_hash
380
- def create_credential_private(opts={})
381
- return nil unless active_db?
382
- private_data = opts.fetch(:private_data)
383
- private_type = opts.fetch(:private_type)
384
-
385
- private_object = nil
386
-
387
- retry_transaction do
388
- if private_data.blank?
389
- private_object = Metasploit::Credential::BlankPassword.where(data:'').first_or_create
390
- else
391
- case private_type
392
- when :password
393
- private_object = Metasploit::Credential::Password.where(data: private_data).first_or_create
394
- when :ssh_key
395
- private_object = Metasploit::Credential::SSHKey.where(data: private_data).first_or_create
396
- when :ntlm_hash
397
- private_object = Metasploit::Credential::NTLMHash.where(data: private_data).first_or_create
398
- private_object.jtr_format = 'nt,lm'
399
- when :postgres_md5
400
- private_object = Metasploit::Credential::PostgresMD5.where(data: private_data).first_or_create
401
- private_object.jtr_format = 'raw-md5,postgres'
402
- when :nonreplayable_hash
403
- private_object = Metasploit::Credential::NonreplayableHash.where(data: private_data).first_or_create
404
- if opts[:jtr_format].present?
405
- private_object.jtr_format = opts[:jtr_format]
406
- end
407
- else
408
- raise ArgumentError, "Invalid Private type: #{private_type}"
409
- end
410
- end
411
- private_object.save!
412
- end
413
- private_object
414
- end
344
+ end
415
345
 
416
- # This method is responsible for the creation of {Metasploit::Credential::Public} objects.
417
- #
418
- # @option opts [String] :username The username to use for the {Metasploit::Credential::Public}
419
- # @raise [KeyError] if a required option is missing
420
- # @return [NilClass] if there is no active database connection
421
- # @return [Metasploit::Credential::Public]
422
- def create_credential_public(opts={})
423
- return nil unless active_db?
424
- username = opts.fetch(:username)
425
-
426
- retry_transaction do
427
- if username.blank?
428
- Metasploit::Credential::BlankUsername.where(username:'').first_or_create!
429
- else
430
- Metasploit::Credential::Username.where(username: username).first_or_create!
346
+ # This method is responsible for creating {Metasploit::Credential::Origin::Session} objects.
347
+ #
348
+ # @option opts [Fixnum] :session_id The ID of the `Mdm::Session` to link this Origin to
349
+ # @option opts [String] :post_reference_name The reference name of the Metasploit Post module to link the origin to
350
+ # @raise [KeyError] if a required option is missing
351
+ # @return [NilClass] if there is no connected database
352
+ # @return [Metasploit::Credential::Origin::Session] The created {Metasploit::Credential::Origin::Session} object
353
+ def create_credential_origin_session(opts={})
354
+ return nil unless active_db?
355
+ session_id = opts.fetch(:session_id)
356
+ post_reference_name = opts.fetch(:post_reference_name)
357
+
358
+ retry_transaction do
359
+ Metasploit::Credential::Origin::Session.where(session_id: session_id, post_reference_name: post_reference_name).first_or_create!
360
+ end
361
+ end
362
+
363
+ # This method is responsible for the creation of {Metasploit::Credential::Private} objects.
364
+ # It will create the correct subclass based on the type.
365
+ #
366
+ # @option opts [String] :jtr_format The format for John the ripper to use to try and crack this
367
+ # @option opts [String] :private_data The actual data for the private (e.g. password, hash, key etc)
368
+ # @option opts [Symbol] :private_type The type of {Metasploit::Credential::Private} to create
369
+ # @raise [ArgumentError] if a valid type is not supplied
370
+ # @raise [KeyError] if a required option is missing
371
+ # @return [NilClass] if there is no active database connection
372
+ # @return [Metasploit::Credential::Password] if the private_type was :password
373
+ # @return [Metasploit::Credential::SSHKey] if the private_type was :ssh_key
374
+ # @return [Metasploit::Credential::NTLMHash] if the private_type was :ntlm_hash
375
+ # @return [Metasploit::Credential::NonreplayableHash] if the private_type was :nonreplayable_hash
376
+ def create_credential_private(opts={})
377
+ return nil unless active_db?
378
+ private_data = opts.fetch(:private_data)
379
+ private_type = opts.fetch(:private_type)
380
+
381
+ private_object = nil
382
+
383
+ retry_transaction do
384
+ if private_data.blank?
385
+ private_object = Metasploit::Credential::BlankPassword.where(data:'').first_or_create
386
+ else
387
+ case private_type
388
+ when :password
389
+ private_object = Metasploit::Credential::Password.where(data: private_data).first_or_create
390
+ when :ssh_key
391
+ private_object = Metasploit::Credential::SSHKey.where(data: private_data).first_or_create
392
+ when :ntlm_hash
393
+ private_object = Metasploit::Credential::NTLMHash.where(data: private_data).first_or_create
394
+ private_object.jtr_format = 'nt,lm'
395
+ when :postgres_md5
396
+ private_object = Metasploit::Credential::PostgresMD5.where(data: private_data).first_or_create
397
+ private_object.jtr_format = 'raw-md5,postgres'
398
+ when :nonreplayable_hash
399
+ private_object = Metasploit::Credential::NonreplayableHash.where(data: private_data).first_or_create
400
+ if opts[:jtr_format].present?
401
+ private_object.jtr_format = opts[:jtr_format]
431
402
  end
403
+ else
404
+ raise ArgumentError, "Invalid Private type: #{private_type}"
432
405
  end
433
406
  end
407
+ private_object.save!
408
+ end
409
+ private_object
410
+ end
434
411
 
435
- # This method is responsible for creating the {Metasploit::Credential::Realm} objects
436
- # that may be required.
437
- #
438
- # @option opts [String] :realm_key The type of Realm this is (e.g. 'Active Directory Domain')
439
- # @option opts [String] :realm_value The actual Realm name (e.g. contosso)
440
- # @raise [KeyError] if a required option is missing
441
- # @return [NilClass] if there is no active database connection
442
- # @return [Metasploit::Credential::Realm] if it successfully creates or finds the object
443
- def create_credential_realm(opts={})
444
- return nil unless active_db?
445
- realm_key = opts.fetch(:realm_key)
446
- realm_value = opts.fetch(:realm_value)
447
-
448
- retry_transaction do
449
- Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first_or_create!
450
- end
412
+ # This method is responsible for the creation of {Metasploit::Credential::Public} objects.
413
+ #
414
+ # @option opts [String] :username The username to use for the {Metasploit::Credential::Public}
415
+ # @raise [KeyError] if a required option is missing
416
+ # @return [NilClass] if there is no active database connection
417
+ # @return [Metasploit::Credential::Public]
418
+ def create_credential_public(opts={})
419
+ return nil unless active_db?
420
+ username = opts.fetch(:username)
421
+
422
+ retry_transaction do
423
+ if username.blank?
424
+ Metasploit::Credential::BlankUsername.where(username:'').first_or_create!
425
+ else
426
+ Metasploit::Credential::Username.where(username: username).first_or_create!
451
427
  end
428
+ end
429
+ end
452
430
 
431
+ # This method is responsible for creating the {Metasploit::Credential::Realm} objects
432
+ # that may be required.
433
+ #
434
+ # @option opts [String] :realm_key The type of Realm this is (e.g. 'Active Directory Domain')
435
+ # @option opts [String] :realm_value The actual Realm name (e.g. contosso)
436
+ # @raise [KeyError] if a required option is missing
437
+ # @return [NilClass] if there is no active database connection
438
+ # @return [Metasploit::Credential::Realm] if it successfully creates or finds the object
439
+ def create_credential_realm(opts={})
440
+ return nil unless active_db?
441
+ realm_key = opts.fetch(:realm_key)
442
+ realm_value = opts.fetch(:realm_value)
443
+
444
+ retry_transaction do
445
+ Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first_or_create!
446
+ end
447
+ end
453
448
 
454
449
 
455
- # This method is responsible for creating a barebones `Mdm::Service` object
456
- # for use by Credential object creation.
457
- #
458
- # @option opts [String] :address The address of the `Mdm::Host`
459
- # @option opts [Fixnum] :port The port number of the `Mdm::Service`
460
- # @option opts [String] :service_name The service name to use for the `Mdm::Service`
461
- # @option opts [String] :protocol The protocol type of the `Mdm::Service``
462
- # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
463
- # @raise [KeyError] if a required option is missing
464
- # @return [NilClass] if there is no connected database
465
- # @return [Mdm::Service]
466
- def create_credential_service(opts={})
467
- return nil unless active_db?
468
- address = opts.fetch(:address)
469
- port = opts.fetch(:port)
470
- service_name = opts.fetch(:service_name)
471
- protocol = opts.fetch(:protocol)
472
- workspace_id = opts.fetch(:workspace_id)
473
-
474
- host_object = Mdm::Host.where(address: address, workspace_id: workspace_id).first_or_create
475
- service_object = Mdm::Service.where(host_id: host_object.id, port: port, proto: protocol).first_or_initialize
476
-
477
- service_object.name = service_name
478
- service_object.state = "open"
479
- service_object.save!
480
-
481
- service_object
482
- end
483
450
 
484
- # This method checks to see if a {Metasploit::Credential::Login} exists for a given
485
- # set of details. If it does exists, we then appropriately set the status to one of our
486
- # failure statuses.
487
- #
488
- # @option opts [String] :address The address of the host we attempted
489
- # @option opts [Fixnum] :port the port of the service we attempted
490
- # @option opts [String] :protocol the transport protocol of the service we attempted
491
- # @option opts [String] :public A string representation of the public we tried
492
- # @option opts [String] :private A string representation of the private we tried
493
- # @option opts [Symbol] :status The status symbol from the {Metasploit::Framework::LoginScanner::Result}
494
- # @raise [KeyError] if any of the above options are missing
495
- # @return [void] Do not worry about the return value from this method
496
- def invalidate_login(opts = {})
497
- return nil unless active_db?
498
- address = opts.fetch(:address)
499
- port = opts.fetch(:port)
500
- protocol = opts.fetch(:protocol)
501
- public = opts.fetch(:username, nil)
502
- private = opts.fetch(:private_data, nil)
503
- realm_key = opts.fetch(:realm_key, nil)
504
- realm_value = opts.fetch(:realm_value, nil)
505
- status = opts.fetch(:status)
506
-
507
-
508
- pub_obj = Metasploit::Credential::Public.where(username: public).first.try(:id)
509
- priv_obj = Metasploit::Credential::Private.where(data: private).first.try(:id)
510
- realm_obj = Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first.try(:id)
511
-
512
- core = Metasploit::Credential::Core.where(public_id: pub_obj, private_id: priv_obj, realm_id: realm_obj).first
513
-
514
- # Do nothing else if we have no matching core. Otherwise look for a Login.
515
- if core.present?
516
- login = core.logins.joins(service: :host).where(services: { port: port, proto: protocol } ).where( hosts: {address: address}).readonly(false).first
517
-
518
- if login.present?
519
- login.status = status
520
- login.last_attempted_at = DateTime.now
521
- login.save!
522
- end
523
-
524
- end
451
+ # This method is responsible for creating a barebones `Mdm::Service` object
452
+ # for use by Credential object creation.
453
+ #
454
+ # @option opts [String] :address The address of the `Mdm::Host`
455
+ # @option opts [Fixnum] :port The port number of the `Mdm::Service`
456
+ # @option opts [String] :service_name The service name to use for the `Mdm::Service`
457
+ # @option opts [String] :protocol The protocol type of the `Mdm::Service``
458
+ # @option opts [Fixnum] :workspace_id The ID of the `Mdm::Workspace` to use for the `Mdm::Host`
459
+ # @raise [KeyError] if a required option is missing
460
+ # @return [NilClass] if there is no connected database
461
+ # @return [Mdm::Service]
462
+ def create_credential_service(opts={})
463
+ return nil unless active_db?
464
+ address = opts.fetch(:address)
465
+ port = opts.fetch(:port)
466
+ service_name = opts.fetch(:service_name)
467
+ protocol = opts.fetch(:protocol)
468
+ workspace_id = opts.fetch(:workspace_id)
469
+
470
+ host_object = Mdm::Host.where(address: address, workspace_id: workspace_id).first_or_create
471
+ service_object = Mdm::Service.where(host_id: host_object.id, port: port, proto: protocol).first_or_initialize
472
+
473
+ service_object.name = service_name
474
+ service_object.state = "open"
475
+ service_object.save!
476
+
477
+ service_object
478
+ end
525
479
 
480
+ # This method checks to see if a {Metasploit::Credential::Login} exists for a given
481
+ # set of details. If it does exists, we then appropriately set the status to one of our
482
+ # failure statuses.
483
+ #
484
+ # @option opts [String] :address The address of the host we attempted
485
+ # @option opts [Fixnum] :port the port of the service we attempted
486
+ # @option opts [String] :protocol the transport protocol of the service we attempted
487
+ # @option opts [String] :public A string representation of the public we tried
488
+ # @option opts [String] :private A string representation of the private we tried
489
+ # @option opts [Symbol] :status The status symbol from the {Metasploit::Framework::LoginScanner::Result}
490
+ # @raise [KeyError] if any of the above options are missing
491
+ # @return [void] Do not worry about the return value from this method
492
+ def invalidate_login(opts = {})
493
+ return nil unless active_db?
494
+ address = opts.fetch(:address)
495
+ port = opts.fetch(:port)
496
+ protocol = opts.fetch(:protocol)
497
+ public = opts.fetch(:username, nil)
498
+ private = opts.fetch(:private_data, nil)
499
+ realm_key = opts.fetch(:realm_key, nil)
500
+ realm_value = opts.fetch(:realm_value, nil)
501
+ status = opts.fetch(:status)
502
+
503
+
504
+ pub_obj = Metasploit::Credential::Public.where(username: public).first.try(:id)
505
+ priv_obj = Metasploit::Credential::Private.where(data: private).first.try(:id)
506
+ realm_obj = Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first.try(:id)
507
+
508
+ core = Metasploit::Credential::Core.where(public_id: pub_obj, private_id: priv_obj, realm_id: realm_obj).first
509
+
510
+ # Do nothing else if we have no matching core. Otherwise look for a Login.
511
+ if core.present?
512
+ login = core.logins.joins(service: :host).where(services: { port: port, proto: protocol } ).where( hosts: {address: address}).readonly(false).first
513
+
514
+ if login.present?
515
+ login.status = status
516
+ login.last_attempted_at = DateTime.now
517
+ login.save!
526
518
  end
527
519
 
520
+ end
528
521
 
529
- private
530
-
531
- # This method wraps a block in a retry if we get a RecordNotUnique validation error.
532
- # This helps guard against race conditions.
533
- def retry_transaction(&block)
534
- tries = 3
535
- begin
536
- yield
537
- rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
538
- tries -= 1
539
- if tries > 0
540
- retry
541
- else
542
- raise
543
- end
544
- end
545
- end
522
+ end
546
523
 
524
+
525
+ private
526
+
527
+ # This method wraps a block in a retry if we get a RecordNotUnique validation error.
528
+ # This helps guard against race conditions.
529
+ def retry_transaction(&block)
530
+ tries = 3
531
+ begin
532
+ yield
533
+ rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
534
+ tries -= 1
535
+ if tries > 0
536
+ retry
537
+ else
538
+ raise
539
+ end
547
540
  end
548
541
  end
549
542
  end