Persist icpr cert as pkcs12 credential
Update creds command to support pkcs12
This commit is contained in:
+20
-20
@@ -98,25 +98,25 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actionpack (7.0.4.2)
|
||||
actionview (= 7.0.4.2)
|
||||
activesupport (= 7.0.4.2)
|
||||
actionpack (7.0.4.3)
|
||||
actionview (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
rack (~> 2.0, >= 2.2.0)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actionview (7.0.4.2)
|
||||
activesupport (= 7.0.4.2)
|
||||
actionview (7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
activemodel (7.0.4.2)
|
||||
activesupport (= 7.0.4.2)
|
||||
activerecord (7.0.4.2)
|
||||
activemodel (= 7.0.4.2)
|
||||
activesupport (= 7.0.4.2)
|
||||
activesupport (7.0.4.2)
|
||||
activemodel (7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activerecord (7.0.4.3)
|
||||
activemodel (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activesupport (7.0.4.3)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
@@ -227,7 +227,7 @@ GEM
|
||||
logging (2.3.1)
|
||||
little-plugger (~> 1.1)
|
||||
multi_json (~> 1.14)
|
||||
loofah (2.19.1)
|
||||
loofah (2.20.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
memory_profiler (1.0.1)
|
||||
@@ -237,7 +237,7 @@ GEM
|
||||
activesupport (~> 7.0)
|
||||
railties (~> 7.0)
|
||||
zeitwerk
|
||||
metasploit-credential (6.0.2)
|
||||
metasploit-credential (6.0.4)
|
||||
metasploit-concern
|
||||
metasploit-model
|
||||
metasploit_data_models (>= 5.0.0)
|
||||
@@ -277,7 +277,7 @@ GEM
|
||||
timeout
|
||||
net-smtp (0.3.3)
|
||||
net-protocol
|
||||
net-ssh (7.0.1)
|
||||
net-ssh (7.1.0)
|
||||
network_interface (0.0.2)
|
||||
nexpose (7.3.0)
|
||||
nio4r (2.5.8)
|
||||
@@ -315,19 +315,19 @@ GEM
|
||||
puma (6.1.1)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.6.2)
|
||||
rack (2.2.6.3)
|
||||
rack (2.2.6.4)
|
||||
rack-protection (3.0.5)
|
||||
rack
|
||||
rack-test (2.0.2)
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.5.0)
|
||||
loofah (~> 2.19, >= 2.19.1)
|
||||
railties (7.0.4.2)
|
||||
actionpack (= 7.0.4.2)
|
||||
activesupport (= 7.0.4.2)
|
||||
railties (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
@@ -337,7 +337,7 @@ GEM
|
||||
rasn1 (0.12.1)
|
||||
strptime (~> 0.2.5)
|
||||
rb-readline (0.5.5)
|
||||
recog (3.0.3)
|
||||
recog (3.1.1)
|
||||
nokogiri
|
||||
redcarpet (3.6.0)
|
||||
regexp_parser (2.7.0)
|
||||
|
||||
+3
-2
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.0].define(version: 2019_05_07_120211) do
|
||||
ActiveRecord::Schema[7.0].define(version: 2022_12_09_005658) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -314,8 +314,9 @@ ActiveRecord::Schema[7.0].define(version: 2019_05_07_120211) do
|
||||
t.datetime "created_at", precision: nil, null: false
|
||||
t.datetime "updated_at", precision: nil, null: false
|
||||
t.string "jtr_format"
|
||||
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))"
|
||||
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)))"
|
||||
end
|
||||
|
||||
create_table "metasploit_credential_publics", id: :serial, force: :cascade do |t|
|
||||
|
||||
@@ -116,14 +116,7 @@ module Exploit::Remote::MsIcpr
|
||||
rescue Rex::Proto::SMB::Exceptions::Error, RubySMB::Error::RubySMBError => e
|
||||
raise MsIcprAuthenticationError, "Unable to authenticate ([#{e.class}] #{e})."
|
||||
end
|
||||
report_service(
|
||||
host: rhost,
|
||||
port: rport,
|
||||
host_name: simple.client.default_name,
|
||||
proto: 'tcp',
|
||||
name: 'smb',
|
||||
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
|
||||
)
|
||||
report_service(icpr_service_data)
|
||||
|
||||
begin
|
||||
simple.client.tree_connect("\\\\#{sock.peerhost}\\IPC$")
|
||||
@@ -222,6 +215,24 @@ module Exploit::Remote::MsIcpr
|
||||
pkcs12 = OpenSSL::PKCS12.create('', '', private_key, response[:certificate])
|
||||
# see: https://pki-tutorial.readthedocs.io/en/latest/mime.html#mime-types
|
||||
info = "#{simple.client.default_domain}\\#{datastore['SMBUser']} Certificate"
|
||||
|
||||
service_data = icpr_service_data
|
||||
credential_data = {
|
||||
**service_data,
|
||||
address: service_data[:host],
|
||||
port: rport,
|
||||
protocol: service_data[:proto],
|
||||
service_name: service_data[:name],
|
||||
workspace_id: myworkspace_id,
|
||||
username: upn || datastore['SMBUser'],
|
||||
private_type: :pkcs12,
|
||||
# pkcs12 is a binary format, but for persisting we Base64 encode it
|
||||
private_data: Base64.strict_encode64(pkcs12.to_der),
|
||||
origin_type: :service,
|
||||
module_fullname: fullname
|
||||
}
|
||||
create_credential(credential_data)
|
||||
|
||||
stored_path = store_loot('windows.ad.cs', 'application/x-pkcs12', rhost, pkcs12.to_der, 'certificate.pfx', info)
|
||||
print_status("Certificate stored at: #{stored_path}")
|
||||
|
||||
@@ -366,5 +377,15 @@ module Exploit::Remote::MsIcpr
|
||||
nil
|
||||
end
|
||||
|
||||
def icpr_service_data
|
||||
{
|
||||
host: rhost,
|
||||
port: rport,
|
||||
host_name: simple.client.default_name,
|
||||
proto: 'tcp',
|
||||
name: 'smb',
|
||||
info: "Module: #{fullname}, last negotiated version: SMBv#{simple.client.negotiated_smb_version} (dialect = #{simple.client.dialect})"
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -104,6 +104,7 @@ class Creds
|
||||
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.',
|
||||
@@ -126,6 +127,8 @@ class Creds
|
||||
print_line " creds add ntlm:E2FC15074BF7751DD408E6B105741864:A1074A69B1BDE45403AB680504BBDD1A"
|
||||
print_line " # Add a Postgres MD5"
|
||||
print_line " creds add user:postgres postgres:md5be86a79bf2043622d58d5453c47d4860"
|
||||
print_line " # Add a user with a PKCS12 file archive"
|
||||
print_line " creds add user:alice pkcs12:/path/to/certificate.pfx"
|
||||
print_line " # Add a user with an SSH key"
|
||||
print_line " creds add user:sshadmin ssh-key:/path/to/id_rsa"
|
||||
print_line " # Add a user and a NonReplayableHash"
|
||||
@@ -203,14 +206,14 @@ class Creds
|
||||
end
|
||||
|
||||
begin
|
||||
params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name', 'jtr', 'postgres')
|
||||
params.assert_valid_keys('user','password','realm','realm-type','ntlm','ssh-key','hash','address','port','protocol', 'service-name', 'jtr', 'pkcs12', 'postgres')
|
||||
rescue ArgumentError => e
|
||||
print_error(e.message)
|
||||
end
|
||||
|
||||
# Verify we only have one type of private
|
||||
if params.slice('password','ntlm','ssh-key','hash', 'postgres').length > 1
|
||||
private_keys = params.slice('password','ntlm','ssh-key','hash', 'postgres').keys
|
||||
if params.slice('password','ntlm','ssh-key','hash', 'pkcs12', 'postgres').length > 1
|
||||
private_keys = params.slice('password','ntlm','ssh-key','hash', 'pkcs12', 'postgres').keys
|
||||
print_error("You can only specify a single Private type. Private types given: #{private_keys.join(', ')}")
|
||||
return
|
||||
end
|
||||
@@ -264,6 +267,17 @@ class Creds
|
||||
data[:private_data] = key_data
|
||||
end
|
||||
|
||||
if params.key? 'pkcs12'
|
||||
begin
|
||||
# pkcs12 is a binary format, but for persisting we Base64 encode it
|
||||
pkcs12_data = Base64.strict_encode64(File.binread(params['pkcs12']))
|
||||
rescue ::Errno::EACCES, ::Errno::ENOENT => e
|
||||
print_error("Failed to add pkcs12 archive: #{e}")
|
||||
end
|
||||
data[:private_type] = :pkcs12
|
||||
data[:private_data] = pkcs12_data
|
||||
end
|
||||
|
||||
if params.key? 'hash'
|
||||
data[:private_type] = :nonreplayable_hash
|
||||
data[:private_data] = params['hash']
|
||||
|
||||
Reference in New Issue
Block a user