metasploit-credential 0.14.3 → 0.14.4

Sign up to get free protection for your applications and to get access to all the features.
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