Module: Msf::Ui::Console::CommandDispatcher::Db::Klist

Included in:
Msf::Ui::Console::CommandDispatcher::Db
Defined in:
lib/msf/ui/console/command_dispatcher/db/klist.rb

Constant Summary collapse

@@klist_opts =
Rex::Parser::Arguments.new(
  ['-v', '--verbose'] => [false, 'Verbose output'],
  ['-d', '--delete'] => [ false, 'Delete *all* matching kerberos entries'],
  ['-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']
)

Instance Method Summary collapse

Instance Method Details

#cmd_klist(*args) ⇒ Object

[View source] [View on GitHub]

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/msf/ui/console/command_dispatcher/db/klist.rb', line 33

def cmd_klist(*args)
  return unless active?

  entries_affected = 0
  mode = :list
  host_ranges = []
  id_search = []
  verbose = false
  @@klist_opts.parse(args) do |opt, _idx, val|
    case opt
    when '-h', '--help'
      cmd_klist_help
      return
    when '-v', '--verbose'
      verbose = true
    when '-d', '--delete'
      mode = :delete
    when '-i', '--id'
      id_search = (id_search + val.split(/,\s*|\s+/)).uniq # allows 1 or 1,2,3 or "1 2 3" or "1, 2, 3"
    when '-a', '--activate'
      mode = :activate
    when '-A', '--deactivate'
      mode = :deactivate
    else
      # Anything that wasn't an option is a host to search for
      unless arg_host_range(val, host_ranges)
        return
      end
    end
  end

  # Sentinel value meaning all
  host_ranges.push(nil) if host_ranges.empty?
  id_search = nil if id_search.empty?

  ticket_results = ticket_search(host_ranges, id_search)

  print_line('Kerberos Cache')
  print_line('==============')

  if ticket_results.empty?
    print_line('No tickets')
    print_line
    return
  end

  if mode == :delete
    result = kerberos_ticket_storage.delete_tickets(ids: ticket_results.map(&:id))
    entries_affected = result.size
  end

  if mode == :activate || mode == :deactivate
    result = set_activation_status(mode, ticket_results)
    entries_affected = result.size
    # Update the contents of ticket results to display the updated status values
    # TODO: should be able to use the results returned from updating loot
    # but it returns a base 64'd data field which breaks when bindata tries to parse it as a ccache
    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
      print_line "Cache[#{index}]:"
      print_line ticket_details.indent(2)
      print_line
    end
  else
    tbl = Rex::Text::Table.new(
      {
        'Columns' => ['id', 'host', 'principal', 'sname', 'enctype', 'issued', 'status', 'path'],
        'SortIndex' => -1,
        # For now, don't perform any word wrapping on the table as it breaks the workflow of
        # copying file paths and pasting them into applications
        'WordWrap' => false,
        'Rows' => ticket_results.map do |ticket|
          [
            ticket.id,
            ticket.host_address,
            ticket.principal,
            ticket.sname,
            Rex::Proto::Kerberos::Crypto::Encryption.const_name(ticket.enctype),
            ticket.starttime,
            ticket_status(ticket),
            ticket.path
          ]
        end
      }
    )
    print_line(tbl.to_s)
  end

  case mode
  when :delete
    print_status("Deleted #{entries_affected} #{entries_affected > 1 ? 'entries' : 'entry'}") if entries_affected > 0
  when :activate
    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
  end
end

#cmd_klist_helpObject

[View source] [View on GitHub]

16
17
18
19
20
21
22
# File 'lib/msf/ui/console/command_dispatcher/db/klist.rb', line 16

def cmd_klist_help
  print_line 'List Kerberos tickets in the database'
  print_line 'Usage: klist [options] [hosts]'
  print_line
  print @@klist_opts.usage
  print_line
end

#cmd_klist_tabs(str, words) ⇒ Object

Tab completion for the klist command

at least 1 when tab completion has reached this stage since the command itself has been completed

Parameters:

  • str (String)

    the string currently being typed before tab was hit

  • words (Array<String>)

    the previously completed words on the command line. words is always

[View source] [View on GitHub]

10
11
12
13
14
# File 'lib/msf/ui/console/command_dispatcher/db/klist.rb', line 10

def cmd_klist_tabs(str, words)
  if words.length == 1
    @@klist_opts.option_keys.select { |opt| opt.start_with?(str) }
  end
end

#kerberos_ticket_storageMsf::Exploit::Remote::Kerberos::Ticket::Storage::ReadWrite (protected)

[View source] [View on GitHub]

138
139
140
# File 'lib/msf/ui/console/command_dispatcher/db/klist.rb', line 138

def kerberos_ticket_storage
  @kerberos_ticket_storage ||= Msf::Exploit::Remote::Kerberos::Ticket::Storage::ReadWrite.new(framework: framework)
end