Le Port de Cobalt a été la cible d’une attaque sur son serveur SCADA.
La direction fait appel à vous pour comprendre comment les assaillants ont réussi à prendre le contrôle des équipements portuaires et à compromettre la sécurité du port.
Les premières investigations ont montré que l’attaquant a utilisé un accès VPN d’un employé corrompu pour pénétrer le système et contourner les contrôles de sécurité, accédant ainsi directement au serveur SCADA avec un compte sans privilèges.
La direction vous met à disposition une copie partielle du système de fichiers ainsi qu’une extraction des logs de connexions SSH correspondant à la période de l’incident.
Votre tâche consiste à analyser minutieusement les données fournies afin d’identifier tout élément suspect ou indicateur de compromission. Recherchez les traces d’activités inhabituelles, les configurations anormales ou les fichiers modifiés qui pourraient révéler les vulnérabilités exploitées par l’attaquant.
Pour effectuer l'exercice, on commencera par monter le système de fichier :
$ mkdir Sillage
$ sudo mount -t squashfs -o loop rootfs.squashfs Sillage/
$ cd Sillage
Une bonne habitude serait de vérifier les sommes de contrôles des paquets et fichiers de configuration du système :
$ sudo debsums --all --silent
debsums: changed file /etc/pam.d/sshd (from openssh-server package)
debsums: changed file /etc/pam.d/su (from util-linux package)
$ echo $?
2
Cependant cette action n'offre rien de concluant si ce n'est des fausses pistes. En effet, en voyant des configurations changées pour SSH et su on aura tendance à se dire que l'on tient la bonne piste, mais il n'en est rien (ce sont des durcissements de configuration qui ont fait ressortir ces fichiers, pas des failles liées à l'exercice).
Le premier indice à trouver est un binaire setuid laissé par l'intrusion comme porte dérobée. On utilisera la commande suivante pour les lister :
$ find . -type f -user root -perm /4000 2>/dev/null
./usr/bin/chfn
./usr/bin/chsh
./usr/bin/fusermount3
./usr/bin/gpasswd
./usr/bin/mount
./usr/bin/newgrp
./usr/bin/ntfs-3g
./usr/bin/ntfs-4g
./usr/bin/passwd
./usr/bin/pkexec
./usr/bin/su
./usr/bin/sudo
./usr/bin/umount
./usr/lib/dbus-1.0/dbus-daemon-launch-helper
./usr/lib/openssh/ssh-keysign
./usr/lib/polkit-1/polkit-agent-helper-1
./usr/lib/xorg/Xorg.wrap
./usr/sbin/pppd
$ find . -type f -user root -perm /4000 2>/dev/null | xargs ls -al
-rwsr-xr-x 1 root root 62672 Apr 7 12:38 ./usr/bin/chfn
-rwsr-xr-x 1 root root 52880 Apr 7 12:38 ./usr/bin/chsh
-rwsr-xr-x 1 root root 35128 Jun 7 14:10 ./usr/bin/fusermount3
-rwsr-xr-x 1 root root 88496 Apr 7 12:38 ./usr/bin/gpasswd
-rwsr-xr-x 1 root root 59704 Nov 21 2024 ./usr/bin/mount
-rwsr-xr-x 1 root root 48896 Apr 7 12:38 ./usr/bin/newgrp
-rwsr-xr-x 1 root root 162752 Jun 7 14:10 ./usr/bin/ntfs-3g
-rwsr-xr-x 1 root root 186 Jun 7 14:10 ./usr/bin/ntfs-4g
-rwsr-xr-x 1 root root 68248 Apr 7 12:38 ./usr/bin/passwd
-rwsr-xr-x 1 root root 26776 Jan 31 2023 ./usr/bin/pkexec
-rwsr-xr-x 1 root root 72000 Nov 21 2024 ./usr/bin/su
-rwsr-xr-x 1 root root 281624 Jun 27 2023 ./usr/bin/sudo
-rwsr-xr-x 1 root root 35128 Nov 21 2024 ./usr/bin/umount
-rwsr-xr-- 1 root uuidd 51272 Sep 16 2023 ./usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 653888 May 8 12:54 ./usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 18664 Jan 31 2023 ./usr/lib/polkit-1/polkit-agent-helper-1
-rwsr-sr-x 1 root root 14672 Feb 19 14:42 ./usr/lib/xorg/Xorg.wrap
-rwsr-xr-- 1 root dip 403832 May 14 2022 ./usr/sbin/pppd
Les binaires setuid retournés semblent légitimes, et aucun ne ressort particulièrement du lot. Cependant, si l'on se renseigne sur chacun des paquets grâce au site https://www.debian.org/distrib/packages#search_packages, on se rend compte que ntfs-3g existe bien mais pas ntfs-4g malgré des similitudes dans leur convention de nommage.
Pour la suite, la date de modification du fichier (7 juin 2025 14:10) sera une information clé.
Pour le second lot de fichiers à trouver, il faudra s'intéresser aux services systemd :
$ ls -l etc/systemd/system
total 1
lrwxrwxrwx 1 root root 42 Jun 3 19:15 dbus-fi.w1.wpa_supplicant1.service -> /lib/systemd/system/wpa_supplicant.service
-rw-r--r-- 1 root root 296 May 8 12:54 dbus-monitor.service
lrwxrwxrwx 1 root root 40 Jun 3 19:15 dbus-org.freedesktop.Avahi.service -> /lib/systemd/system/avahi-daemon.service
lrwxrwxrwx 1 root root 40 Jun 3 19:16 dbus-org.freedesktop.ModemManager1.service -> /lib/systemd/system/ModemManager.service
lrwxrwxrwx 1 root root 53 Jun 3 19:16 dbus-org.freedesktop.nm-dispatcher.service -> /lib/systemd/system/NetworkManager-dispatcher.service
lrwxrwxrwx 1 root root 45 Jun 3 19:15 dbus-org.freedesktop.timesync1.service -> /lib/systemd/system/systemd-timesyncd.service
lrwxrwxrwx 1 root root 35 Jun 3 19:15 display-manager.service -> /lib/systemd/system/lightdm.service
drwxr-xr-x 2 root root 41 Jun 3 19:09 getty.target.wants
drwxr-xr-x 2 root root 38 Jun 3 19:15 graphical.target.wants
drwxr-xr-x 2 root root 472 Jun 8 01:16 multi-user.target.wants
drwxr-xr-x 2 root root 83 Jun 3 19:16 network-online.target.wants
drwxr-xr-x 2 root root 35 Jun 3 19:15 printer.target.wants
drwxr-xr-x 2 root root 84 Jun 3 19:17 sockets.target.wants
lrwxrwxrwx 1 root root 31 Jun 5 02:12 sshd.service -> /lib/systemd/system/ssh.service
drwxr-xr-x 2 root root 220 Jun 3 19:17 sysinit.target.wants
drwxr-xr-x 2 root root 206 Jun 3 19:15 timers.target.wants
Le premier élément différenciant sera une date de modification différente des autres fichiers du dossier pour le fichier de service dbus-monitor.service.
Pourtant le contenu semble légitime :
$ cat etc/systemd/system/dbus-monitor.service
[Unit]
Description=DBUS Session Monitor
Documentation=man:dbus-monitor(1)
After=network.target
[Service]
Type=simple
ExecStart=/usr/libexec/dbus-monitor
Restart=on-failure
RestartSec=15s
StandardOutput=null
StandardError=null
SyslogIdentifier=dbus-monitor
[Install]
WantedBy=multi-user.target
Hormis les sections StandardOutput et StandardError qui indiquent de ne pas enregistrer la sortie, ce qui est suspicieux surtout pour un service devant monitorer des données.
Cette piste nous mène également jusqu'au binaire /usr/libexec/dbus-monitor, hors après quelques recherches il apparait que le binaire dbus-monitor légitime installé par le paquet dbus-bin (https://packages.debian.org/bookworm/amd64/dbus-bin/filelist) devrait être situé dans /usr/bin/ et non dans /usr/libexec/, c'est donc bien le fichier /usr/libexec/dbus-monitor qui est le maillon finale de cette implantation dans le système.
Il ne faudra pas oublier dans notre réponse le lien symbolique /etc/systemd/system/multi-user.target.wants/dbus-monitor.service qui indique que le service systemd usurpant dbus-monitor est lancé à chaque démarrage du système, ce qui en fait un bon point d'ancrage pour la persistance.
Pour résumer, voici les fichiers attendus :
- /usr/bin/ntfs-4g
- /usr/libexec/dbus-monitor
- /etc/systemd/system/dbus-monitor.service
- /etc/systemd/system/multi-user.target.wants/dbus-monitor.service
Pour le second flag, on s'intéressera au fichier de logs SSH sshd_auth.log fourni. En se remémorant la date de modification du fichier /usr/bin/ntfs-4g (7 juin 2025 14:10), on observe certaines connexions le 7 juin 2025, dont une à 14:09. On peut estimer qu'il aura fallu environ une minute à l'attaquant pour effectuer son attaque avant de créer sa porte dérobée dont il a oublié de modifier la date de création dans la précipitation.
Jun 07 14:09:47 SCADA sshd[12053]: Connection from 10.28.0.38 port 56778 on 10.2.0.10 port 22 rdomain ""
# ...
On en déduit donc que l'usurpation a été faite sur le compte d'audit n°28.
Le premier indice à trouver est l'incohérence de la version du kernel par rapport à la distribution Debian.
$ cat etc/*-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
On apprend donc que l'OS est Debian 12, la version du kernel installée devrait donc être en 6.x.x.
$ ls -l boot
total 436463
-rw-r--r-- 1 root root 248521 Jun 4 03:13 config-5.16.10
drwxr-xr-x 5 root root 119 Jun 4 04:02 grub
-rw-r--r-- 1 root root 435426167 Jun 4 03:14 initrd.img-5.16.10
-rw-r--r-- 1 root root 4734653 Jun 4 03:13 System.map-5.16.10
-rw-r--r-- 1 root root 6527392 Jun 4 03:13 vmlinuz-5.16.10
Or la version kernel installée est 5.16.10, ce qui est normalement la série pour un Debian 11 (des contraintes de compatibilités logicielles ont pu être à l'origine de cette paire inhabituelle).
De là, il suffit de chercher par exemple CVE kernel 5.16.10 sur un navigateur (ou un LLM) et d'analyser les propositions. On sait que le compte d'audit n°28 n'a aucun privilège, il s'agit donc d'une faille de type escalade de privilèges puisque l'attaquant a pu obtenir un accès root. La CVE la plus probable est donc DirtyPipe.