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 12, 2025
1 parent d0a4593 commit 407494c
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 45 deletions.
1 change: 1 addition & 0 deletions .github/workflows/command_shell_acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ jobs:
path: metasploit-framework

- name: Setup Ruby
run: git config --system core.longpaths true
env:
BUNDLE_FORCE_RUBY_PLATFORM: true
uses: ruby/setup-ruby@v1
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/shared_meterpreter_acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ jobs:
ref: ${{ inputs.metasploit_framework_commit }}

- name: Setup Ruby
run: git config --system core.longpaths true
env:
BUNDLE_FORCE_RUBY_PLATFORM: true
# Required for macos13 pg gem compilation
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ source 'https://rubygems.org'
gemspec name: 'metasploit-framework'

gem 'metasploit-credential', git: 'https://github.com/cdelafuente-r7/metasploit-credential', branch: 'enh/MS-9710/add_pkcs12_metadata'
gem 'metasploit-model', git: 'https://github.com/cdelafuente-r7/metasploit-model', branch: 'feat/model/search/operation/jsonb'
gem 'metasploit_data_models', git: 'https://github.com/cdelafuente-r7/metasploit_data_models', branch: 'enh/visitor/jsonb'

# separate from test as simplecov is not run on travis-ci
group :coverage do
Expand Down
44 changes: 29 additions & 15 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
GIT
remote: https://github.com/cdelafuente-r7/metasploit-credential
revision: acc5a012f4bc7e7774af059e778b947cd994da1e
revision: 6c8554df2feab43489ca86eada790970e9749fb3
branch: enh/MS-9710/add_pkcs12_metadata
specs:
metasploit-credential (6.0.12)
Expand All @@ -14,6 +14,32 @@ GIT
rubyntlm
rubyzip

GIT
remote: https://github.com/cdelafuente-r7/metasploit-model
revision: 925a11f61f02123f29e32bb196b374390d36beb6
branch: feat/model/search/operation/jsonb
specs:
metasploit-model (5.0.3)
activemodel (~> 7.0)
activesupport (~> 7.0)
railties (~> 7.0)

GIT
remote: https://github.com/cdelafuente-r7/metasploit_data_models
revision: 34fc27d3059c919eac98cf2a8061c31146189a26
branch: enh/visitor/jsonb
specs:
metasploit_data_models (6.0.6)
activerecord (~> 7.0)
activesupport (~> 7.0)
arel-helpers
metasploit-concern
metasploit-model (>= 3.1)
pg
railties (~> 7.0)
recog
webrick

PATH
remote: .
specs:
Expand Down Expand Up @@ -308,21 +334,7 @@ GEM
activesupport (~> 7.0)
railties (~> 7.0)
zeitwerk
metasploit-model (5.0.2)
activemodel (~> 7.0)
activesupport (~> 7.0)
railties (~> 7.0)
metasploit-payloads (2.0.189)
metasploit_data_models (6.0.5)
activerecord (~> 7.0)
activesupport (~> 7.0)
arel-helpers
metasploit-concern
metasploit-model (>= 3.1)
pg
railties (~> 7.0)
recog
webrick
metasploit_payloads-mettle (1.0.35)
method_source (1.1.0)
mime-types (3.6.0)
Expand Down Expand Up @@ -597,6 +609,8 @@ DEPENDENCIES
memory_profiler
metasploit-credential!
metasploit-framework!
metasploit-model!
metasploit_data_models!
octokit
pry-byebug
rake
Expand Down
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: { adcs_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.",
'adcs-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', 'adcs-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][:adcs_ca] = params['adcs-ca'] if params['adcs-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
43 changes: 39 additions & 4 deletions spec/lib/msf/ui/console/command_dispatcher/creds_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
priv = FactoryBot.create(:metasploit_credential_pkcs12_with_ca_and_adcs_template,
subject: pkcs12_subject,
issuer: pkcs12_issuer,
ca: pkcs12_ca,
adcs_ca: pkcs12_ca,
adcs_template: pkcs12_adcs_template)
FactoryBot.create(:metasploit_credential_core,
origin: FactoryBot.create(:metasploit_credential_origin_import),
Expand Down Expand Up @@ -331,7 +331,7 @@

context 'pkcs12' do
it 'should show just the pkcs12' do
private_str = "subject:#{pkcs12_subject},issuer:#{pkcs12_issuer},CA:#{pkcs12_ca},ADCS_template:#{pkcs12_adcs_template}"
private_str = "subject:#{pkcs12_subject},issuer:#{pkcs12_issuer},ADCS CA:#{pkcs12_ca},ADCS template:#{pkcs12_adcs_template}"
private_str = "#{private_str[0,76]} (TRUNCATED)"
creds.cmd_creds('-t', 'pkcs12')
expect(@output.join("\n")).to match_table <<~TABLE
Expand Down Expand Up @@ -528,10 +528,10 @@
end
end
context 'pkcs12' do
let(:priv) { FactoryBot.create(:metasploit_credential_pkcs12) }
let(:priv) { FactoryBot.build(: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,41 @@
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.build(: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

context 'with metadata other than password' do
let(:adcs_ca) { 'myca' }
let(:adcs_template) { 'mytemplate' }

it 'creates a core if the password is correct' do
expect {
creds.cmd_creds('add', "pkcs12:#{@file.path}", "adcs-ca:#{adcs_ca}", "adcs-template:#{adcs_template}")
}.to change { Metasploit::Credential::Core.count }.by 1
expect(Metasploit::Credential::Pkcs12.first.adcs_ca).to eq(adcs_ca)
expect(Metasploit::Credential::Pkcs12.first.adcs_template).to eq(adcs_template)
end
end
end
end
context 'realm-types' do
Expand Down

0 comments on commit 407494c

Please sign in to comment.