macOS Auto Start
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
This section is heavily based on the blog series Beyond the good ol' LaunchAgents, the goal is to add more Autostart Locations (if possible), indicate which techniques are still working nowadays with latest version of macOS (13.4) and to specify the permissions needed.
Here you can find start locations useful for sandbox bypass that allows you to simply execute something by writing it into a file and waiting for a very common action, a determined amount of time or an action you can usually perform from inside a sandbox without needing root permissions.
/Library/LaunchAgents
Trigger: Reboot
Root required
/Library/LaunchDaemons
Trigger: Reboot
Root required
/System/Library/LaunchAgents
Trigger: Reboot
Root required
/System/Library/LaunchDaemons
Trigger: Reboot
Root required
~/Library/LaunchAgents
Trigger: Relog-in
~/Library/LaunchDemons
Trigger: Relog-in
As interesting fact, launchd
has an embedded property list in a the Mach-o section __Text.__config
which contains other well known services launchd must start. Moreover, these services can contain the RequireSuccess
, RequireRun
and RebootOnSuccess
that means that they must be run and complete successfully.
Ofc, It cannot be modified because of code signing.
launchd
is the first process executed by OX S kernel at startup and the last one to finish at shut down. It should always have the PID 1. This process will read and execute the configurations indicated in the ASEP plists in:
/Library/LaunchAgents
: Per-user agents installed by the admin
/Library/LaunchDaemons
: System-wide daemons installed by the admin
/System/Library/LaunchAgents
: Per-user agents provided by Apple.
/System/Library/LaunchDaemons
: System-wide daemons provided by Apple.
When a user logs in the plists located in /Users/$USER/Library/LaunchAgents
and /Users/$USER/Library/LaunchDemons
are started with the logged users permissions.
The main difference between agents and daemons is that agents are loaded when the user logs in and the daemons are loaded at system startup (as there are services like ssh that needs to be executed before any user access the system). Also agents may use GUI while daemons need to run in the background.
There are cases where an agent needs to be executed before the user logins, these are called PreLoginAgents. For example, this is useful to provide assistive technology at login. They can be found also in /Library/LaunchAgents
(see here an example).
New Daemons or Agents config files will be loaded after next reboot or using launchctl load <target.plist>
It's also possible to load .plist files without that extension with launchctl -F <file>
(however those plist files won't be automatically loaded after reboot).
It's also possible to unload with launchctl unload <target.plist>
(the process pointed by it will be terminated),
To ensure that there isn't anything (like an override) preventing an Agent or Daemon from running run: sudo launchctl load -w /System/Library/LaunchDaemos/com.apple.smdb.plist
List all the agents and daemons loaded by the current user:
If a plist is owned by a user, even if it's in a daemon system wide folders, the task will be executed as the user and not as root. This can prevent some privilege escalation attacks.
launchd
is the first user mode process which is started from the kernel. The process start must be successful and it cannot exit or crash. It's even protected against some killing signals.
One of the first things launchd
would do is to start all the daemons like:
Timer daemons based on time to be executed:
atd (com.apple.atrun.plist
): Has a StartInterval
of 30min
crond (com.apple.systemstats.daily.plist
): Has StartCalendarInterval
to start at 00:15
Network daemons like:
org.cups.cups-lpd
: Listens in TCP (SockType: stream
) with SockServiceName: printer
SockServiceName must be either a port or a service from /etc/services
com.apple.xscertd.plist
: Listens on TCP in port 1640
Path daemons that are executed when a specified path changes:
com.apple.postfix.master
: Checking the path /etc/postfix/aliases
IOKit notifications daemons:
com.apple.xartstorageremoted
: "com.apple.iokit.matching" => { "com.apple.device-attach" => { "IOMatchLaunchStream" => 1 ...
Mach port:
com.apple.xscertd-helper.plist
: It's indicating in the MachServices
entry the name com.apple.xscertd.helper
UserEventAgent:
This is different from the previous one. It makes launchd spawn apps in response to specific event. However, in this case, the main binary involved isn't launchd
but /usr/libexec/UserEventAgent
. It loads plugins from the SIP restricted folder /System/Library/UserEventPlugins/ where each plugin indicates its initialiser in the XPCEventModuleInitializer
key or. in the case of older plugins, in the CFPluginFactories
dict under the key FB86416D-6164-2070-726F-70735C216EC0
of its Info.plist
.
Writeup: https://theevilbit.github.io/beyond/beyond_0001/ Writeup (xterm): https://theevilbit.github.io/beyond/beyond_0018/
Useful to bypass sandbox: ✅
TCC Bypass: ✅
But you need to find an app with a TCC bypass that executes a shell that loads these files
~/.zshrc
, ~/.zlogin
, ~/.zshenv.zwc
, ~/.zshenv
, ~/.zprofile
Trigger: Open a terminal with zsh
/etc/zshenv
, /etc/zprofile
, /etc/zshrc
, /etc/zlogin
Trigger: Open a terminal with zsh
Root required
~/.zlogout
Trigger: Exit a terminal with zsh
/etc/zlogout
Trigger: Exit a terminal with zsh
Root required
Potentially more in: man zsh
~/.bashrc
Trigger: Open a terminal with bash
/etc/profile
(didn't work)
~/.profile
(didn't work)
~/.xinitrc
, ~/.xserverrc
, /opt/X11/etc/X11/xinit/xinitrc.d/
Trigger: Expected to trigger with xterm, but it isn't installed and even after installed this error is thrown: xterm: DISPLAY is not set
When initiating a shell environment such as zsh
or bash
, certain startup files are run. macOS currently uses /bin/zsh
as the default shell. This shell is automatically accessed when the Terminal application is launched or when a device is accessed via SSH. While bash
and sh
are also present in macOS, they need to be explicitly invoked to be used.
The man page of zsh, which we can read with man zsh
has a long description of the startup files.
Configuring the indicated exploitation and loging-out and loging-in or even rebooting didn't work for me to execute the app. (The app wasn't being executed, maybe it needs to be running when these actions are performed)
Writeup: https://theevilbit.github.io/beyond/beyond_0021/
~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist
Trigger: Restart reopening applications
All the applications to reopen are inside the plist ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist
So, make the reopen applications launch your own one, you just need to add your app to the list.
The UUID can be found listing that directory or with ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}'
To check the applications that will be reopened you can do:
To add an application to this list you can use:
~/Library/Preferences/com.apple.Terminal.plist
Trigger: Open Terminal
In ~/Library/Preferences
are store the preferences of the user in the Applications. Some of these preferences can hold a configuration to execute other applications/scripts.
For example, the Terminal can execute a command in the Startup:
This config is reflected in the file ~/Library/Preferences/com.apple.Terminal.plist
like this:
So, if the plist of the preferences of the terminal in the system could be overwritten, the the open
functionality can be used to open the terminal and that command will be executed.
You can add this from the cli with:
Anywhere
Trigger: Open Terminal
If you create a .terminal
script and opens, the Terminal application will be automatically invoked to execute the commands indicated in there. If the Terminal app has some special privileges (such as TCC), your command will be run with those special privileges.
Try it with:
You could also use the extensions .command
, .tool
, with regular shell scripts content and they will be also opened by Terminal.
If terminal has Full Disk Access it will be able to complete that action (note that the command executed will be visible in a terminal window).
Writeup: https://theevilbit.github.io/beyond/beyond_0013/ Writeup: https://posts.specterops.io/audio-unit-plug-ins-896d3434a882
/Library/Audio/Plug-Ins/HAL
Root required
Trigger: Restart coreaudiod or the computer
/Library/Audio/Plug-ins/Components
Root required
Trigger: Restart coreaudiod or the computer
~/Library/Audio/Plug-ins/Components
Trigger: Restart coreaudiod or the computer
/System/Library/Components
Root required
Trigger: Restart coreaudiod or the computer
According to the previous writeups it's possible to compile some audio plugins and get them loaded.
Writeup: https://theevilbit.github.io/beyond/beyond_0028/
/System/Library/QuickLook
/Library/QuickLook
~/Library/QuickLook
/Applications/AppNameHere/Contents/Library/QuickLook/
~/Applications/AppNameHere/Contents/Library/QuickLook/
QuickLook plugins can be executed when you trigger the preview of a file (press space bar with the file selected in Finder) and a plugin supporting that file type is installed.
It's possible to compile your own QuickLook plugin, place it in one of the previous locations to load it and then go to a supported file and press space to trigger it.
This didn't work for me, neither with the user LoginHook nor with the root LogoutHook
Writeup: https://theevilbit.github.io/beyond/beyond_0022/
You need to be able to execute something like defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh
Lo
cated in ~/Library/Preferences/com.apple.loginwindow.plist
They are deprecated but can be used to execute commands when a user logs in.
This setting is stored in /Users/$USER/Library/Preferences/com.apple.loginwindow.plist
To delete it:
The root user one is stored in /private/var/root/Library/Preferences/com.apple.loginwindow.plist
Here you can find start locations useful for sandbox bypass that allows you to simply execute something by writing it into a file and expecting not super common conditions like specific programs installed, "uncommon" user actions or environments.
Writeup: https://theevilbit.github.io/beyond/beyond_0004/
Useful to bypass sandbox: ✅
However, you need to be able to execute crontab
binary
Or be root
TCC bypass: 🔴
/usr/lib/cron/tabs/
, /private/var/at/tabs
, /private/var/at/jobs
, /etc/periodic/
Root required for direct write access. No root required if you can execute crontab <file>
Trigger: Depends on the cron job
List the cron jobs of the current user with:
You can also see all the cron jobs of the users in /usr/lib/cron/tabs/
and /var/at/tabs/
(needs root).
In MacOS several folders executing scripts with certain frequency can be found in:
There you can find the regular cron jobs, the at jobs (not very used) and the periodic jobs (mainly used for cleaning temporary files). The daily periodic jobs can be executed for example with: periodic daily
.
To add a user cronjob programatically it's possible to use:
Writeup: https://theevilbit.github.io/beyond/beyond_0002/
~/Library/Application Support/iTerm2/Scripts/AutoLaunch
Trigger: Open iTerm
~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt
Trigger: Open iTerm
~/Library/Preferences/com.googlecode.iterm2.plist
Trigger: Open iTerm
Scripts stored in ~/Library/Application Support/iTerm2/Scripts/AutoLaunch
will be executed. For example:
or:
The script ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt
will also be executed:
The iTerm2 preferences located in ~/Library/Preferences/com.googlecode.iterm2.plist
can indicate a command to execute when the iTerm2 terminal is opened.
This setting can be configured in the iTerm2 settings:
And the command is reflected in the preferences:
You can set the command to execute with:
Highly probable there are other ways to abuse the iTerm2 preferences to execute arbitrary commands.
Writeup: https://theevilbit.github.io/beyond/beyond_0007/
Useful to bypass sandbox: ✅
But xbar must be installed
TCC bypass: ✅
It requests Accessibility permissions
~/Library/Application\ Support/xbar/plugins/
Trigger: Once xbar is executed
If the popular program xbar is installed, it's possible to write a shell script in ~/Library/Application\ Support/xbar/plugins/
which will be executed when xbar is started:
Writeup: https://theevilbit.github.io/beyond/beyond_0008/
Useful to bypass sandbox: ✅
But Hammerspoon must be installed
TCC bypass: ✅
It requests Accessibility permissions
~/.hammerspoon/init.lua
Trigger: Once hammerspoon is executed
Hammerspoon serves as an automation platform for macOS, leveraging the LUA scripting language for its operations. Notably, it supports the integration of complete AppleScript code and the execution of shell scripts, enhancing its scripting capabilities significantly.
The app looks for a single file, ~/.hammerspoon/init.lua
, and when started the script will be executed.
Useful to bypass sandbox: ✅
But BetterTouchTool must be installed
TCC bypass: ✅
It requests Automation-Shortcuts and Accessibility permissions
~/Library/Application Support/BetterTouchTool/*
This tool allows to indicate applications or scripts to execute when some shortcuts are pressed . An attacker might be able configure his own shortcut and action to execute in the database to make it execute arbitrary code (a shortcut could be to just to press a key).
Useful to bypass sandbox: ✅
But Alfred must be installed
TCC bypass: ✅
It requests Automation, Accessibility and even Full-Disk access permissions
???
It allows to create workflows that can execute code when certain conditions are met. Potentially it's possible for an attacker to create a workflow file and make Alfred load it (it's needed to pay the premium version to use workflows).
Writeup: https://theevilbit.github.io/beyond/beyond_0006/
Useful to bypass sandbox: ✅
But ssh needs to be enabled and used
TCC bypass: ✅
SSH use to have FDA access
~/.ssh/rc
Trigger: Login via ssh
/etc/ssh/sshrc
Root required
Trigger: Login via ssh
To turn ssh on requres Full Disk Access:
By default, unless PermitUserRC no
in /etc/ssh/sshd_config
, when a user logins via SSH the scripts /etc/ssh/sshrc
and ~/.ssh/rc
will be executed.
Writeup: https://theevilbit.github.io/beyond/beyond_0003/
~/Library/Application Support/com.apple.backgroundtaskmanagementagent
Trigger: Login
Exploit payload stored calling osascript
/var/db/com.apple.xpc.launchd/loginitems.501.plist
Trigger: Login
Root required
In System Preferences -> Users & Groups -> Login Items you can find items to be executed when the user logs in. It it's possible to list them, add and remove from the command line:
These items are stored in the file ~/Library/Application Support/com.apple.backgroundtaskmanagementagent
Login items can also be indicated in using the API SMLoginItemSetEnabled which will store the configuration in /var/db/com.apple.xpc.launchd/loginitems.501.plist
(Check previous section about Login Items, this is an extension)
If you store a ZIP file as a Login Item the Archive Utility
will open it and if the zip was for example stored in ~/Library
and contained the Folder LaunchAgents/file.plist
with a backdoor, that folder will be created (it isn't by default) and the plist will be added so the next time the user logs in again, the backdoor indicated in the plist will be executed.
Another options would be to create the files .bash_profile
and .zshenv
inside the user HOME so if the folder LaunchAgents already exist this technique would still work.
Writeup: https://theevilbit.github.io/beyond/beyond_0014/
Need to execute at
and it must be enabled
at
tasks are designed for scheduling one-time tasks to be executed at certain times. Unlike cron jobs, at
tasks are automatically removed post-execution. It's crucial to note that these tasks are persistent across system reboots, marking them as potential security concerns under certain conditions.
By default they are disabled but the root user can enable them with:
This will create a file in 1 hour:
Check the job queue using atq:
Above we can see two jobs scheduled. We can print the details of the job using at -c JOBNUMBER
If AT tasks aren't enabled the created tasks won't be executed.
The job files can be found at /private/var/at/jobs/
The filename contains the queue, the job number, and the time it’s scheduled to run. For example let’s take a loot at a0001a019bdcd2
.
a
- this is the queue
0001a
- job number in hex, 0x1a = 26
019bdcd2
- time in hex. It represents the minutes passed since epoch. 0x019bdcd2
is 26991826
in decimal. If we multiply it by 60 we get 1619509560
, which is GMT: 2021. April 27., Tuesday 7:46:00
.
If we print the job file, we find that it contains the same information we got using at -c
.
Writeup: https://theevilbit.github.io/beyond/beyond_0024/ Writeup: https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d
Useful to bypass sandbox: ✅
But you need to be able to call osascript
with arguments to contact System Events
to be able to configure Folder Actions
TCC bypass: 🟠
It has some basic TCC permissions like Desktop, Documents and Downloads
/Library/Scripts/Folder Action Scripts
Root required
Trigger: Access to the specified folder
~/Library/Scripts/Folder Action Scripts
Trigger: Access to the specified folder
Folder Actions are scripts automatically triggered by changes in a folder such as adding, removing items, or other actions like opening or resizing the folder window. These actions can be utilized for various tasks, and can be triggered in different ways like using the Finder UI or terminal commands.
To set up Folder Actions, you have options like:
Crafting a Folder Action workflow with Automator and installing it as a service.
Attaching a script manually via the Folder Actions Setup in the context menu of a folder.
Utilizing OSAScript to send Apple Event messages to the System Events.app
for programmatically setting up a Folder Action.
This method is particularly useful for embedding the action into the system, offering a level of persistence.
The following script is an example of what can be executed by a Folder Action:
To make the above script usable by Folder Actions, compile it using:
After the script is compiled, set up Folder Actions by executing the script below. This script will enable Folder Actions globally and specifically attach the previously compiled script to the Desktop folder.
Run the setup script with:
This is the way yo implement this persistence via GUI:
This is the script that will be executed:
Compile it with: osacompile -l JavaScript -o folder.scpt source.js
Move it to:
Then, open the Folder Actions Setup
app, select the folder you would like to watch and select in your case folder.scpt
(in my case I called it output2.scp):
Now, if you open that folder with Finder, your script will be executed.
This configuration was stored in the plist located in ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist
in base64 format.
Now, lets try to prepare this persistence without GUI access:
Copy ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist
to /tmp
to backup it:
cp ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist /tmp
Remove the Folder Actions you just set:
Now that we have an empty environment
Copy the backup file: cp /tmp/com.apple.FolderActionsDispatcher.plist ~/Library/Preferences/
Open the Folder Actions Setup.app to consume this config: open "/System/Library/CoreServices/Applications/Folder Actions Setup.app/"
And this didn't work for me, but those are the instructions from the writeup:(
Writeup: https://theevilbit.github.io/beyond/beyond_0027/
Useful to bypass sandbox: ✅
But you need to have installed a malicious application inside the system
TCC bypass: 🔴
~/Library/Preferences/com.apple.dock.plist
Trigger: When the user clicks on the app inside the dock
All the applications that appear in the Dock are specified inside the plist: ~/Library/Preferences/com.apple.dock.plist
It's possible to add an application just with:
Using some social engineering you could impersonate for example Google Chrome inside the dock and actually execute your own script:
Writeup: https://theevilbit.github.io/beyond/beyond_0017
Useful to bypass sandbox: 🟠
A very specific action needs to happen
You will end in another sandbox
TCC bypass: 🔴
/Library/ColorPickers
Root required
Trigger: Use the color picker
~/Library/ColorPickers
Trigger: Use the color picker
Compile a color picker bundle with your code (you could use this one for example) and add a constructor (like in the Screen Saver section) and copy the bundle to ~/Library/ColorPickers
.
Then, when the color picker is triggered your should should be aswell.
Note that the binary loading your library has a very restrictive sandbox: /System/Library/Frameworks/AppKit.framework/Versions/C/XPCServices/LegacyExternalColorPickerService-x86_64.xpc/Contents/MacOS/LegacyExternalColorPickerService-x86_64
Writeup: https://theevilbit.github.io/beyond/beyond_0026/ Writeup: https://objective-see.org/blog/blog_0x11.html
Useful to bypass sandbox: No, because you need to execute your own app
TCC bypass: ???
A specific app
An application example with a Finder Sync Extension can be found here.
Applications can have Finder Sync Extensions
. This extension will go inside an application that will be executed. Moreover, for the extension to be able to execute its code it must be signed with some valid Apple developer certificate, it must be sandboxed (although relaxed exceptions could be added) and it must be registered with something like:
Writeup: https://theevilbit.github.io/beyond/beyond_0016/ Writeup: https://posts.specterops.io/saving-your-access-d562bf5bf90b
/System/Library/Screen Savers
Root required
Trigger: Select the screen saver
/Library/Screen Savers
Root required
Trigger: Select the screen saver
~/Library/Screen Savers
Trigger: Select the screen saver
Create a new project in Xcode and select the template to generate a new Screen Saver. Then, are your code to it, for example the following code to generate logs.
Build it, and copy the .saver
bundle to ~/Library/Screen Savers
. Then, open the Screen Saver GUI and it you just click on it, it should generate a lot of logs:
Note that because inside the entitlements of the binary that loads this code (/System/Library/Frameworks/ScreenSaver.framework/PlugIns/legacyScreenSaver.appex/Contents/MacOS/legacyScreenSaver
) you can find com.apple.security.app-sandbox
you will be inside the common application sandbox.
Saver code:
writeup: https://theevilbit.github.io/beyond/beyond_0011/
Useful to bypass sandbox: 🟠
But you will end in an application sandbox
TCC bypass: 🔴
The sandbox looks very limited
~/Library/Spotlight/
Trigger: A new file with a extension managed by the spotlight plugin is created.
/Library/Spotlight/
Trigger: A new file with a extension managed by the spotlight plugin is created.
Root required
/System/Library/Spotlight/
Trigger: A new file with a extension managed by the spotlight plugin is created.
Root required
Some.app/Contents/Library/Spotlight/
Trigger: A new file with a extension managed by the spotlight plugin is created.
New app required
Spotlight is macOS's built-in search feature, designed to provide users with quick and comprehensive access to data on their computers. To facilitate this rapid search capability, Spotlight maintains a proprietary database and creates an index by parsing most files, enabling swift searches through both file names and their content.
The underlying mechanism of Spotlight involves a central process named 'mds', which stands for 'metadata server'. This process orchestrates the entire Spotlight service. Complementing this, there are multiple 'mdworker' daemons that perform a variety of maintenance tasks, such as indexing different file types (ps -ef | grep mdworker
). These tasks are made possible through Spotlight importer plugins, or ".mdimporter bundles", which enable Spotlight to understand and index content across a diverse range of file formats.
The plugins or .mdimporter
bundles are located in the places mentioned previously and if a new bundle appear it's loaded within monute (no need to restart any service). These bundles need to indicate which file type and extensions they can manage, this way, Spotlight will use them when a new file with the indicated extension is created.
It's possible to find all the mdimporters
loaded running:
And for example /Library/Spotlight/iBooksAuthor.mdimporter is used to parse these type of files (extensions .iba
and .book
among others):
If you check the Plist of other mdimporter
you might not find the entry UTTypeConformsTo
. Thats because that is a built-in Uniform Type Identifiers (UTI) and it doesn't need to specify extensions.
Moreover, System default plugins always take precedence, so an attacker can only access files that are not otherwise indexed by Apple's own mdimporters
.
To create your own importer you could start with this project: https://github.com/megrimm/pd-spotlight-importer and then change the name, the CFBundleDocumentTypes
and add UTImportedTypeDeclarations
so it supports the extension you would like to support and refelc them in schema.xml
.
Then change the code of the function GetMetadataForFile
to execute your payload when a file with the processed extension is created.
Finally build and copy your new .mdimporter
to one of thre previous locations and you can chech whenever it's loaded monitoring the logs or checking mdimport -L.
It doesn't look like this is working anymore.
Writeup: https://theevilbit.github.io/beyond/beyond_0009/
/System/Library/PreferencePanes
/Library/PreferencePanes
~/Library/PreferencePanes
It doesn't look like this is working anymore.
Here you can find start locations useful for sandbox bypass that allows you to simply execute something by writing it into a file being root and/or requiring other weird conditions.
Writeup: https://theevilbit.github.io/beyond/beyond_0019/
/etc/periodic/daily
, /etc/periodic/weekly
, /etc/periodic/monthly
, /usr/local/etc/periodic
Root required
Trigger: When the time comes
/etc/daily.local
, /etc/weekly.local
or /etc/monthly.local
Root required
Trigger: When the time comes
The periodic scripts (/etc/periodic
) are executed because of the launch daemons configured in /System/Library/LaunchDaemons/com.apple.periodic*
. Note that scripts stored in /etc/periodic/
are executed as the owner of the file, so this won't work for a potential privilege escalation.
There are other periodic scripts that will be executed indicated in /etc/defaults/periodic.conf
:
If you manage to write any of the files /etc/daily.local
, /etc/weekly.local
or /etc/monthly.local
it will be executed sooner or later.
Note that the periodic script will be executed as the owner of the script. So if a regular user owns the script, it will be executed as that user (this might prevent privilege escalation attacks).
Writeup: Linux Hacktricks PAM Writeup: https://theevilbit.github.io/beyond/beyond_0005/
Root always required
As PAM is more focused in persistence and malware that on easy execution inside macOS, this blog won't give a detailed explanation, read the writeups to understand this technique better.
Check PAM modules with:
A persistence/privilege escalation technique abusing PAM is as easy as modifying the module /etc/pam.d/sudo adding at the beginning the line:
So it will looks like something like this:
And therefore any attempt to use sudo
will work.
Note that this directory is protected by TCC so it's highly probably that the user will get a prompt asking for access.
Another nice example is su, were you can see that it's also possible to give parameters to the PAM modules (and you coukd also backdoor this file):
Writeup: https://theevilbit.github.io/beyond/beyond_0028/ Writeup: https://posts.specterops.io/persistent-credential-theft-with-authorization-plugins-d17b34719d65
Useful to bypass sandbox: 🟠
But you need to be root and make extra configs
TCC bypass: ???
/Library/Security/SecurityAgentPlugins/
Root required
It's also needed to configure the authorization database to use the plugin
You can create an authorization plugin that will be executed when a user logs-in to maintain persistence. For more information about how to create one of these plugins check the previous writeups (and be careful, a poorly written one can lock you out and you will need to clean your mac from recovery mode).
Move the bundle to the location to be loaded:
Finally add the rule to load this Plugin:
The evaluate-mechanisms
will tell the authorization framework that it will need to call an external mechanism for authorization. Moreover, privileged
will make it be executed by root.
Trigger it with:
And then the staff group should have sudo access (read /etc/sudoers
to confirm).
Writeup: https://theevilbit.github.io/beyond/beyond_0030/
/private/etc/man.conf
Root required
/private/etc/man.conf
: Whenever man is used
The config file /private/etc/man.conf
indicate the binary/script to use when opening man documentation files. So the path to the executable could be modified so anytime the user uses man to read some docs a backdoor is executed.
For example set in /private/etc/man.conf
:
And then create /tmp/view
as:
Writeup: https://theevilbit.github.io/beyond/beyond_0023/
Useful to bypass sandbox: 🟠
But you need to be root and apache needs to be running
TCC bypass: 🔴
Httpd doesn't have entitlements
/etc/apache2/httpd.conf
Root required
Trigger: When Apache2 is started
You can indicate in /etc/apache2/httpd.conf
to load a module adding a line such as:
This way your compiled moduled will be loaded by Apache. The only thing is that either you need to sign it with a valid Apple certificate, or you need to add a new trusted certificate in the system and sign it with it.
Then, if needed , to make sure the server will be started you could execute:
Code example for the Dylb:
Writeup: https://theevilbit.github.io/beyond/beyond_0031/
Useful to bypass sandbox: 🟠
But you need to be root, auditd be running and cause a warning
TCC bypass: 🔴
/etc/security/audit_warn
Root required
Trigger: When auditd detects a warning
Whenever auditd detects a warning the script /etc/security/audit_warn
is executed. So you could add your payload on it.
You could force a warning with sudo audit -n
.
This is deprecated, so nothing should be found in those directories.
The StartupItem is a directory that should be positioned within either /Library/StartupItems/
or /System/Library/StartupItems/
. Once this directory is established, it must encompass two specific files:
An rc script: A shell script executed at startup.
A plist file, specifically named StartupParameters.plist
, which contains various configuration settings.
Ensure that both the rc script and the StartupParameters.plist
file are correctly placed inside the StartupItem directory for the startup process to recognize and utilize them.
I cannot find this component in my macOS so for more info check the writeup
Writeup: https://theevilbit.github.io/beyond/beyond_0023/
Introduced by Apple, emond is a logging mechanism that seems to be underdeveloped or possibly abandoned, yet it remains accessible. While not particularly beneficial for a Mac administrator, this obscure service could serve as a subtle persistence method for threat actors, likely unnoticed by most macOS admins.
For those aware of its existence, identifying any malicious usage of emond is straightforward. The system's LaunchDaemon for this service seeks scripts to execute in a single directory. To inspect this, the following command can be used:
Writeup: https://theevilbit.github.io/beyond/beyond_0018/
/opt/X11/etc/X11/xinit/privileged_startx.d
Root required
Trigger: With XQuartz
XQuartz is no longer installed in macOS, so if you want more info check the writeup.
It's so complicated to install kext even as root taht I won't consider this to escape from sandboxes or even for persistence (unless you have an exploit)
In order to install a KEXT as a startup item, it needs to be installed in one of the following locations:
/System/Library/Extensions
KEXT files built into the OS X operating system.
/Library/Extensions
KEXT files installed by 3rd party software
You can list currently loaded kext files with:
For more information about kernel extensions check this section.
Writeup: https://theevilbit.github.io/beyond/beyond_0029/
/usr/local/bin/amstoold
Root required
Apparently the plist
from /System/Library/LaunchAgents/com.apple.amstoold.plist
was using this binary while exposing a XPC service... the thing is that the binary didn't exist, so you could place something there and when the XPC service gets called your binary will be called.
I can no longer find this in my macOS.
Writeup: https://theevilbit.github.io/beyond/beyond_0015/
/Library/Preferences/Xsan/.xsanrc
Root required
Trigger: When the service is run (rarely)
Apparently it's not very common to run this script and I couldn't even find it in my macOS, so if you want more info check the writeup.
This isn't working in modern MacOS versions
It's also possible to place here commands that will be executed at startup. Example os regular rc.common script:
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)