378 lines
14 KiB
Markdown
378 lines
14 KiB
Markdown
# macOS Auto Start Locations
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|
||
|
||
Here are locations on the system that could lead to the **execution** of a binary **without** **user** **interaction**.
|
||
|
||
### Launchd
|
||
|
||
**`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.
|
||
|
||
```xml
|
||
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>Label</key>
|
||
<string>com.apple.someidentifier</string>
|
||
<key>ProgramArguments</key>
|
||
<array>
|
||
<string>/Users/username/malware</string>
|
||
</array>
|
||
<key>RunAtLoad</key><true/> <!--Execute at system startup-->
|
||
<key>StartInterval</key>
|
||
<integer>800</integer> <!--Execute each 800s-->
|
||
<key>KeepAlive</key>
|
||
<dict>
|
||
<key>SuccessfulExit</key></false> <!--Re-execute if exit unsuccessful-->
|
||
<!--If previous is true, then re-execute in successful exit-->
|
||
</dict>
|
||
</dict>
|
||
</plist>
|
||
```
|
||
|
||
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**](https://github.com/HelmutJ/CocoaSampleCode/tree/master/PreLoginAgents) an example).
|
||
|
||
\{% hint style="info" %\} 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` \{% endhint %\}
|
||
|
||
List all the agents and daemons loaded by the current user:
|
||
|
||
```bash
|
||
launchctl list
|
||
```
|
||
|
||
### Cron
|
||
|
||
List the cron jobs of the **current user** with:
|
||
|
||
```bash
|
||
crontab -l
|
||
```
|
||
|
||
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:
|
||
|
||
```bash
|
||
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /etc/periodic/
|
||
```
|
||
|
||
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`.
|
||
|
||
The periodic scripts (**`/etc/periodic`**) are executed because of the **launch daemons** configured in `/System/Library/LaunchDaemons/com.apple.periodic*`. Note that if a script is stored in `/etc/periodic/` as a way to **escalate privilege**s, it will be **executed** as the **owner of the file**.
|
||
|
||
```bash
|
||
ls -l /System/Library/LaunchDaemons/com.apple.periodic*
|
||
-rw-r--r-- 1 root wheel 887 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-daily.plist
|
||
-rw-r--r-- 1 root wheel 895 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-monthly.plist
|
||
-rw-r--r-- 1 root wheel 891 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-weekly.plist
|
||
```
|
||
|
||
### kext
|
||
|
||
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:
|
||
|
||
```bash
|
||
kextstat #List loaded kext
|
||
kextload /path/to/kext.kext #Load a new one based on path
|
||
kextload -b com.apple.driver.ExampleBundle #Load a new one based on path
|
||
kextunload /path/to/kext.kext
|
||
kextunload -b com.apple.driver.ExampleBundle
|
||
```
|
||
|
||
For more information about [**kernel extensions check this section**](macos-security-and-privilege-escalation/mac-os-architecture#i-o-kit-drivers).
|
||
|
||
### **Login Items**
|
||
|
||
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:
|
||
|
||
```bash
|
||
#List all items:
|
||
osascript -e 'tell application "System Events" to get the name of every login item'
|
||
|
||
#Add an item:
|
||
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/path/to/itemname", hidden:false}'
|
||
|
||
#Remove an item:
|
||
osascript -e 'tell application "System Events" to delete login item "itemname"'
|
||
```
|
||
|
||
These items are stored in the file /Users/\<username>/Library/Application Support/com.apple.backgroundtaskmanagementagent
|
||
|
||
### At
|
||
|
||
“At tasks” are used to **schedule tasks at specific times**.\
|
||
These tasks differ from cron in that **they are one time tasks** t**hat get removed after executing**. However, they will **survive a system restart** so they can’t be ruled out as a potential threat.
|
||
|
||
By **default** they are **disabled** but the **root** user can **enable** **them** with:
|
||
|
||
```bash
|
||
sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.atrun.plist
|
||
```
|
||
|
||
This will create a file at 13:37:
|
||
|
||
```bash
|
||
echo hello > /tmp/hello | at 1337
|
||
```
|
||
|
||
If AT tasks aren't enabled the created tasks won't be executed.
|
||
|
||
### Login/Logout Hooks
|
||
|
||
They are deprecated but can be used to execute commands when a user logs in.
|
||
|
||
```bash
|
||
cat > $HOME/hook.sh << EOF
|
||
#!/bin/bash
|
||
echo 'My is: \`id\`' > /tmp/login_id.txt
|
||
EOF
|
||
chmod +x $HOME/hook.sh
|
||
defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh
|
||
```
|
||
|
||
This setting is stored in `/Users/$USER/Library/Preferences/com.apple.loginwindow.plist`
|
||
|
||
```bash
|
||
defaults read /Users/$USER/Library/Preferences/com.apple.loginwindow.plist
|
||
{
|
||
LoginHook = "/Users/username/hook.sh";
|
||
MiniBuddyLaunch = 0;
|
||
TALLogoutReason = "Shut Down";
|
||
TALLogoutSavesState = 0;
|
||
oneTimeSSMigrationComplete = 1;
|
||
}
|
||
```
|
||
|
||
To delete it:
|
||
|
||
```bash
|
||
defaults delete com.apple.loginwindow LoginHook
|
||
```
|
||
|
||
In the previous example we have created and deleted a **LoginHook**, it's also possible to create a **LogoutHook**.
|
||
|
||
The root user one is stored in `/private/var/root/Library/Preferences/com.apple.loginwindow.plist`
|
||
|
||
### Emond
|
||
|
||
Apple introduced a logging mechanism called **emond**. It appears it was never fully developed, and development may have been **abandoned** by Apple for other mechanisms, but it remains **available**.
|
||
|
||
This little-known service may **not be much use to a Mac admin**, but to a threat actor one very good reason would be to use it as a **persistence mechanism that most macOS admins probably wouldn't know** to look for. Detecting malicious use of emond shouldn't be difficult, as the System LaunchDaemon for the service looks for scripts to run in only one place:
|
||
|
||
```bash
|
||
ls -l /private/var/db/emondClients
|
||
```
|
||
|
||
{% hint style="danger" %}
|
||
**As this isn't used much, anything in that folder should be suspicious**
|
||
{% endhint %}
|
||
|
||
### Startup Items
|
||
|
||
\{% hint style="danger" %\} **This is deprecated, so nothing should be found in the following directories.** \{% endhint %\}
|
||
|
||
A **StartupItem** is a **directory** that gets **placed** in one of these two folders. `/Library/StartupItems/` or `/System/Library/StartupItems/`
|
||
|
||
After placing a new directory in one of these two locations, **two more items** need to be placed inside that directory. These two items are a **rc script** **and a plist** that holds a few settings. This plist must be called “**StartupParameters.plist**”.
|
||
|
||
{% tabs %}
|
||
{% tab title="StartupParameters.plist" %}
|
||
```xml
|
||
<?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>Description</key>
|
||
<string>This is a description of this service</string>
|
||
<key>OrderPreference</key>
|
||
<string>None</string> <!--Other req services to execute before this -->
|
||
<key>Provides</key>
|
||
<array>
|
||
<string>superservicename</string> <!--Name of the services provided by this file -->
|
||
</array>
|
||
</dict>
|
||
</plist>
|
||
```
|
||
{% endtab %}
|
||
|
||
{% tab title="superservicename" %}
|
||
```bash
|
||
#!/bin/sh
|
||
. /etc/rc.common
|
||
|
||
StartService(){
|
||
touch /tmp/superservicestarted
|
||
}
|
||
|
||
StopService(){
|
||
rm /tmp/superservicestarted
|
||
}
|
||
|
||
RestartService(){
|
||
echo "Restarting"
|
||
}
|
||
|
||
RunService "$1"
|
||
```
|
||
{% endtab %}
|
||
{% endtabs %}
|
||
|
||
### /etc/rc.common
|
||
|
||
{% hint style="danger" %}
|
||
**This isn't working in modern MacOS versions**
|
||
{% endhint %}
|
||
|
||
It's also possible to place here **commands that will be executed at startup.** Example os regular rc.common script:
|
||
|
||
```bash
|
||
#
|
||
# Common setup for startup scripts.
|
||
#
|
||
# Copyright 1998-2002 Apple Computer, Inc.
|
||
#
|
||
|
||
######################
|
||
# Configure the shell #
|
||
######################
|
||
|
||
#
|
||
# Be strict
|
||
#
|
||
#set -e
|
||
set -u
|
||
|
||
#
|
||
# Set command search path
|
||
#
|
||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/System/Library/CoreServices; export PATH
|
||
|
||
#
|
||
# Set the terminal mode
|
||
#
|
||
#if [ -x /usr/bin/tset ] && [ -f /usr/share/misc/termcap ]; then
|
||
# TERM=$(tset - -Q); export TERM
|
||
#fi
|
||
|
||
###################
|
||
# Useful functions #
|
||
###################
|
||
|
||
#
|
||
# Determine if the network is up by looking for any non-loopback
|
||
# internet network interfaces.
|
||
#
|
||
CheckForNetwork()
|
||
{
|
||
local test
|
||
|
||
if [ -z "${NETWORKUP:=}" ]; then
|
||
test=$(ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/inet/p' | wc -l)
|
||
if [ "${test}" -gt 0 ]; then
|
||
NETWORKUP="-YES-"
|
||
else
|
||
NETWORKUP="-NO-"
|
||
fi
|
||
fi
|
||
}
|
||
|
||
alias ConsoleMessage=echo
|
||
|
||
#
|
||
# Process management
|
||
#
|
||
GetPID ()
|
||
{
|
||
local program="$1"
|
||
local pidfile="${PIDFILE:=/var/run/${program}.pid}"
|
||
local pid=""
|
||
|
||
if [ -f "${pidfile}" ]; then
|
||
pid=$(head -1 "${pidfile}")
|
||
if ! kill -0 "${pid}" 2> /dev/null; then
|
||
echo "Bad pid file $pidfile; deleting."
|
||
pid=""
|
||
rm -f "${pidfile}"
|
||
fi
|
||
fi
|
||
|
||
if [ -n "${pid}" ]; then
|
||
echo "${pid}"
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
#
|
||
# Generic action handler
|
||
#
|
||
RunService ()
|
||
{
|
||
case $1 in
|
||
start ) StartService ;;
|
||
stop ) StopService ;;
|
||
restart) RestartService ;;
|
||
* ) echo "$0: unknown argument: $1";;
|
||
esac
|
||
}
|
||
```
|
||
|
||
### Profiles
|
||
|
||
Configuration profiles can force a user to use certain browser settings, DNS proxy settings, or VPN settings. Many other payloads are possible which make them ripe for abuse.
|
||
|
||
You can enumerate them running:
|
||
|
||
```bash
|
||
ls -Rl /Library/Managed\ Preferences/
|
||
```
|
||
|
||
### Other persistence techniques and tools
|
||
|
||
* [https://github.com/cedowens/Persistent-Swift](https://github.com/cedowens/Persistent-Swift)
|
||
* [https://github.com/D00MFist/PersistentJXA](https://github.com/D00MFist/PersistentJXA)
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
* Do you work in a **cybersecurity company**? Do you want to see your **company advertised in HackTricks**? or do you want to have access to the **latest version of the PEASS or download HackTricks in PDF**? Check the [**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)!
|
||
* Discover [**The PEASS Family**](https://opensea.io/collection/the-peass-family), our collection of exclusive [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
* Get the [**official PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||
* **Join the** [**💬**](https://emojipedia.org/speech-balloon/) [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** me on **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||
* **Share your hacking tricks by submitting PRs to the** [**hacktricks repo**](https://github.com/carlospolop/hacktricks) **and** [**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud).
|
||
|
||
</details>
|