Teilen Sie Ihre Hacking-Tricks, indem Sie PRs an dieHackTricks und HackTricks Cloud GitHub-Repositories einreichen.
Sandbox-Ladevorgang
Im vorherigen Bild ist es möglich zu beobachten, wie die Sandbox geladen wird, wenn eine Anwendung mit der Berechtigung com.apple.security.app-sandbox ausgeführt wird.
Der Compiler wird /usr/lib/libSystem.B.dylib mit dem Binärprogramm verknüpfen.
Dann wird libSystem.B andere verschiedene Funktionen aufrufen, bis das xpc_pipe_routine die Berechtigungen der App an securityd sendet. Securityd überprüft, ob der Prozess innerhalb der Sandbox unter Quarantäne gestellt werden sollte, und wenn ja, wird er unter Quarantäne gestellt.
Schließlich wird die Sandbox aktiviert, indem __sandbox_ms aufgerufen wird, der __mac_syscall aufrufen wird.
Mögliche Umgehungen
Umgehung der Quarantäne-Attribute
Von sandboxierten Prozessen erstellte Dateien erhalten das Quarantäne-Attribut, um das Entkommen aus der Sandbox zu verhindern. Wenn es jedoch gelingt, einen .app-Ordner ohne das Quarantäne-Attribut innerhalb einer sandboxierten Anwendung zu erstellen, könnte das App-Bundle-Binärprogramm auf /bin/bash zeigen und einige Umgebungsvariablen in der plist hinzufügen, um open zu missbrauchen und die neue App unsandboxed zu starten.
Daher können Sie derzeit, wenn Sie in der Lage sind, einen Ordner mit einem Namen, der mit .app endet, ohne ein Quarantäne-Attribut zu erstellen, der Sandbox entkommen, da macOS nur das Quarantäne-Attribut im.app-Ordner und im Hauptausführbaren überprüft (und wir werden das Hauptausführbare auf /bin/bash zeigen).
Beachten Sie, dass, wenn ein .app-Bundle bereits autorisiert wurde, ausgeführt zu werden (es hat ein Quarantäne xttr mit der Flagge für die Autorisierung zum Ausführen), könnten Sie es auch missbrauchen... außer dass Sie jetzt nicht in .app-Bundles schreiben können, es sei denn, Sie haben einige privilegierte TCC-Berechtigungen (die Sie nicht in einer Sandbox mit hohen Berechtigungen haben werden).
Auch wenn eine Anwendung dazu gedacht ist, sandboxiert zu sein (com.apple.security.app-sandbox), ist es möglich, die Sandbox zu umgehen, wenn sie z. B. von einem StartAgenten (~/Library/LaunchAgents) ausgeführt wird.
Wie in diesem Beitrag erklärt, könnten Sie, wenn Sie Persistenz mit einer sandboxierten Anwendung erlangen möchten, diese automatisch als StartAgent ausführen lassen und möglicherweise bösartigen Code über DyLib-Umgebungsvariablen einschleusen.
Missbrauch von Autostart-Orten
Wenn ein sandboxierter Prozess an einem Ort schreiben kann, an dem später eine unsandboxierte Anwendung das Binärprogramm ausführen wird, wird er in der Lage sein, einfach durch Platzieren des Binärprogramms dort zu entkommen. Ein gutes Beispiel für solche Orte sind ~/Library/LaunchAgents oder /System/Library/LaunchDaemons.
Dafür benötigen Sie möglicherweise sogar 2 Schritte: Einen Prozess mit einer permissiveren Sandbox (file-read*, file-write*) ausführen lassen, der Ihren Code ausführt, der tatsächlich an einem Ort schreibt, an dem er unsandboxiert ausgeführt wird.
Überprüfen Sie diese Seite zu Autostart-Orten:
Missbrauch anderer Prozesse
Wenn Sie aus dem Sandbox-Prozess heraus in der Lage sind, andere Prozesse zu kompromittieren, die in weniger restriktiven Sandboxes (oder gar keiner) ausgeführt werden, können Sie aus deren Sandboxes entkommen:
Statisches Kompilieren & Dynamisches Verknüpfen
Diese Forschung entdeckte 2 Möglichkeiten, die Sandbox zu umgehen. Da die Sandbox aus dem Benutzerbereich angewendet wird, wenn die libSystem-Bibliothek geladen wird. Wenn ein Binärprogramm das Laden dieser Bibliothek vermeiden könnte, würde es nie in die Sandbox gelangen:
Wenn das Binärprogramm vollständig statisch kompiliert wäre, könnte es das Laden dieser Bibliothek vermeiden.
Wenn das Binärprogramm keine Bibliotheken laden müsste (weil der Linker auch in libSystem ist), müsste es libSystem nicht laden.
Shellcodes
Beachten Sie, dass selbst Shellcodes in ARM64 in libSystem.dylib verknüpft werden müssen:
Beachten Sie, dass selbst wenn einige Aktionen möglicherweise im Sandbox-Modus erlaubt sind, wenn eine Anwendung über eine spezifische Berechtigung verfügt, wie zum Beispiel:
Inhalt: Dieses XML-Dokument definiert die Berechtigungen, die der Sandbox-Prozess haben soll. Es enthält eine Liste von Berechtigungen, die dem Prozess gewährt werden, um auf bestimmte Ressourcen zuzugreifen oder bestimmte Aktionen auszuführen. Diese Berechtigungen können verwendet werden, um die Sandbox zu umgehen oder zu debuggen.
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0">
<dict><key>com.apple.security.app-sandbox</key><true/></dict></plist>
macOS-Sandbox-Debug-und-Bypass
In diesem Abschnitt werden verschiedene Techniken zum Debuggen und Umgehen von macOS-Sandbox-Anwendungen behandelt. Es werden Methoden diskutiert, um die Sandbox-Einschränkungen zu umgehen und potenzielle Schwachstellen auszunutzen. Dies ist nützlich für Sicherheitsforscher und Entwickler, um die Sicherheit von macOS-Anwendungen zu testen und zu verbessern.
# Compile itgcc-Xlinker-sectcreate-Xlinker__TEXT-Xlinker__info_plist-XlinkerInfo.plistsand.c-osand# Create a certificate for "Code Signing"# Apply the entitlements via signingcodesign-s<cert-name>--entitlementsentitlements.xmlsand
Die App wird versuchen, die Datei ~/Desktop/del.txt zu lesen, was die Sandbox nicht erlauben wird.
Erstellen Sie eine Datei dort, da sobald die Sandbox umgangen ist, sie in der Lage sein wird, sie zu lesen:
echo"Sandbox Bypassed">~/Desktop/del.txt
Lassen Sie uns die Anwendung debuggen, um zu sehen, wann die Sandbox geladen wird:
# Load app in debugginglldb./sand# Set breakpoint in xpc_pipe_routine(lldb) b xpc_pipe_routine# run(lldb) r# This breakpoint is reached by different functionalities# Check in the backtrace is it was de sandbox one the one that reached it# We are looking for the one libsecinit from libSystem.B, like the following one:(lldb) bt* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1* frame #0: 0x00000001873d4178 libxpc.dylib`xpc_pipe_routineframe#1: 0x000000019300cf80 libsystem_secinit.dylib`_libsecinit_appsandbox + 584frame#2: 0x00000001874199c4 libsystem_trace.dylib`_os_activity_initiate_impl + 64frame#3: 0x000000019300cce4 libsystem_secinit.dylib`_libsecinit_initializer + 80frame#4: 0x0000000193023694 libSystem.B.dylib`libSystem_initializer + 272# To avoid lldb cutting info(lldb) settings set target.max-string-summary-length 10000# The message is in the 2 arg of the xpc_pipe_routine function, get it with:(lldb) p (char*) xpc_copy_description($x1)(char *) $0 = 0x000000010100a400 "<dictionary: 0x6000026001e0> { count = 5, transaction: 0, voucher = 0x0, contents =\n\t\"SECINITD_REGISTRATION_MESSAGE_SHORT_NAME_KEY\" => <string: 0x600000c00d80> { length = 4, contents = \"sand\" }\n\t\"SECINITD_REGISTRATION_MESSAGE_IMAGE_PATHS_ARRAY_KEY\" => <array: 0x600000c00120> { count = 42, capacity = 64, contents =\n\t\t0: <string: 0x600000c000c0> { length = 14, contents = \"/tmp/lala/sand\" }\n\t\t1: <string: 0x600000c001e0> { length = 22, contents = \"/private/tmp/lala/sand\" }\n\t\t2: <string: 0x600000c000f0> { length = 26, contents = \"/usr/lib/libSystem.B.dylib\" }\n\t\t3: <string: 0x600000c00180> { length = 30, contents = \"/usr/lib/system/libcache.dylib\" }\n\t\t4: <string: 0x600000c00060> { length = 37, contents = \"/usr/lib/system/libcommonCrypto.dylib\" }\n\t\t5: <string: 0x600000c001b0> { length = 36, contents = \"/usr/lib/system/libcompiler_rt.dylib\" }\n\t\t6: <string: 0x600000c00330> { length = 33, contents = \"/usr/lib/system/libcopyfile.dylib\" }\n\t\t7: <string: 0x600000c00210> { length = 35, contents = \"/usr/lib/system/libcorecry"...
# The 3 arg is the address were the XPC response will be stored(lldb) register read x2x2=0x000000016fdfd660# Move until the end of the function(lldb) finish# Read the response## Check the address of the sandbox container in SECINITD_REPLY_MESSAGE_CONTAINER_ROOT_PATH_KEY(lldb) memory read -f p 0x000000016fdfd660 -c 10x16fdfd660:0x0000600003d04000(lldb) p (char*) xpc_copy_description(0x0000600003d04000)(char *) $4 = 0x0000000100204280 "<dictionary: 0x600003d04000> { count = 7, transaction: 0, voucher = 0x0, contents =\n\t\"SECINITD_REPLY_MESSAGE_CONTAINER_ID_KEY\" => <string: 0x600000c04d50> { length = 22, contents = \"xyz.hacktricks.sandbox\" }\n\t\"SECINITD_REPLY_MESSAGE_QTN_PROC_FLAGS_KEY\" => <uint64: 0xaabe660cef067137>: 2\n\t\"SECINITD_REPLY_MESSAGE_CONTAINER_ROOT_PATH_KEY\" => <string: 0x600000c04e10> { length = 65, contents = \"/Users/carlospolop/Library/Containers/xyz.hacktricks.sandbox/Data\" }\n\t\"SECINITD_REPLY_MESSAGE_SANDBOX_PROFILE_DATA_KEY\" => <data: 0x600001704100>: { length = 19027 bytes, contents = 0x0000f000ba0100000000070000001e00350167034d03c203... }\n\t\"SECINITD_REPLY_MESSAGE_VERSION_NUMBER_KEY\" => <int64: 0xaa3e660cef06712f>: 1\n\t\"SECINITD_MESSAGE_TYPE_KEY\" => <uint64: 0xaabe660cef067137>: 2\n\t\"SECINITD_REPLY_FAILURE_CODE\" => <uint64: 0xaabe660cef067127>: 0\n}"
# To bypass the sandbox we need to skip the call to __mac_syscall# Lets put a breakpoint in __mac_syscall when x1 is 0 (this is the code to enable the sandbox)(lldb) breakpoint set --name __mac_syscall --condition '($x1 == 0)'(lldb) c# The 1 arg is the name of the policy, in this case "Sandbox"(lldb) memory read -f s $x00x19300eb22:"Sandbox"## BYPASS## Due to the previous bp, the process will be stopped in:Process2517stopped* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1frame#0: 0x0000000187659900 libsystem_kernel.dylib`__mac_syscalllibsystem_kernel.dylib`:->0x187659900<+0>:movx16,#0x17d0x187659904<+4>:svc#0x800x187659908<+8>:b.lo0x187659928 ; <+40>0x18765990c<+12>:pacibsp# To bypass jump to the b.lo address modifying some registers first(lldb) breakpoint delete 1 # Remove bp(lldb) register write $pc 0x187659928 #b.lo address(lldb) register write $x0 0x00(lldb) register write $x1 0x00(lldb) register write $x16 0x17d(lldb) cProcess2517resumingSandboxBypassed!Process2517exitedwithstatus=0 (0x00000000)
Auch wenn die Sandbox umgangen wird, wird TCC den Benutzer fragen, ob er dem Prozess erlauben möchte, Dateien vom Desktop zu lesen.