Linux : journaux et persistance
Où Linux enregistre les connexions et les commandes, comment lire les traces SSH, et les endroits où un attaquant s'installe pour durer.
Elouan
Série Systèmes Windows et Linux · article 6 sur 6
Un serveur Linux exposé sur Internet reçoit des tentatives de connexion SSH en permanence, parfois des milliers par jour. La plupart échouent. L’enjeu est de repérer celle qui réussit, puis de comprendre ce qui s’est passé ensuite. Pour ça, il faut savoir où Linux range ses journaux, et quels endroits un attaquant utilise pour s’installer durablement.
Où sont les journaux
Historiquement, Linux écrit ses journaux en texte dans /var/log, via le service syslog (rsyslog sur la plupart des distributions). Le nom des fichiers change selon la famille de distribution :
| Contenu | Debian / Ubuntu | Red Hat / Rocky / Alma |
|---|---|---|
| Authentifications, SSH, sudo | /var/log/auth.log | /var/log/secure |
| Messages généraux du système | /var/log/syslog | /var/log/messages |
| Connexions réussies (binaire) | /var/log/wtmp | /var/log/wtmp |
| Connexions échouées (binaire) | /var/log/btmp | /var/log/btmp |
| Dernière connexion par compte | /var/log/lastlog | /var/log/lastlog |
| Serveurs web | /var/log/apache2/, /var/log/nginx/ | /var/log/httpd/, /var/log/nginx/ |
Sur les systèmes avec systemd, le journal de systemd (journald) centralise aussi tous ces messages, dans un format binaire qu’on lit avec journalctl. Sur certaines distributions récentes, il n’y a même plus de fichiers texte par défaut.
journalctl -u ssh --since "2026-10-05 08:00" --until "2026-10-05 12:00"
journalctl _COMM=sudo # toutes les utilisations de sudo
last -F # connexions réussies, avec dates complètes
lastb | head # derniers échecs (en root)
Lire les traces SSH
Dans auth.log, les lignes importantes ressemblent à ça :
Failed password for invalid user admin from 203.0.113.50 port 51122 ssh2
Failed password for root from 203.0.113.50 port 51188 ssh2
Accepted password for deploy from 203.0.113.50 port 51240 ssh2
Accepted publickey for alice from 198.51.100.7 port 40022 ssh2: ED25519 SHA256:…
sudo: deploy : TTY=pts/0 ; PWD=/home/deploy ; USER=root ; COMMAND=/bin/bash
| Message | Signification |
|---|---|
Failed password for invalid user X | Le compte n’existe pas : un robot qui teste une liste de noms |
Failed password for X | Mauvais mot de passe sur un compte existant |
Accepted password / Accepted publickey | Connexion réussie, par mot de passe ou par clé |
sudo: … COMMAND= | Une commande lancée avec sudo, avec l’utilisateur et le dossier |
Le scénario classique
Des centaines de Failed password depuis 203.0.113.50, puis un Accepted password for deploy depuis la même adresse, puis un sudo … COMMAND=/bin/bash. Le mot de passe du compte deploy a été deviné, et l’attaquant a obtenu un shell root. La suite de l’enquête : ce qui a été lancé ensuite, et ce qui a été laissé pour revenir.
L’historique du shell, une source peu fiable
Le fichier ~/.bash_history contient les commandes tapées… parfois. Il n’est écrit qu’à la fermeture du shell, et il se neutralise très facilement :
unset HISTFILE # plus d'historique pour cette session
export HISTSIZE=0
history -c # efface l'historique en mémoire
ln -sf /dev/null ~/.bash_history
Ces manipulations sont elles-mêmes une technique répertoriée (T1070.003). Un historique vide, tronqué ou lié à /dev/null est donc un indice, pas une preuve d’innocence.
auditd, la vraie trace des commandes
auditd est le système d’audit du noyau. Avec des règles adaptées, il enregistre chaque exécution de programme (appel système execve), avec l’utilisateur réel (même après un sudo), le dossier et les arguments. On interroge ses journaux avec ausearch et aureport. C’est beaucoup plus fiable que l’historique, mais il faut l’avoir configuré avant l’incident.
Les mécanismes de persistance
Comme sous Windows, un attaquant veut pouvoir revenir. Les emplacements les plus courants sous Linux :
| Mécanisme | Où regarder | Technique ATT&CK |
|---|---|---|
| Cron | /etc/crontab, /etc/cron.d/, /etc/cron.{hourly,daily,…}/, /var/spool/cron/, crontab -l -u <user> | T1053.003 |
| Service systemd | /etc/systemd/system/, ~/.config/systemd/user/ | T1543.002 |
| Timer systemd | Fichiers .timer, systemctl list-timers | T1053.006 |
| Clé SSH | ~/.ssh/authorized_keys de chaque compte, root compris | T1098.004 |
| Démarrage du shell | ~/.bashrc, ~/.profile, /etc/profile, /etc/profile.d/, /etc/bash.bashrc | T1546.004 |
| Compte supplémentaire | /etc/passwd (UID 0 en double, nouveau compte) | T1136 |
| Bibliothèque préchargée | /etc/ld.so.preload, variable LD_PRELOAD | T1574.006 |
| Binaire SUID | find / -perm -4000 (un shell SUID caché) | T1548.001 |
| Web shell | Fichiers récents dans la racine du serveur web | T1505.003 |
| Module noyau | lsmod, /etc/modules-load.d/ (rootkits) | T1547.006 |
La clé SSH oubliée
Changer le mot de passe d’un compte compromis ne suffit pas si l’attaquant a ajouté sa clé publique dans authorized_keys : il se reconnecte sans mot de passe. Il faut vérifier ces fichiers pour tous les comptes.
Une vérification rapide après incident
# Comptes avec UID 0 et comptes récemment ajoutés
awk -F: '$3 == 0' /etc/passwd
tail -n 5 /etc/passwd
# Tâches planifiées
ls -la /etc/cron* /var/spool/cron/ 2>/dev/null
for u in $(cut -d: -f1 /etc/passwd); do crontab -l -u "$u" 2>/dev/null; done
# Services et timers ajoutés récemment
ls -lt /etc/systemd/system/ | head
systemctl list-timers --all
# Clés SSH autorisées
find / -name authorized_keys -exec ls -l {} \; 2>/dev/null
# Préchargement de bibliothèques
cat /etc/ld.so.preload 2>/dev/null
# Fichiers modifiés dans les 3 derniers jours dans les dossiers sensibles
find /etc /usr/bin /usr/sbin /var/www -mtime -3 -type f 2>/dev/null
Attention : si la machine est compromise par un rootkit, ces commandes peuvent mentir. Dans une vraie investigation, on analyse plutôt une copie du disque depuis une machine saine (voir la série sur la réponse à incident et le forensic).
C’est la fin de la série sur les systèmes : la suivante s’attaque à Active Directory.
L'essentiel
- Les connexions et l'utilisation de sudo sont dans /var/log/auth.log (Debian, Ubuntu) ou /var/log/secure (Red Hat, Rocky, Alma).
- Sur les systèmes avec systemd, le journal est aussi consultable avec journalctl (ex. journalctl -u ssh --since today).
- last lit /var/log/wtmp (connexions réussies), lastb lit /var/log/btmp (échecs), lastlog donne la dernière connexion de chaque compte.
- SSH : « Accepted password » / « Accepted publickey » = connexion réussie, « Failed password » = échec, « Invalid user » = compte inexistant.
- L'historique bash (~/.bash_history) n'est pas fiable : il n'est écrit qu'à la fermeture du shell et se désactive ou s'efface facilement. auditd est la vraie source pour tracer les commandes.
- Persistance classique sous Linux : cron, services et timers systemd, clés dans ~/.ssh/authorized_keys, fichiers de démarrage du shell (.bashrc, /etc/profile.d), comptes UID 0, /etc/ld.so.preload, web shells.
Idées reçues
L'historique bash d'un compte compromis est vide. Peut-on en conclure que l'attaquant n'a rien fait ?
L'erreur courante. Répondre oui.
En réalité. Non. L'historique n'est écrit qu'à la fermeture propre du shell, et l'attaquant peut le désactiver (unset HISTFILE, HISTSIZE=0), l'effacer (history -c), ou passer par un shell qui n'en tient pas. Un historique vide ou un lien vers /dev/null est même un indice suspect. Il faut s'appuyer sur auditd, les journaux d'authentification, et les traces laissées sur le disque.
Quelle est la différence entre « Failed password for invalid user admin » et « Failed password for root » ?
L'erreur courante. Dire que ce sont deux échecs identiques.
En réalité. Le premier indique que le compte « admin » n'existe pas sur la machine : c'est typique des robots qui essaient des listes de noms. Le second vise un compte qui existe. Une connexion réussie (« Accepted ») venant de la même IP juste après une série d'échecs est le signal à ne pas manquer.
Comment un attaquant peut-il garder un accès SSH sans connaître aucun mot de passe ?
L'erreur courante. Penser qu'il doit forcément voler un mot de passe.
En réalité. En ajoutant sa clé publique dans le fichier ~/.ssh/authorized_keys d'un compte (technique T1098.004). Il peut ensuite se connecter avec sa clé privée, même si le mot de passe est changé. Il faut donc vérifier ces fichiers pour tous les comptes, root compris, après un incident.
Que permet le fichier /etc/ld.so.preload ?
L'erreur courante. Ne pas le connaître.
En réalité. Il force le chargement d'une bibliothèque dans tous les programmes lancés sur la machine. Un attaquant s'en sert pour injecter son code partout, ou pour cacher des fichiers et des processus aux commandes comme ls ou ps (technique de rootkit en espace utilisateur, T1574.006). Ce fichier est absent sur la plupart des systèmes : sa présence est à examiner.
Tester ses connaissances
Références
- Practical Linux ForensicsBruce Nikkel · No Starch Press
- How Linux Works (3e éd.)Brian Ward · No Starch Press