Aller au contenu
Ilan Oudor Étudiant en Cybersécurité
Tous les articles
4 min de lecture

Deux heures. C'est le temps qu'il a fallu pour la première tentative

SSH par clés, fail2ban, CrowdSec, Trivy. Et le moment où j'ai regardé les journaux d'une machine mise en ligne le matin même.

HardeningSSHfail2banCrowdSecTrivy

Supprimer le mot de passe plutôt que le renforcer

Le conseil qu'on m'avait donné en cours, c'était d'imposer des mots de passe longs.

C'est un mauvais conseil, parce qu'il laisse le mécanisme en place. Tant qu'une authentification par mot de passe est acceptée, elle peut être devinée, rejouée, ou obtenue par hameçonnage.

La config qu'on a retenue supprime le mécanisme :

# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers admin@10.99.0.0/24
MaxAuthTries 3

La ligne qui compte le plus est AllowUsers. Elle restreint l'accès à un seul compte, et uniquement depuis le VLAN d'administration. Même avec la bonne clé privée, une connexion depuis le LAN est refusée avant toute vérification cryptographique.

Petite mésaventure : j'ai relancé sshd avec une directive mal orthographiée et je me suis retrouvé dehors. Sauvé par la console Proxmox. Depuis, rituel invariable :

sshd -t                  # valide la syntaxe AVANT
systemctl reload sshd    # recharge sans couper les sessions ouvertes
# et on garde le terminal actuel ouvert le temps de tester une nouvelle connexion

fail2ban, et ce que j'ai vu dans les logs

fail2ban lit les journaux et bannit les IP qui échouent trop souvent. Avec PasswordAuthentication no, son rôle change : il ne protège plus contre le forçage de mot de passe, puisqu'il n'y en a plus. Il élimine le bruit de fond.

[sshd]
enabled  = true
maxretry = 3
findtime = 10m
bantime  = 1h
bantime.increment = true     # 1h, puis 2h, puis 4h pour les récidivistes

bantime.increment est le réglage que je conseillerais à tout le monde. Un scanner persistant finit banni des jours entiers, alors qu'un admin qui se trompe de clé est bloqué quelques minutes.

Ensuite j'ai regardé le compteur.

La machine était en ligne depuis le matin. La première tentative d'authentification non sollicitée est arrivée en moins de deux heures. Au bout d'une semaine, plusieurs milliers, depuis des dizaines de pays, testant toujours les mêmes noms : root, admin, ubuntu, test, oracle.

Rien de ciblé. Personne ne m'en voulait. C'est du balayage industriel de l'espace d'adressage IPv4.

C'est une chose de lire en cours qu'Internet est hostile. C'en est une autre de voir le compteur grimper sur sa propre machine, alors qu'elle n'héberge encore rien.

CrowdSec : apprendre des attaques des autres

fail2ban a une limite. Chaque serveur apprend seul, et seulement après avoir été attaqué. Si une IP a passé la journée à attaquer mille autres machines, la mienne l'ignore jusqu'à ce qu'elle s'y mette.

CrowdSec analyse les journaux localement, comme fail2ban, mais partage les signaux avec une communauté et redistribue une liste noire construite à partir de ce qui est observé ailleurs.

Trois filtres successifs devant l'application Requête entrante 1 · Pare-feu OPNsense port fermé, refus 2 · Liste noire bouncer CrowdSec IP signalée, refus 3 · Service application authentification les journaux du service alimentent la décision de blocage
Le bouncer s'intercale devant Traefik : une adresse déjà signalée ailleurs n'atteint jamais l'application.

Sur la semaine d'observation, une bonne partie du trafic bloqué l'a été par la liste communautaire, pour des adresses que notre machine n'avait jamais croisées.

Trivy, et la surface d'attaque qu'on ne voit pas

Les trois couches précédentes protègent l'accès. Elles ne disent rien de ce qu'il y a dans les conteneurs qu'on déploie.

trivy image liste les vulnérabilités connues des paquets d'une image. Le premier scan sur nos images a été un rappel à l'ordre. Des images officielles, récentes, tirées de Docker Hub, embarquaient des dizaines de vulnérabilités connues, dont plusieurs critiques.

trivy image --severity HIGH,CRITICAL --ignore-unfixed --exit-code 1 monimage:latest

--ignore-unfixed est l'option qui rend l'outil utilisable. Sans elle, on se noie sous des centaines de vulnérabilités sans correctif disponible, donc sur lesquelles on ne peut rien faire. Avec elle, la sortie devient une liste de choses à corriger.

Le fil rouge

Chaque couche répond à une menace différente. SSH par clés supprime une classe entière d'attaques, fail2ban et CrowdSec absorbent l'automatisé, Trivy traite ce qu'on introduit soi-même. Aucune ne suffit seule.

Mais s'il ne fallait garder qu'une chose : la configuration par défaut d'un outil n'est pas un choix de sécurité. C'est un choix de compatibilité, fait pour que le truc démarre chez tout le monde du premier coup. Le travail commence là où la doc s'arrête.