Solution de prae_gitlab pour Échec OP 3/3

forensics mémoire linux

8 décembre 2024

Analyse préliminaire

En récupérant l’image, une petite analyse rapide, c’est une image avec plusieurs partitions présentes :

# fdisk -l fcsc.raw | grep "^fcsc"
fcsc.raw1     2048     4095     2048    1M BIOS boot
fcsc.raw2     4096  1861631  1857536  907M Linux filesystem
fcsc.raw3  1861632 20969471 19107840  9,1G Linux filesystem

On décide de faire un petit loopback-setup sur ce fichier pour qu’il soit mappé sur /dev/loop0 et ainsi avoir accès aux différentes partitions :

losetup -P /dev/loop0 fcsc.raw

Je me retrouve avec un mapping des différentes partitions sur le loopback device :

# fdisk -l /dev/loop0 | grep "^/dev/loop0"
/dev/loop0p1    2048     4095     2048    1M BIOS boot
/dev/loop0p2    4096  1861631  1857536  907M Linux filesystem
/dev/loop0p3 1861632 20969471 19107840  9,1G Linux filesystem

$ lsblk
NAME                MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
loop0                 7:0    0    10G  1 loop
├─loop0p1           259:4    0     1M  1 part
├─loop0p2           259:5    0   907M  1 part
└─loop0p3           259:6    0   9,1G  1 part

$ bklid
/dev/loop0p3: UUID="45e2f0c4-6640-453d-8b7a-8a60bd61c63d" TYPE="crypto_LUKS" PARTUUID="2460a435-c99a-4e48-a8d9-2ad8c3308242"
/dev/loop0p1: PARTUUID="fd391bf6-5e1f-4966-82e8-57e2547fd4ad"
/dev/loop0p2: UUID="427db55e-1263-43a4-9005-dfb083639311" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="3d33e289-3358-4e7b-80b7-3c9be3d5de07"

On sait que le /dev/loop0p3 est chiffré, donc on utilise cryptsetup pour ouvrir le coffre-fort numérique :

# cryptsetup luksOpen /dev/loop0p3 rootfs
Enter passphrase for /dev/loop0p3: fcsc2022

Voilà, notre rootfs est bindé et ouvert :

$ lsblk
NAME                MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
loop0                 7:0    0    10G  1 loop
├─loop0p1           259:4    0     1M  1 part
├─loop0p2           259:5    0   907M  1 part
└─loop0p3           259:6    0   9,1G  1 part
  └─rootfs          252:3    0   9,1G  1 crypt

Je décide de monter le système de fichiers normalement, voir ce qu’il y a à l’intérieur et naviguer dans les différents répertoires et fichiers. Je regarde dans l’historique du shell, rien (enfin si mais… passons… ;-) ). Je vais voir du côté de /var/log/, je vois des adresses IP, mais aucun ne fonctionne. J’analyse les fichiers lastlog, btmp et wtmp et les adresses IP ne fonctionnent pas également. Je finis par me dire que l’auteur a loupé un truc… ou bien que c’est moi…

Je reviens sur la note d’intention de l’auteur et je lis “semble avoir essayé de dissimuler l’une de ses adresses IP”.

Je pars sur l’idée d’une offuscation d’adresse IP, je fais même un reverse de certains hashs étranges dans certains logs. Je ne trouve toujours rien, je finis par aller voir dans la partition où sont stockées les données du /boot en espérant un indice, mais rien de probant. J’en suis même à reverse l’image swap en me disant que les quelques octets présents dedans non-NULL sont des données potentiellement intéressantes…

Mais je sors de là bredouille…

Log wars : A new hope

Je reviens de nouveau sur la note d’intention de l’auteur et je me dis que j’ai peut-être mal interprété ce qu’il a voulu dire. En effet, j’ai écarté une idée, celle de données supprimées, mais encore présentes dans le filesystem. J’ai écarté cette idée, car le recouvrement de données supprimées était déjà présent dans un autre défi, et donc, j’ai écarté cette possibilité pensant qu’on ne pouvait pas avoir le même genre de défi dans un autre défi… Grave erreur de ma part : Déjà pour avoir écarté une possible solution, mais en plus de n’avoir pas prévu ce cas de figure : j’ai monté le fs en read-write, ce qui veut dire que j’ai potentiellement manipulé des données sur le filesystem et écrasé le flag caché…

Je décide de repartir de zéro avec un nouveau fcsc.raw vierge et sans possibilité de pouvoir toucher au fs :

chattr -i fcsc.raw   # mode parano :-)
losetup --read-only -P /dev/loop0 fcsc.raw
cryptsetup luksOpen /dev/loop0p3 rootfs

De là, j’ai un device déchiffré et mappé dans un /dev/dm-4, je décide d’aller à la pèche des données en raw sur le device. En partant sur ce principe, je suis sûr de ne pas toucher au fs (même avec les différents read-only flag auparavant ;-)

Je pars à la pèche en essayant de filtrer l’output de l’analyse : Le système étant administré à distance, je filtre sur la syntaxe d’un log sshd, d’une adresse IP et de notre cher obob, pour voir qui s’est connecté par le passé sur le système :

sshd[<pid>]: Accepted password for obob from <ipaddr> port <port> ssh2

Lançons une regex sur un résultat strings du device rootfs :

# strings /dev/dm-4 | grep "sshd.*Accepted.*obob.*\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}"
Mar 27 04:12:29 obob sshd[1571]: Accepted password for obob from 192.168.37.1 port 41864 ssh2
Mar 27 21:19:49 obob sshd[1308]: Accepted password for obob from 192.168.37.1 port 33028 ssh2
Mar 27 21:21:48 obob sshd[1536]: Accepted password for obob from 192.168.37.1 port 33032 ssh2
Mar 27 21:19:49 obob sshd[1308]: Accepted password for obob from 192.168.37.1 port 33028 ssh2
Mar 27 03:54:01 obob sshd[2161]: Accepted password for obob from 172.16.123.1 port 34520 ssh2
Mar 27 21:50:51 obob sshd[4956]: Accepted password for obob from 172.16.123.1 port 55266 ssh2
Mar 27 04:12:29 obob sshd[1571]: Accepted password for obob from 192.168.37.1 port 41864 ssh2
Mar 27 21:21:48 obob sshd[1536]: Accepted password for obob from 192.168.37.1 port 33032 ssh2
Mar 27 21:29:40 obob sshd[1212]: Accepted password for obob from 172.16.123.1 port 55180 ssh2
Mar 27 21:30:47 obob sshd[1427]: Accepted password for obob from 172.16.123.1 port 55182 ssh2
Mar 27 21:31:14 obob sshd[1547]: Accepted password for obob from 172.16.123.1 port 55184 ssh2
Mar 27 21:35:59 obob sshd[2293]: Accepted password for obob from 172.16.123.1 port 55204 ssh2
Mar 27 21:36:17 obob sshd[2410]: Accepted password for obob from 172.16.123.1 port 55206 ssh2
Mar 27 21:36:45 obob sshd[2556]: Accepted password for obob from 172.16.123.1 port 55208 ssh2
Mar 27 21:37:03 obob sshd[2675]: Accepted password for obob from 172.16.123.1 port 55210 ssh2
Mar 27 21:40:09 obob sshd[4366]: Accepted password for obob from 172.16.123.1 port 55218 ssh2
Mar 27 21:49:40 obob sshd[4804]: Accepted password for obob from 172.16.123.1 port 55258 ssh2

Dans le tas des adresses IP que j’avais vu dans les logs lors de ma première analyse, je constate une IP que je n’avais jamais vu auparavant et qui n’apparait pas dans le filesystem maintenant : 192.168.37.1

En prenant cette adresse IP et en filtrant de nouveau, elle apparait également dans d’autres occurrences introuvables maintenant et qui sont plus d’étranges :

MESSAGE=    obob : TTY=pts/0 ; PWD=/var/log ; USER=root ; COMMAND=/usr/bin/grep -r -a 172.16.123.1 .
_CMDLINE=sudo grep -r -a 172.16.123.1 .
MESSAGE=    obob : TTY=pts/0 ; PWD=/var/log ; USER=root ; COMMAND=/usr/bin/grep -r -a 172.16.123.1  .
_CMDLINE=sudo grep -r -a 172.16.123.1  .
sudo grep -r -a '172.16.123.1 ' .
fail2ban.filter         [5082]: INFO    [sshd] Found 192.168.37.1 - 2022-03-27 04:12:26

Le flag ne peut être que lui :

FCSC{192.168.37.1}