Skip to content

Commit

Permalink
Allow setting of the host for a kerberos ticket in the cache, so that…
Browse files Browse the repository at this point in the history
… it'll be automatically used
  • Loading branch information
smashery committed Oct 5, 2023
1 parent 1ee7f03 commit 33d9384
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 3 deletions.
17 changes: 17 additions & 0 deletions lib/msf/core/exploit/remote/kerberos/ticket/storage/write_mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,23 @@ def activate_ccache(ids:)
set_ccache_status(ids: ids, status: 'active')
end

def set_rhost(rhost, ids:)

updated_loots = []
host_obj = report_host(host: rhost)
ids.each do |id|
loot = objects({ id: id })
if loot.blank?
print_warning("Ccache with id: #{id} was not found in loot")
next
end
updated_loots << Array.wrap(framework.db.update_loot({ id: id, host: host_obj })).first
end
updated_loots.map do |stored_loot|
StoredTicket.new(stored_loot)
end
end

private

# @param [Array<Integer>] ids List of ticket IDs to update
Expand Down
28 changes: 26 additions & 2 deletions lib/msf/ui/console/command_dispatcher/db/klist.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def cmd_klist_help
['-h', '--help'] => [false, 'Help banner'],
['-i', '--index'] => [true, 'Kerberos entry ID(s) to search for, e.g. `-i 1` or `-i 1,2,3` or `-i 1 -i 2 -i 3`'],
['-a', '--activate'] => [false, 'Activates *all* matching kerberos entries'],
['-A', '--deactivate'] => [false, 'Deactivates *all* matching kerberos entries']
['-A', '--deactivate'] => [false, 'Deactivates *all* matching kerberos entries'],
['-r', '--set-rhost'] => [true, 'Set the host associated with *all* matching kerberos entries']
)

def cmd_klist(*args)
Expand All @@ -37,6 +38,7 @@ def cmd_klist(*args)
mode = :list
host_ranges = []
id_search = []
new_rhost = nil
verbose = false
@@klist_opts.parse(args) do |opt, _idx, val|
case opt
Expand All @@ -53,6 +55,9 @@ def cmd_klist(*args)
mode = :activate
when '-A', '--deactivate'
mode = :deactivate
when '-r', '--set-rhost'
mode = :rhost
new_rhost = val
else
# Anything that wasn't an option is a host to search for
unless arg_host_range(val, host_ranges)
Expand All @@ -67,7 +72,12 @@ def cmd_klist(*args)

ticket_results = ticket_search(host_ranges, id_search)

print_line('Kerberos Cache')
header_suffix = ''
if [:activate, :deactivate, :delete, :rhost].include?(mode)
header_suffix = ' (affected entries)'
end

print_line("Kerberos Cache#{header_suffix}")
print_line('==============')

if ticket_results.empty?
Expand All @@ -90,6 +100,18 @@ def cmd_klist(*args)
ticket_results = ticket_search(host_ranges, id_search)
end

if mode == :rhost
begin
result = kerberos_ticket_storage.set_rhost(new_rhost, ids: ticket_results.map(&:id))
rescue ::ArgumentError => e # e.g. invalid IP address
print_error(e.message)
return
end
entries_affected = result.size
# Get tickets with updated host values
ticket_results = ticket_search(host_ranges, id_search)
end

if verbose
ticket_results.each.with_index do |ticket_result, index|
ticket_details = Rex::Proto::Kerberos::CredentialCache::Krb5CcachePresenter.new(ticket_result.ccache).present
Expand Down Expand Up @@ -128,6 +150,8 @@ def cmd_klist(*args)
print_status("Activated #{entries_affected} #{entries_affected > 1 ? 'entries' : 'entry'}") if entries_affected > 0
when :deactivate
print_status("Deactivated #{entries_affected} #{entries_affected > 1 ? 'entries' : 'entry'}") if entries_affected > 0
when :rhost
print_status("Modified #{entries_affected} #{entries_affected > 1 ? 'entries' : 'entry'}") if entries_affected > 0
end
end

Expand Down
3 changes: 2 additions & 1 deletion modules/auxiliary/admin/kerberos/forge_ticket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def initialize(info = {})
OptString.new('EXTRA_SIDS', [ false, 'Extra sids separated by commas, Ex: S-1-5-21-1755879683-3641577184-3486455962-519']),
OptString.new('SPN', [ false, 'The Service Principal Name (Only used for silver ticket)'], conditions: %w[ACTION == FORGE_SILVER]),
OptInt.new('DURATION', [ true, 'Duration of the ticket in days', 3650]),
OptAddress.new('RHOST', [false, 'The host that this ticket will be registered to in the Metasploit Kerberos cache']),
]
)

Expand Down Expand Up @@ -101,7 +102,7 @@ def forge_ccache(sname:, flags:, is_golden:)
is_golden: is_golden
)

Msf::Exploit::Remote::Kerberos::Ticket::Storage.store_ccache(ccache, framework_module: self)
Msf::Exploit::Remote::Kerberos::Ticket::Storage.store_ccache(ccache, framework_module: self, host: datastore['RHOST'])

if datastore['VERBOSE']
print_ccache_contents(ccache, key: enc_key)
Expand Down

0 comments on commit 33d9384

Please sign in to comment.