Skip to content

Commit

Permalink
Update ms_icpr and creds to reflect the changes in the Pkcs12 dat…
Browse files Browse the repository at this point in the history
…a model

- a separate field is now used for metadata (`private_metadata`) when
  creating a new Pkcs12
- the `creds` command now support adding an encrypted Pkcs12 with a password
  • Loading branch information
cdelafuente-r7 committed Feb 6, 2025
1 parent d0a4593 commit 3581724
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 27 deletions.
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2022_12_09_005658) do
ActiveRecord::Schema[7.0].define(version: 2025_02_04_172657) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand Down Expand Up @@ -314,6 +314,7 @@
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "jtr_format"
t.jsonb "metadata", default: {}, null: false
t.index "type, decode(md5(data), 'hex'::text)", name: "index_metasploit_credential_privates_on_type_and_data_pkcs12", unique: true, where: "((type)::text = 'Metasploit::Credential::Pkcs12'::text)"
t.index "type, decode(md5(data), 'hex'::text)", name: "index_metasploit_credential_privates_on_type_and_data_sshkey", unique: true, where: "((type)::text = 'Metasploit::Credential::SSHKey'::text)"
t.index ["type", "data"], name: "index_metasploit_credential_privates_on_type_and_data", unique: true, where: "(NOT (((type)::text = 'Metasploit::Credential::SSHKey'::text) OR ((type)::text = 'Metasploit::Credential::Pkcs12'::text)))"
Expand Down
8 changes: 2 additions & 6 deletions lib/msf/core/exploit/remote/ms_icpr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,8 @@ def do_request_cert(icpr, opts)
workspace_id: myworkspace_id,
username: upn || datastore['SMBUser'],
private_type: :pkcs12,
private_data: Metasploit::Credential::Pkcs12.build_data(
# pkcs12 is a binary format, but for persisting we Base64 encode it
pkcs12: Base64.strict_encode64(pkcs12.to_der),
ca: datastore['CA'],
adcs_template: cert_template
),
private_data: Base64.strict_encode64(pkcs12.to_der),
private_metadata: { ca: datastore['CA'], adcs_template: cert_template },
origin_type: :service,
module_fullname: fullname
}
Expand Down
39 changes: 20 additions & 19 deletions lib/msf/ui/console/command_dispatcher/creds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,19 @@ def cmd_creds_help
print_line "Usage - Adding credentials:"
print_line " creds add uses the following named parameters."
{
user: 'Public, usually a username',
password: 'Private, private_type Password.',
ntlm: 'Private, private_type NTLM Hash.',
postgres: 'Private, private_type postgres MD5',
pkcs12: 'Private, private_type pkcs12 archive file, must be a file path.',
'ssh-key' => 'Private, private_type SSH key, must be a file path.',
hash: 'Private, private_type Nonreplayable hash',
jtr: 'Private, private_type John the Ripper hash type.',
realm: 'Realm, ',
'realm-type' => "Realm, realm_type (#{Metasploit::Model::Realm::Key::SHORT_NAMES.keys.join(' ')}), defaults to domain.",
ca: 'CA, Certificate Authority that issued the pkcs12 certificate',
'adcs-template' => 'ADCS Template, template used to issue the pkcs12 certificate'
user: 'Public, usually a username',
password: 'Private, private_type Password.',
ntlm: 'Private, private_type NTLM Hash.',
postgres: 'Private, private_type postgres MD5',
pkcs12: 'Private, private_type pkcs12 archive file, must be a file path.',
'ssh-key' => 'Private, private_type SSH key, must be a file path.',
hash: 'Private, private_type Nonreplayable hash',
jtr: 'Private, private_type John the Ripper hash type.',
realm: 'Realm, ',
'realm-type' => "Realm, realm_type (#{Metasploit::Model::Realm::Key::SHORT_NAMES.keys.join(' ')}), defaults to domain.",
ca: 'CA, Certificate Authority that issued the pkcs12 certificate',
'adcs-template' => 'ADCS Template, template used to issue the pkcs12 certificate',
'pkcs12-password' => 'The password to decrypt the Pkcs12, defaults to an empty password'
}.each_pair do |keyword, description|
print_line " #{keyword.to_s.ljust 10}: #{description}"
end
Expand Down Expand Up @@ -208,7 +209,7 @@ def creds_add(*args)
end

begin
params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name', 'jtr', 'pkcs12', 'postgres', 'ca', 'adcs-template')
params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name', 'jtr', 'pkcs12', 'postgres', 'ca', 'adcs-template', 'pkcs12-password')
rescue ArgumentError => e
print_error(e.message)
end
Expand Down Expand Up @@ -277,11 +278,11 @@ def creds_add(*args)
print_error("Failed to add pkcs12 archive: #{e}")
end
data[:private_type] = :pkcs12
data[:private_data] = Metasploit::Credential::Pkcs12.build_data(
pkcs12: pkcs12_data,
ca: params['ca'],
adcs_template: params['adcs-template']
)
data[:private_data] = pkcs12_data
data[:private_metadata] = {}
data[:private_metadata][:ca] = params['ca'] if params['ca']
data[:private_metadata][:adcs_template] = params['adcs-template'] if params['adcs-template']
data[:private_metadata][:pkcs12_password] = params['pkcs12-password'] if params['pkcs12-password']
end

if params.key? 'hash'
Expand Down Expand Up @@ -311,7 +312,7 @@ def creds_add(*args)
framework.db.create_credential(data)
end
rescue ActiveRecord::RecordInvalid => e
print_error("Failed to add #{data['private_type']}: #{e}")
print_error("Failed to add #{data[:private_type]}: #{e}")
end
end

Expand Down
24 changes: 23 additions & 1 deletion spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@
let(:priv) { FactoryBot.create(:metasploit_credential_pkcs12) }
before(:each) do
@file = Tempfile.new('mypkcs12.pfx')
@file.write(Base64.strict_decode64(priv.pkcs12))
@file.write(Base64.strict_decode64(priv.data))
@file.close
end
it 'creates a core if one does not exist' do
Expand All @@ -550,6 +550,28 @@
creds.cmd_creds('add', "pkcs12:#{@file.path}")
}.to_not change { Metasploit::Credential::Core.count }
end

context 'with a password' do
let(:pkcs12_password) { 'mypass' }
let(:priv) {
FactoryBot.create(:metasploit_credential_pkcs12,
pkcs12_password: pkcs12_password,
metadata: { pkcs12_password: pkcs12_password }
)
}

it 'creates a core if the password is correct' do
expect {
creds.cmd_creds('add', "pkcs12:#{@file.path}", "pkcs12-password:#{pkcs12_password}")
}.to change { Metasploit::Credential::Core.count }.by 1
end

it 'does not creates a core if the password is incorrect' do
expect {
creds.cmd_creds('add', "pkcs12:#{@file.path}", "pkcs12-password:wrongpass")
}.to_not change { Metasploit::Credential::Core.count }
end
end
end
end
context 'realm-types' do
Expand Down

0 comments on commit 3581724

Please sign in to comment.