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 :

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 :

Cependant, ces arguments sont déjà fragiles :

À noter que dans tous les cas, l’authentification par mot de passe reste intrinsèquement fragile. Les scripts, robots, et administrateurs peu sensibilisés ne vérifient jamais ces empreintes, ce qui permet à l’attaquant présent sur le réseau un man-in-the-middle. 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. Je me suis basé sur rsync magic command du même auteur ; ). 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 :

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.