Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız [ABONELİK PLANLARI]'na göz atın (https://github.com/sponsors/carlospolop)!
Hacking püf noktalarınızı paylaşarak PR göndererek HackTricks (https://github.com/carlospolop/hacktricks) ve HackTricks Cloud github depolarına katkıda bulunun.
Kum havuzu yükleme süreci
Önceki resimde, com.apple.security.app-sandbox yetkisi olan bir uygulama çalıştırıldığında kum havuzunun nasıl yükleneceği görülebilir.
Derleyici, /usr/lib/libSystem.B.dylib'i ikili dosyaya bağlayacaktır.
Ardından, libSystem.B, xpc_pipe_routine'dan uygulamanın yetkilerini securityd'ye gönderene kadar diğer birçok işlevi çağıracaktır. Securityd, işlemin Kum Havuzu içinde karantinaya alınıp alınmamasını kontrol eder ve eğer öyleyse karantinaya alınır.
Son olarak, kum havuzu, __sandbox_ms'yi çağıracak ve __mac_syscall'ı çağıracaktır.
Olası Atlatmalar
Karantina özniteliğini atlatma
Kum havuzlu işlemler tarafından oluşturulan dosyalara, kum havuzundan kaçınmak için karantina özniteliği eklenir. Ancak, kum havuzlu bir uygulama içinde karantina özniteliği olmayan bir .app klasörü oluşturmayı başarırsanız, uygulama paketi ikilisinin /bin/bash'e işaret etmesini sağlayabilir ve plist içine bazı çevresel değişkenler ekleyerek open'ı kötüye kullanarak yeni uygulamayı kum havuzundan kaçınarak başlatabilirsiniz.
Bu nedenle, şu anda, yalnızca karantina özniteliği olmayan bir isimle biten bir klasör oluşturabilme yeteneğine sahipseniz, macOS yalnızca .app klasöründe ve ana yürütülebilir dosyada karantina özniteliğini kontrol eder (ve ana yürütülebilir dosyayı /bin/bash'e işaret edeceğiz).
Bir .app paketinin zaten çalıştırılmasına izin verildiyse (çalıştırılmasına izin verilen bayrakla karantina xttr'ye sahiptir), bunu da kötüye kullanabilirsiniz... ancak artık .app paketlerine yazamazsınız çünkü bazı ayrıcalıklı TCC izinlerine sahip olmadıkça (yüksek bir kum havuzu içinde olmayacaksınız).
Bir uygulamanın kum havuzunda olması amaçlansa da (com.apple.security.app-sandbox), örneğin bir Başlatma Ajanı'ndan (~/Library/LaunchAgents) çalıştırılıyorsa kum havuzunu atlatmak mümkündür.
Bu yazıda açıklandığı gibi, kum havuzunda olan bir uygulamayla kalıcılık sağlamak istiyorsanız, uygulamanın otomatik olarak Başlatma Ajanı olarak çalıştırılmasını sağlayabilir ve belki de DyLib çevresel değişkenleri aracılığıyla kötü amaçlı kod enjekte edebilirsiniz.
Otomatik Başlatma Konumlarını Kötüye Kullanma
Bir kum havuzlu işlem, daha sonra kum havuzundan kaçınarak çalışacak bir uygulamanın ikilisinin bulunacağı yere yazabiliyorsa, oraya ikilinin yerleştirilmesiyle kaçabilir. Bu tür konumların iyi bir örneği ~/Library/LaunchAgents veya /System/Library/LaunchDaemons'tir.
Bunun için belki de 2 adıma ihtiyacınız olabilir: Daha geniş kum havuzlu bir işlem (file-read*, file-write*) kodunuzu yürütecek ve aslında kum havuzundan kaçınarak çalıştırılacak yere yazacak bir kod.
Otomatik Başlatma konumları hakkında bu sayfaya göz atın:
Kum havuzlu işlemdeyken daha az kısıtlayıcı kum havuzlarında çalışan diğer işlemleri tehlikeye atabilirseniz, onların kum havuzlarından kaçabilirsiniz:
Bu araştırma Kum Havuzunu atlatmanın 2 yolunu keşfetti. Çünkü kum havuzu, libSystem kütüphanesi yüklendiğinde kullanıcı alanından uygulanır. Bir ikili dosya bu kütüphaneyi yüklemeyi başarabilirse, kum havuzuna asla alınmaz:
Eğer ikili dosya tamamen statik olarak derlenmişse, bu kütüphaneyi yüklemeyi atlayabilir.
Eğer ikili dosyanın herhangi bir kütüphaneyi yüklemesi gerekmezse (çünkü bağlayıcı da libSystem'de ise), libSystem'u yüklemesi gerekmez.
Kabuk Kodları
Not edin ki ARM64'te bile kabuk kodlarılibSystem.dylib'e bağlanmak zorundadır:
Belirli bir uygulamanın belirli bir yetkiye sahip olması durumunda, bazı işlemlerinkum havuzu tarafından izin verilse bile gibi olabileceğini unutmayın:
Bu dosya, uygulamanın hangi sistem kaynaklarına erişebileceğini belirten izinlerin listesini içerir. Bu izinler, uygulamanın çalışma zamanında hangi aksiyonları gerçekleştirebileceğini sınırlamak için kullanılır. Bu dosya, macOS kum havuzu mekanizmasının bir parçası olarak kullanılır ve uygulamanın güvenliğini artırmak için önemlidir.
<!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>
Info.plist
Bu dosya, uygulamanın Sandbox ayarlarını tanımlar. Uygulamanın hangi kaynaklara erişebileceğini ve hangi izinlere sahip olabileceğini belirler.
# 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
Uygulama, Sandbox'ın izin vermeyeceği~/Desktop/del.txt dosyasını okumaya çalışacak.
Sandbox atlatıldığında okuyabileceği bir dosya oluşturun:
echo"Sandbox Bypassed">~/Desktop/del.txt
Uygulamayı hata ayıklamak için Sandbox'ın ne zaman yüklendiğini görelim:
# 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)
Sandbox atlatıldığında bile TCC, kullanıcıya işlemin masaüstünden dosya okumasına izin verip vermek istemediğini soracaktır.