4 points par GN⁺ 2024-06-24 | 1 commentaires | Partager sur WhatsApp

Objectif

  • Permettre uniquement aux utilisateurs autorisés d’exécuter des commandes avec les privilèges root
  • Ne pas utiliser d’élévation de privilèges

Mise en œuvre

  • Créer une clé SSH dédiée pour l’utiliser dans l’authentification root

    mkdir /root/.ssh/
    echo ssh-ed25519 AAAAC3Nza... > /root/.ssh/local_keys
    
  • Lancer une instance du serveur sshd liée à un socket de domaine Unix

    mkdir /run/sshd/
    chown root:wheel /run/sshd/
    chmod 750 /run/sshd/
    s6-ipcserver /run/sshd/sshd.sock sshd -ie -o AuthorizedKeysFile=/root/.ssh/local_keys -o PermitRootLogin=yes
    
  • Verrouiller le compte root et le configurer pour empêcher toute connexion par mot de passe

    # modifier le mot de passe root dans le fichier /etc/passwd
    
  • Utiliser l’option ProxyCommand pour se connecter à l’instance locale de sshd

    ssh -o ProxyCommand='socat STDIO UNIX-CONNECT:/run/sshd/sshd.sock' \
        -i .ssh/root-key.pub \
        -t \
        root@root \
        "cd $(pwd); '$SHELL' --login"
    
  • Écrire un script qui transmet le descripteur de fichier du socket à l’aide de l’option ProxyUseFdpass

    #!/usr/bin/env python3
    import sys
    import socket
    import array
    
    s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    s.connect("/run/sshd/sshd.sock")
    
    fds = array.array("i", [s.fileno()])
    ancdata = [(socket.SOL_SOCKET, socket.SCM_RIGHTS, fds)]
    socket.socket(fileno=1).sendmsg([b'\0'], ancdata)
    
  • Exécuter finalement la commande ssh

    ssh -o ProxyCommand='/home/hugo/tmp/passfd.py' \
        -i .ssh/root-key.pub \
        -o ProxyUseFdpass=yes \
        -t \
        root@root \
        "cd $(pwd); '$SHELL' --login"
    

Conclusion

  • Cette technique utilise OpenSSH pour gérer les détails de sécurité
  • Elle prend en charge diverses méthodes d’authentification, y compris les clés SSH matérielles
  • La procédure de configuration sur un nouvel hôte n’est pas compliquée
  • Le script passfd.py est une solution provisoire pour l’expérimentation ; pour un usage quotidien, il vaut mieux en faire un petit exécutable

L’avis de GN⁺

  • Cette méthode peut améliorer la sécurité comme alternative à sudo ou doas
  • L’approche consistant à utiliser SSH pour renforcer l’authentification prend en charge diverses méthodes d’authentification, y compris l’authentification matérielle
  • La configuration système reste relativement simple, si bien qu’un ingénieur débutant peut facilement la reproduire
  • Il serait plus pratique de transformer le script passfd.py en petit exécutable et de le placer dans /usr/local/bin
  • Cette méthode fonctionne uniquement en local, sans exposition réseau, ce qui renforce la sécurité

1 commentaires

 
GN⁺ 2024-06-24
Avis Hacker News
  • Problème de complexité supplémentaire : au lieu d’un seul binaire suid existant, il faut désormais deux binaires utilisant un socket UNIX, dont l’un s’exécute en tant que root. Cela augmente la complexité, y compris avec des opérations de chiffrement asymétrique.

  • Sécurité du système : en limitant le binaire sudo à un groupe spécifique (wheel) et en ajustant les permissions, on peut conserver un niveau de sécurité similaire à l’approche sshd. Si le gestionnaire de paquets du système casse les permissions de sudo, il est aussi possible de les corriger périodiquement avec cron ou d’installer sudo directement depuis les sources.

  • run0 de systemd : l’outil run0 de systemd fonctionne de manière similaire à sudo, mais n’est pas SUID. Il demande à la place au gestionnaire de services d’exécuter la commande. Son fonctionnement ressemble donc davantage à celui de ssh.

  • Comparaison entre ssh et sudo : on peut se demander si se connecter en root via ssh est réellement plus sûr que sudo. Il faut aussi discuter de la manière d’empêcher l’accès d’utilisateurs distants à sshd. Comparée aux limitations de sudo, l’approche via ssh peut être plus vulnérable.

  • Problème des services réseau : si ssh ne démarre pas au boot, la connexion via console devient elle aussi impossible. Cela peut causer davantage de problèmes que sudo ou su.

  • Approche similaire à systemd run0 : il existe une approche similaire à l’outil run0 de systemd.

  • Contrôle fin avec sudo : sudo permet de contrôler finement les commandes et leurs arguments, la création de sous-shells, etc. Une nouvelle approche perdrait ce niveau de granularité, et la gestion de clés de confiance deviendrait plus difficile.

  • Configuration d’une console SSH : une méthode consiste à gérer l’accès root via une console SSH dédiée, avec un Yubikey et des règles de pare-feu pour renforcer la sécurité.

  • Limites du protocole SSH : dans SSH, la création de processus ne fait pas partie du protocole, et il n’est pas possible de transmettre des ressources locales à un processus enfant. Pour l’utiliser comme remplacement de sudo, il faudrait une extension comparable à POSIX spawn.

  • Gestion des utilisateurs : il est important de ne pas traiter les utilisateurs comme des enfants, mais de définir des valeurs par défaut raisonnables pour éviter les problèmes potentiels. Si un accès root est nécessaire, il est préférable de se connecter via la console.

  • Problème du mode mono-utilisateur : s’il est impossible de se connecter en root en mode mono-utilisateur, la récupération du système devient difficile. C’est nécessaire pour résoudre des problèmes pouvant survenir lors d’une mise à niveau du système.