Path: blob/master/modules/post/windows/gather/enum_ad_groups.rb
19592 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Auxiliary::Report7include Msf::Post::Windows::LDAP8# include Msf::Post::Windows::Accounts910USER_FIELDS = [11'name',12'distinguishedname',13'description'14].freeze1516def initialize(info = {})17super(18update_info(19info,20'Name' => 'Windows Gather Active Directory Groups',21'Description' => %q{22This module will enumerate AD groups on the specified domain.23},24'License' => MSF_LICENSE,25'Author' => [26'Stuart Morgan <stuart.morgan[at]mwrinfosecurity.com>'27],28'Platform' => [ 'win' ],29'SessionTypes' => [ 'meterpreter' ],30'Notes' => {31'Stability' => [CRASH_SAFE],32'SideEffects' => [],33'Reliability' => []34}35)36)3738register_options([39OptString.new('ADDITIONAL_FIELDS', [false, 'Additional fields to retrieve, comma separated', nil]),40OptString.new('FILTER', [false, 'Customised LDAP filter', nil])41])42end4344def run45@user_fields = USER_FIELDS.dup4647if datastore['ADDITIONAL_FIELDS']48additional_fields = datastore['ADDITIONAL_FIELDS'].gsub(/\s+/, '').split(',')49@user_fields.push(*additional_fields)50end5152max_search = datastore['MAX_SEARCH']5354begin55f = ''56f = "(#{datastore['FILTER']})" if datastore['FILTER']57q = query("(&(objectClass=group)#{f})", max_search, @user_fields)58rescue ::RuntimeError, ::Rex::Post::Meterpreter::RequestError => e59# Can't bind or in a network w/ limited accounts60print_error(e.message)61return62end6364if q.nil? || q[:results].empty?65print_status('No results returned.')66else67results_table = parse_results(q[:results])68print_line results_table.to_s69end70end7172# Takes the results of LDAP query, parses them into a table73# and records and usernames as {Metasploit::Credential::Core}s in74# the database.75#76# @param results [Array<Array<Hash>>] The LDAP query results to parse77# @return [Rex::Text::Table] The table containing all the result data78def parse_results(results)79# Results table holds raw string data80results_table = Rex::Text::Table.new(81'Header' => 'Domain Groups',82'Indent' => 1,83'SortIndex' => -1,84'Columns' => @user_fields85)8687results.each do |result|88row = []8990result.each do |field|91if field.nil?92row << ''93else94row << field[:value]95end96end9798results_table << row99end100results_table101end102end103104105