metasploit-credential 6.0.4 → 6.0.5

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
  SHA256:
3
- metadata.gz: 97884e997f5fe9428e4fc79f0b4a9e4a4e51a06363b372a2fa1affa0dffba6d5
4
- data.tar.gz: 37e4b1a543e249e7facb0c6570efd104d4bf347922636b561aecb78bab0602a8
3
+ metadata.gz: c890cd98fc73ff6cbd909ded7207646f534477a4308f60f1e7dc09231cd29d88
4
+ data.tar.gz: 62fd27bcb61c852fb705cb89a0848771f6c4ae64b6a3c76202228ea6d2037969
5
5
  SHA512:
6
- metadata.gz: 23da300c2d52cd12a8aeb398010b21d2542ab4f88f59946fabde21efbb3554c30f36b32839961abef13c43528324ddacc807d68872cc9df3bbf2e47d31c66905
7
- data.tar.gz: 90f93c7bd036e2f6b328dca97707d5e85bd40a257cb6f7dba928d0d6fd983cd295e38b3052cb6aae271c37bd730e4b5c36e71feed1e1dc561bb0b163c207d098
6
+ metadata.gz: 06bf39bbda84fc40c4f25085a39e4f27211a50246879fbe3b50f034c502a9b6fcf7cebbe9292912a4bfc42f8804837a45e8cbc332253b5f3fc5b122983f6b23e
7
+ data.tar.gz: d361ca8222849ab597accea494fef812339b971537bcd9cdbc3259eb19271a57f31cd1773c8338282211bf43569ee507888eb09f7326799b9ec6d66140bc50cd
checksums.yaml.gz.sig CHANGED
Binary file
@@ -73,7 +73,8 @@ class Metasploit::Credential::KrbEncKey < Metasploit::Credential::PasswordHash
73
73
  # Callbacks
74
74
  #
75
75
 
76
- before_validation :normalize_data
76
+ serialize :data, Metasploit::Credential::CaseInsensitiveSerializer
77
+ validates_uniqueness_of :data, :case_sensitive => false
77
78
 
78
79
  #
79
80
  # Validations
@@ -162,15 +163,6 @@ class Metasploit::Credential::KrbEncKey < Metasploit::Credential::PasswordHash
162
163
  }
163
164
  end
164
165
 
165
- # Normalizes {#data} by making it all lowercase so that the unique validation and index on
166
- # ({Metasploit::Credential::Private#type}, {#data}) catches collision in a case-insensitive manner without the need
167
- # to use case-insensitive comparisons.
168
- def normalize_data
169
- if data
170
- self.data = data.downcase
171
- end
172
- end
173
-
174
166
  # Validates that {#data} is in the expected data format
175
167
  def data_format
176
168
  unless DATA_REGEXP.match(data)
@@ -55,15 +55,18 @@ class Metasploit::Credential::NTLMHash < Metasploit::Credential::ReplayableHash
55
55
  # @return [String] `'<LAN Manager hex digest>:<NT LAN Manager hex digest>'`
56
56
 
57
57
  #
58
- # Callbacks
58
+ # Serializers
59
59
  #
60
60
 
61
- before_validation :normalize_data
61
+ # Hash results are always downcased when stored in the database
62
+ # This serializer allows for ORM to search in a case-insensitive
63
+ serialize :data, Metasploit::Credential::CaseInsensitiveSerializer
62
64
 
63
65
  #
64
66
  # Validations
65
67
  #
66
68
 
69
+ validates_uniqueness_of :data, :case_sensitive => false
67
70
  validate :data_format
68
71
 
69
72
  #
@@ -130,15 +133,6 @@ class Metasploit::Credential::NTLMHash < Metasploit::Credential::ReplayableHash
130
133
 
131
134
  private
132
135
 
133
- # Normalizes {#data} by making it all lowercase so that the unique validation and index on
134
- # ({Metasploit::Credential::Private#type}, {#data}) catches collision in a case-insensitive manner without the need
135
- # to use case-insensitive comparisons.
136
- def normalize_data
137
- if data
138
- self.data = data.downcase
139
- end
140
- end
141
-
142
136
  # Validates that {#data} is in the NTLM data format of <LAN Manager hex digest>:<NT LAN Manager hex digest>. Both hex
143
137
  # digests are 32 lowercase hexadecimal characters.
144
138
  def data_format
@@ -13,7 +13,8 @@ class Metasploit::Credential::PostgresMD5 < Metasploit::Credential::ReplayableHa
13
13
  # Callbacks
14
14
  #
15
15
 
16
- before_validation :normalize_data
16
+ serialize :data, Metasploit::Credential::CaseInsensitiveSerializer
17
+ validates_uniqueness_of :data, :case_sensitive => false
17
18
 
18
19
  #
19
20
  # Validations
@@ -23,15 +24,6 @@ class Metasploit::Credential::PostgresMD5 < Metasploit::Credential::ReplayableHa
23
24
 
24
25
  private
25
26
 
26
- # Normalizes {#data} by making it all lowercase so that the unique validation and index on
27
- # ({Metasploit::Credential::Private#type}, {#data}) catches collision in a case-insensitive manner without the need
28
- # to use case-insensitive comparisons.
29
- def normalize_data
30
- if data
31
- self.data = data.downcase
32
- end
33
- end
34
-
35
27
  def data_format
36
28
  unless DATA_REGEXP.match(data)
37
29
  errors.add(:data, 'is not in Postgres MD5 Hash format')
@@ -0,0 +1,9 @@
1
+ class Metasploit::Credential::CaseInsensitiveSerializer
2
+ def self.load(value)
3
+ value
4
+ end
5
+
6
+ def self.dump(value)
7
+ value.downcase
8
+ end
9
+ end
@@ -116,7 +116,6 @@ class Metasploit::Credential::Importer::Core
116
116
  private_class = row['private_type'].present? ? row['private_type'].constantize : ''
117
117
  private_data = row['private_data'].present? ? row['private_data'] : ''
118
118
 
119
-
120
119
  if realms[realm_value].nil?
121
120
  realms[realm_value] = Metasploit::Credential::Realm.where(key: realm_key, value: realm_value).first_or_create
122
121
  end
@@ -210,7 +209,7 @@ class Metasploit::Credential::Importer::Core
210
209
  if private_data.strip == BLANK_TOKEN
211
210
  private_object_for_row = Metasploit::Credential::BlankPassword.first_or_create
212
211
  else
213
- private_object_for_row = @private_credential_type.constantize.where(data: row['private_data']).first_or_create
212
+ private_object_for_row = @private_credential_type.constantize.where(data: private_data).first_or_create
214
213
  end
215
214
 
216
215
  # need to check private_object_for_row.valid? to raise a user facing message if any cred had invalid private
@@ -3,7 +3,7 @@
3
3
  module Metasploit
4
4
  module Credential
5
5
  # VERSION is managed by GemRelease
6
- VERSION = '6.0.4'
6
+ VERSION = '6.0.5'
7
7
 
8
8
  # @return [String]
9
9
  #
@@ -28,6 +28,7 @@ module Metasploit
28
28
 
29
29
  autoload :BlankPassword
30
30
  autoload :BlankUsername
31
+ autoload :CaseInsensitiveSerializer
31
32
  autoload :Core
32
33
  autoload :CoreValidations
33
34
  autoload :Creation
@@ -1,6 +1,6 @@
1
1
  development: &pgsql
2
2
  adapter: postgresql
3
- database: metasploit-credential_development3
3
+ database: metasploit-credential_development2
4
4
  username: msf
5
5
  password: pass123
6
6
  host: localhost
@@ -10,4 +10,4 @@ development: &pgsql
10
10
  min_messages: warning
11
11
  test:
12
12
  <<: *pgsql
13
- database: metasploit-credential_test3
13
+ database: metasploit-credential_test2
@@ -178,6 +178,37 @@ RSpec.describe Metasploit::Credential::Creation do
178
178
  end
179
179
  end
180
180
  end
181
+ context 'deletion and creation' do
182
+ let(:private_data) { 'md5ac4bbe016b808c3c0b816981f240dcae' }
183
+ let(:private_data_upcase) { private_data.upcase }
184
+ let(:credential_data) {{
185
+ workspace_id: workspace.id,
186
+ user_id: user.id,
187
+ origin_type: :manual,
188
+ username: 'admin',
189
+ private_data: private_data,
190
+ private_type: :postgres_md5
191
+ }}
192
+ it 'creates a private cred' do
193
+ expect{ test_object.create_credential(credential_data) }.to change{ Metasploit::Credential::PostgresMD5.count }.by(1)
194
+ end
195
+ let(:credential_data_upcase) {{
196
+ workspace_id: workspace.id,
197
+ user_id: user.id,
198
+ origin_type: :manual,
199
+ username: 'admin',
200
+ private_data: private_data_upcase,
201
+ private_type: :postgres_md5
202
+ }}
203
+ it 'allows for the recreation of core with case insensitive private credentials set to different case' do
204
+ expect{ test_object.create_credential(credential_data) }.to change{ Metasploit::Credential::PostgresMD5.count }.by(1)
205
+ expect{ Metasploit::Credential::Core.first.destroy }.to change{ Metasploit::Credential::Core.count }.by(-1)
206
+ expect( Metasploit::Credential::PostgresMD5.count ).to eq(1)
207
+ expect( Metasploit::Credential::Core.count ).to eq(0)
208
+ expect{ test_object.create_credential(credential_data_upcase) }.to change{ Metasploit::Credential::Core.count }.by(1)
209
+ expect( Metasploit::Credential::PostgresMD5.count ).to eq(1)
210
+ end
211
+ end
181
212
  end
182
213
 
183
214
  context '#create_credential_and_login' do
@@ -148,4 +148,30 @@ RSpec.describe Metasploit::Credential::KrbEncKey, type: :model do
148
148
  end
149
149
  end
150
150
  end
151
+
152
+ context 'serialization' do
153
+ context '#first_or_create' do
154
+ let(:data) { 'msf_krbenckey:23:e22e04519aa757d12f1219c4f31252f4:' }
155
+ let(:upcase_data) {data.upcase}
156
+
157
+ context 'creates a new instance that stores case-insensitive value' do
158
+ it 'creates case insensitive data' do
159
+ expect{ Metasploit::Credential::KrbEncKey.where(data: data).first_or_create }.to change{Metasploit::Credential::KrbEncKey.count}.by(1)
160
+ expect{ Metasploit::Credential::KrbEncKey.where(data: upcase_data).first_or_create }.not_to change{Metasploit::Credential::KrbEncKey.count}
161
+ end
162
+ end
163
+
164
+ context 'finds an existing case insensitive match' do
165
+ let(:krb_enc_key) do
166
+ FactoryBot.build(
167
+ :metasploit_credential_krb_enc_key,
168
+ data: upcase_data
169
+ )
170
+ end
171
+ it 'successfully looks up credential in case insensitive way' do
172
+ expect( krb_enc_key.data ).to eq(data)
173
+ end
174
+ end
175
+ end
176
+ end
151
177
  end
@@ -397,5 +397,29 @@ RSpec.describe Metasploit::Credential::NTLMHash, type: :model do
397
397
  end
398
398
  end
399
399
 
400
+ context 'serialization' do
401
+ context '#first_or_create' do
402
+ let(:data) { 'aad3b435b51404eeaad3b435b51404ee:4dc0249ad90ab626362050195893c788' }
403
+ let(:upcase_data) {data.upcase}
404
+
405
+ context 'creates a new instance that stores case-insensitive value' do
406
+ it 'creates case insensitive data' do
407
+ expect{ Metasploit::Credential::NTLMHash.where(data: data).first_or_create }.to change{Metasploit::Credential::NTLMHash.count}.by(1)
408
+ expect{ Metasploit::Credential::NTLMHash.where(data: upcase_data).first_or_create }.not_to change{Metasploit::Credential::NTLMHash.count}
409
+ end
410
+ end
400
411
 
412
+ context 'finds an existing case insensitive match' do
413
+ let(:ntlm_hash) do
414
+ FactoryBot.build(
415
+ :metasploit_credential_ntlm_hash,
416
+ data: upcase_data
417
+ )
418
+ end
419
+ it 'successfully looks up credential in case insensitive way' do
420
+ expect( ntlm_hash.data ).to eq(data)
421
+ end
422
+ end
423
+ end
424
+ end
401
425
  end
@@ -119,4 +119,30 @@ RSpec.describe Metasploit::Credential::PostgresMD5, type: :model do
119
119
  end
120
120
  end
121
121
 
122
+ context 'serialization' do
123
+ context '#first_or_create' do
124
+ let(:data) { "md5#{SecureRandom.hex(16)}" }
125
+ let(:upcase_data) {data.upcase}
126
+
127
+ context 'creates a new instance that stores case-insensitive value' do
128
+ it 'creates case insensitive data' do
129
+ expect{ Metasploit::Credential::PostgresMD5.where(data: data).first_or_create }.to change{Metasploit::Credential::PostgresMD5.count}.by(1)
130
+ expect{ Metasploit::Credential::PostgresMD5.where(data: upcase_data).first_or_create }.not_to change{Metasploit::Credential::PostgresMD5.count}
131
+ end
132
+ end
133
+
134
+ context 'finds an existing case insensitive match' do
135
+ let(:postgres_md5) do
136
+ FactoryBot.build(
137
+ :metasploit_credential_postgres_md5,
138
+ data: upcase_data
139
+ )
140
+ end
141
+
142
+ it 'successfully looks up credential in case insensitive way' do
143
+ expect( postgres_md5.data ).to eq(data)
144
+ end
145
+ end
146
+ end
147
+ end
122
148
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metasploit-credential
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.4
4
+ version: 6.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -93,7 +93,7 @@ cert_chain:
93
93
  EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
94
94
  9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
95
95
  -----END CERTIFICATE-----
96
- date: 2023-04-11 00:00:00.000000000 Z
96
+ date: 2023-05-19 00:00:00.000000000 Z
97
97
  dependencies:
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: metasploit-concern
@@ -291,6 +291,7 @@ files:
291
291
  - db/migrate/20161107203710_create_index_on_private_data_and_type_for_ssh_key.rb
292
292
  - db/migrate/20221209005658_create_index_on_private_data_and_type_for_pkcs12.rb
293
293
  - lib/metasploit/credential.rb
294
+ - lib/metasploit/credential/case_insensitive_serializer.rb
294
295
  - lib/metasploit/credential/core_validations.rb
295
296
  - lib/metasploit/credential/creation.rb
296
297
  - lib/metasploit/credential/engine.rb
metadata.gz.sig CHANGED
Binary file