Skip to content

Commit 2734dae

Browse files
authored
Merge pull request #20459 from adfoster-r7/consolidate-pkcs12-cert-file-reads
Consolidate pkcs12 cert file reads
2 parents d25fd08 + ced20bf commit 2734dae

File tree

5 files changed

+26
-20
lines changed

5 files changed

+26
-20
lines changed

lib/metasploit/framework/ldap/client.rb

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,11 @@ def ldap_auth_opts_plaintext(opts)
111111

112112
def ldap_auth_opts_schannel(opts, ssl)
113113
auth_opts = {}
114-
pfx_path = opts[:ldap_cert_file]
115114
raise Msf::ValidationError, 'The SSL option must be enabled when using Schannel authentication.' unless ssl
116115
raise Msf::ValidationError, 'Can not sign and seal when using Schannel authentication.' if opts.fetch(:sign_and_seal, false)
117116

118-
if pfx_path.present?
119-
unless ::File.file?(pfx_path) && ::File.readable?(pfx_path)
120-
raise Msf::ValidationError, 'Failed to load the PFX certificate file. The path was not a readable file.'
121-
end
122-
123-
begin
124-
pkcs = OpenSSL::PKCS12.new(File.binread(pfx_path), '')
125-
rescue StandardError => e
126-
raise Msf::ValidationError, "Failed to load the PFX file (#{e})"
127-
end
117+
if opts[:ldap_pkcs12].present?
118+
pkcs = opts[:ldap_pkcs12][:value]
128119
else
129120
pkcs12_storage = Msf::Exploit::Remote::Pkcs12::Storage.new(
130121
framework: opts[:framework],

lib/msf/core/exploit/remote/ldap.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,15 @@ def peer
7575
# @return [Hash] The options to use when connecting to the target
7676
# LDAP server.
7777
def get_connect_opts
78+
pkcs12_storage = Msf::Exploit::Remote::Pkcs12::Storage.new(framework: framework, framework_module: self)
7879
opts = {
7980
username: datastore['LDAPUsername'],
8081
password: datastore['LDAPPassword'],
8182
domain: datastore['LDAPDomain'],
8283
base: datastore['BASE_DN'],
8384
domain_controller_rhost: datastore['DomainControllerRhost'],
8485
ldap_auth: datastore['LDAP::Auth'],
85-
ldap_cert_file: datastore['LDAP::CertFile'],
86+
ldap_pkcs12: datastore['LDAP::CertFile'] ? pkcs12_storage.read_pkcs12_cert_path(datastore['LDAP::CertFile']) : nil,
8687
ldap_rhostname: datastore['LDAP::Rhostname'],
8788
ldap_krb_offered_enc_types: datastore['LDAP::KrbOfferedEncryptionTypes'],
8889
ldap_krb5_cname: datastore['LDAP::Krb5Ccname'],

lib/msf/core/exploit/remote/pkcs12/storage.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,23 @@ def initialize(framework: nil, framework_module: nil)
1616
@framework_module = framework_module
1717
end
1818

19+
# @param [String] cert_path A path to the file system where a pkcs12 cert is located, or a reference to a core database i.e., "id:123"
20+
# @param [String] cert_pass The certificate password
21+
# @param [String] workspace The workspace to restrict searches to
22+
def read_pkcs12_cert_path(cert_path, cert_pass = '', workspace: nil)
23+
is_readable = ::File.file?(cert_path) && ::File.readable?(cert_path)
24+
raise Msf::ValidationError, 'Failed to load the PFX certificate file. The path was not a readable file.' unless is_readable
25+
data = File.binread(cert_path)
26+
27+
begin
28+
pkcs12 = OpenSSL::PKCS12.new(data, cert_pass)
29+
rescue StandardError => e
30+
raise Msf::ValidationError, "Failed to load the PFX file (#{e})"
31+
end
32+
33+
{ path: cert_path, value: pkcs12 }
34+
end
35+
1936
# Get stored pkcs12 matching the options query.
2037
#
2138
# @param [Hash] options The options for matching pkcs12's.

modules/auxiliary/admin/kerberos/get_ticket.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,8 @@ def initialize(info = {})
9191

9292
def validate_options
9393
if datastore['CERT_FILE'].present?
94-
certificate = File.binread(datastore['CERT_FILE'])
95-
begin
96-
@pfx = OpenSSL::PKCS12.new(certificate, datastore['CERT_PASSWORD'] || '')
97-
rescue OpenSSL::PKCS12::PKCS12Error => e
98-
fail_with(Failure::BadConfig, "Unable to parse certificate file (#{e})")
99-
end
94+
pkcs12_storage = Msf::Exploit::Remote::Pkcs12::Storage.new(framework: framework, framework_module: self)
95+
@pfx = pkcs12_storage.read_pkcs12_cert_path(datastore['CERT_FILE'], datastore['CERT_PASSWORD'], workspace: workspace)[:value]
10096

10197
if datastore['USERNAME'].blank? && datastore['DOMAIN'].present?
10298
fail_with(Failure::BadConfig, 'Domain override provided but no username override provided (must provide both or neither)')

modules/auxiliary/scanner/ldap/ldap_login.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,15 @@ def run_host(ip)
111111
ignore_private: ignore_private
112112
)
113113

114+
pkcs12_storage = Msf::Exploit::Remote::Pkcs12::Storage.new(framework: framework, framework_module: self)
114115
opts = {
115116
domain: datastore['LDAPDomain'],
116117
append_domain: datastore['APPEND_DOMAIN'],
117118
ssl: datastore['SSL'],
118119
proxies: datastore['PROXIES'],
119120
domain_controller_rhost: datastore['DomainControllerRhost'],
120121
ldap_auth: datastore['LDAP::Auth'],
121-
ldap_cert_file: datastore['LDAP::CertFile'],
122+
ldap_pkcs12: datastore['LDAP::CertFile'] ? pkcs12_storage.read_pkcs12_cert_path(datastore['LDAP::CertFile']) : nil,
122123
ldap_rhostname: datastore['Ldap::Rhostname'],
123124
ldap_krb_offered_enc_types: datastore['Ldap::KrbOfferedEncryptionTypes'],
124125
ldap_krb5_cname: datastore['Ldap::Krb5Ccname']
@@ -167,7 +168,7 @@ def run_host(ip)
167168
successful_logins << result
168169
if opts[:ldap_auth] == Msf::Exploit::Remote::AuthOption::SCHANNEL
169170
# Schannel auth has no meaningful credential information to store in the DB
170-
msg = opts[:ldap_cert_file].nil? ? 'Using stored certificate' : "Cert File #{opts[:ldap_cert_file]}"
171+
msg = opts[:ldap_pkcs12].nil? ? 'Using stored certificate' : "Cert File #{opts[:ldap_pkcs12][:path]} (#{opts[:ldap_pkcs12][:value].certificate.subject})"
171172
print_brute level: :good, ip: ip, msg: "Success: '#{msg}'"
172173
else
173174
create_credential_and_login(credential_data) if result.credential.private

0 commit comments

Comments
 (0)