Débusquons les mythes cybersécurité !
De nombreux responsables sécurité interdisent la connexion SSH à partir du login root
. Nous
allons voir dans cet article en quoi cette mesure de sécurité reste en réalité trop souvent
incomprise, et en profiter pour initier la catégories cargo cult security
, inspirée de
l’expression Cargo Cult Programming
en l’adaptant à la cyber-sécurité.
Interdire la connexion SSH à partir de l’utilisateur root
La variable permitRootLogin
accepte les valeurs suivantes :
PermitRootLogin
no (interdiction) ou yes (autorisation)
without-password (obsolète) ou prohibit-password
forced-commands-only (c'est la meilleure option en fait)
À noter la valeur without-password
trompeuse, puisqu’elle interdit en réalité la connexion à
partir d’un mot de passe. La valeur prohibit-password
, plus claire, la déprécie désormais.
Les justifications apportées se résument généralement aux arguments suivants :
- Le login
root
étant prédictible, l’attaquant peut tenter de deviner son mot de passe et passe ainsi d’une complexité n2 à n, - L’attaquant disposerait directement des pleins pouvoir,
- Perte de traçabilité, puisqu’il n’est plus évident de faire correspondre
root
à l’utilisateur se connectant.
Et donc, nos ‘‘experts en sécurité’’ choisissent de durcir la configuration SSH de la façon suivante :
PermitRootLogin no
À noter à titre d’exemple le man oscap-ssh
:
Note that the openscap scanner is best run by the root
user as in the first example above. To do this, the PermitRootLogin
directive must be enabled in /etc/ssh/sshd_config
,
which is itself a security violation.
A safer approach is to enable a non-privileged user (oscap-user
in the second example above) to run only the oscap
binary as root
(with the --sudo
flag) by updating the remote machine’s sudoers
file or adding a file like /etc/sudoers.d/99-oscap-user
:
Defaults!/usr/bin/oscap !requiretty oscap-user ALL=(root) NOPASSWD: /usr/bin/oscap
Parfait ! Qu’on m’explique en quoi une règle sudo
potentiellement dangeureuse reste mieux qu’un PermitRootLogin=forced-commands-only
Mais nos ‘‘experts en sécurité’’ vivent heureux.
Et nous, on va quand même avoir des problèmes.
Pourquoi ça ne marche pas
Techniquement, cela permet pourtant de respecter le cahier des charges : Plus de connexion directe
à partir de l’utilisateur root
, donc :
- Plus difficile à bruteforcer, il faut désormais déterminer un utilisateur valide en plus du mot de passe,
- L’attaquant ayant néanmoins réussi à déterminer un couple {utilisateur} ↔ {mot de passe} valide ne dispose donc que d’un compte sans privilège,
- La configuration permet la traçabilité.
Cependant, ces arguments sont déjà fragiles :
- Un mot de passe de 6 caractères alphanumériques aléatoires (pas non plus la politique la plus robuste) nécessite quand même, à supposer un bruteforce de 10 essais par secondes (donc une bonne latence pour l’attaquant) (26 + 26 + 10)6 / 10 secondes pour atteindre l’ensemble de l’espace, soit environ 180 ans…
- Si l’attaquant découvre le mot de passe associé au login nominatif de l’administrateur, ben…
il est administrateur ! Il lui suffira de backdoorer son
bashrc
pour récupérer le mot de passesudo
ousu
!
À noter : L’authentification par mot de passe reste intrinsèquement fragile !
Les scripts, robots, et administrateurs peu sensibilisés ne vérifient jamais ces empreintes. Pensez notamment aux scripts et tâches planifiées lancées avecStrictHostKeyChecking=no
ou
KnownHostsFile=/dev/null
.
Un attaquant présent sur le réseau pouvant réaliser un
man-in-the-middle
obtiendra ce mot de
passe.
Voir le très bon article gremwell - MITM SSH qui démontre d’ailleurs que l’authentification par clef interdit complètement le MITM.
Mais à l’extrême, si interdir le SSH pour l’utilisateur root
permet de faire plaisir à nos
‘‘experts sécurité’’ et de passer à autre chose, cela pourrait constituer un compromis acceptable.
En réalité, les effets de bords sont pires que le mal.
Des effets de bords imprévus
J’ai dû m’attacher à la configuration rsync
pour permettre de réaliser un plan de restauration.
J'en ai profité pour rédiger cet article :
rsync magic command.
L’idée consiste à utiliser une clef SSH tagguée pour imposer l’ouverture du démon rsync
dans un tunnel
SSH et à réaliser le transfert via SSH, bénéficiant ainsi du chiffrement des données transférées et d’une
authentification solide par clef SSH. Cependant, pour respecter l’interdiction de connexion en
root
, j’ai dû utiliser un utilisateur sans privilèges.
La configuration ressemblait alors à ceci :
uid = youruser
gid = youruser
use chroot = no
read only = no
max connections = 2
log file = /tmp/rsyncd.log
pid file = /tmp/rsyncd.pid
[module1]
path = /home/youruser/upload_target
comment = Restricted upload area
auth users = fakeuser
J’obtenais le message d’erreur suivant dans le fichier /tmp/rsyncd.log
:
rsync: [Receiver] setgroups failed: Operation not permitted (1)
Cette erreur survient parce que :
- Le processus
rsync
tente de droper ses privilèges, - Mais il n’a pas le droit pour cela ; puisque la
capability
associée n’est permise qu’à l’utilisateurroot
.
La solution consiste alors à exécuter rsync
en sudo
!
# clef SSH tagguée
command="sudo /usr/bin/rsync --server --daemon --config=/home/myuser/rsyncd.conf" ssh-rsa ...
# Configuration sudo
myuser ALL=(ALL) NOPASSWD: /usr/bin/rsync
Super ! Maintenant, au lieu d’avoir un transfert de fichiers protégé par clef, j’ai un utilisateur
jusque là non-privilégié mais pouvant désormais utiliser rsync
à loisir sur la machine ;
L’élévation de privilège s’obtient rapidement (cf. Cette réponse très complête sur stackoverflow.).
% sudo rsync --perms --chmod u+s /bin/dash /bin/rootdash
% rootdash
# whoami
root
À retenir :
À chaque fois que vous devez renseigner sudo
pour une tâche automatique ou périodique, vous faites une erreur !
Comment travailler proprement
De très nombreux outils, scripts de sauvegarde / restauration, tâches planifiées de transfert de
fichiers, supervision, etc. nécessitent parfois de se connecter à partir de l’utilisateur root
.
Et c’est normal !
Plutôt que l’interdire de manière dogmatique, et ouvrir par effet de bord des brêches critiques
dans la configuration sudo
, il est préférable de paramétrer pour chaque besoin une clef SSH
tagguée et déclencher l’action sur cette clef :
PermitRootLogin forced-commands-only
La clef tagguée permet de restreindre à des jeux atomiques d’actions unitaires dont l’administrateur doit pouvoir déterminer si elles présentent un danger ou non.
La pratique d’interdire la connexion à root
implique de configurer un utilisateur sans privilège,
de lui associer des scripts de post-exécution, pour déplacer les fichiers synchronisés par
exemple dans un autre répertoire, de changer les permissions et les ownerships, etc. in fine
de réaliser un grand nombre de tâches toutes plus à risques puisqu’impliquant une élévation
et la transmission de données potentiellement sensibles à des utilisateurs non-privilégiés.