web-dev-qa-db-fra.com

Comment limiter les utilisateurs SSH à un ensemble de commandes prédéfini après la connexion?

C'est une idée de sécurité. Nos employés auront accès à certaines commandes sur un serveur Linux mais pas à tous. Ils doivent par exemple avoir la possibilité d'accéder à un fichier journal (less logfile) ou lancer différentes commandes (shutdown.sh/run.sh).

Informations d'arrière-plan:

Tous les employés accèdent au serveur avec le même nom d'utilisateur: notre produit s'exécute avec des autorisations utilisateur "normales", aucune "installation" n'est nécessaire. Décompressez-le simplement dans votre répertoire utilisateur et lancez-le. Nous gérons plusieurs serveurs sur lesquels notre application est "installée". Sur chaque machine, il y a un utilisateur johndoe. Nos employés ont parfois besoin d'accéder à l'application en ligne de commande pour accéder aux fichiers journaux et les vérifier, ou pour redémarrer l'application manuellement. Seules certaines personnes auront un accès complet en ligne de commande.

Nous utilisons l'authentification ppk sur le serveur.

Ce serait formidable si employee1 ne peut accéder qu’au fichier journal et que employee2 peut aussi faire X, etc.

Solution: Comme solution, je vais utiliser l'option command comme indiqué dans le accepté réponse . Je vais créer mon propre petit script Shell qui sera le seul fichier pouvant être exécuté pour certains employés. Le script proposera plusieurs commandes pouvant être exécutées, mais aucune autre. Je vais utiliser les paramètres suivants dans authorized_keys de comme indiqué ici :

command="/bin/myscript.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty
ssh-dss AAAAB3....o9M9qz4xqGCqGXoJw= user@Host

C'est assez de sécurité pour nous. Merci, communauté!

78
Marcel

Vous pouvez également limiter les clés aux commandes autorisées (dans le fichier allowed_keys).

C'est à dire. l'utilisateur ne se connecterait pas via ssh et n'aurait alors qu'un ensemble restreint de commandes mais serait seulement autorisé à exécuter ces commandes via ssh (par exemple, "ssh somehost bin/showlogfile")

63
HD.

ssh suit la tradition rsh en utilisant le programme Shell de l'utilisateur à partir du fichier de mots de passe pour exécuter des commandes.

Cela signifie que nous pouvons résoudre ce problème sans impliquer la configuration de ssh de quelque manière que ce soit.

Si vous ne souhaitez pas que l'utilisateur puisse accéder à Shell, remplacez-le simplement par un script. Si vous regardez dans /etc/passwd vous verrez qu'il existe un champ qui attribue un interpréteur de commandes Shell à chaque utilisateur. Le script est utilisé comme Shell à la fois pour leur connexion interactive ssh user@Host ainsi que pour les commandes ssh user@Host command arg ....

Voici un exemple. J'ai créé un utilisateur foo dont le shell est un script. Le script imprime le message my arguments are: suivi de ses arguments (chacun sur une ligne séparée et entre crochets) et se termine. Dans le journal au cas où, il n'y a pas d'arguments. Voici ce qui se passe:

webserver:~# ssh foo@localhost
foo@localhost's password:
Linux webserver [ snip ]
[ snip ]
my arguments are:
Connection to localhost closed.

Si l'utilisateur essaie d'exécuter une commande, cela ressemble à ceci:

webserver:~# ssh foo@localhost cat /etc/passwd
foo@localhost's password:
my arguments are:
<-c>
<cat /etc/passwd>

Notre "Shell" reçoit un -c appel de style, avec la commande entière comme un argument, de la même manière que /bin/sh le recevrait.

Comme vous pouvez le constater, nous pouvons maintenant développer le script de manière à ce qu’il reconnaisse le cas quand il a été appelé avec un -c argument, puis analyse la chaîne (disons par correspondance). Les chaînes autorisées peuvent être passées au shell réel en appelant récursivement /bin/bash -c <string>. Le cas de rejet peut imprimer un message d'erreur et se terminer (y compris le cas où -c est manquant).

Vous devez faire attention à la façon dont vous écrivez cela. Je recommande d’écrire uniquement des correspondances positives qui ne permettent que des choses très spécifiques et interdisent tout le reste.

Note: Si vous êtes root, vous pouvez toujours vous connecter à ce compte en remplaçant le shell dans la commande su, comme ceci su -s /bin/bash foo. (Shell de remplacement au choix.) Les utilisateurs non root ne peuvent pas le faire.

Voici un exemple de script: restreindre l’utilisateur à l’utilisation exclusive de ssh pour git aux référentiels sous /git.

#!/bin/sh

if [ $# -ne 2 ] || [ "$1" != "-c" ] ; then
  printf "interactive login not permitted\n"
  exit 1
fi

set -- $2

if [ $# != 2 ] ; then
  printf "wrong number of arguments\n"
  exit 1
fi

case "$1" in
  ( git-upload-pack | git-receive-pack )
    ;; # continue execution
  ( * )
    printf "command not allowed\n"
    exit 1
    ;;
esac

# Canonicalize the path name: we don't want escape out of
# git via ../ path components.

gitpath=$(readlink -f "$2")  # GNU Coreutils specific

case "$gitpath" in
  ( /git/* )
     ;; # continue execution
  ( * )
    printf "access denied outside of /git\n"
    exit 1
    ;;
esac

if ! [ -e "$gitpath" ] ; then
   printf "that git repo doesn't exist\n"
   exit 1
fi

"$1" "$gitpath"

Bien sûr, nous sommes convaincus que ces programmes Git git-upload-pack et git-receive-pack ne pas avoir de trous ou de trappes d’échappement permettant aux utilisateurs d’accéder au système.

Cela est inhérent à ce type de système de restriction. L'utilisateur est authentifié pour exécuter du code dans un certain domaine de sécurité et nous modifions une restriction afin de limiter ce domaine à un sous-domaine. Par exemple, si vous autorisez un utilisateur à exécuter la commande vim sur un fichier spécifique pour l'éditer, l'utilisateur peut simplement obtenir un shell avec :!sh[Enter].

29
Kaz

Ce que vous recherchez s'appelle Restricted Shell . Bash fournit un tel mode dans lequel les utilisateurs ne peuvent exécuter que les commandes présentes dans leurs répertoires de départ (et ne peuvent pas se déplacer dans d’autres répertoires), ce qui pourrait vous suffire.

J'ai trouvé ce fil très illustratif, bien qu'un peu daté.

14
Vinko Vrsalovic

Vous devriez acquérir `rssh ', le shell restreint

Vous pouvez suivre les guides de restriction mentionnés ci-dessus, ils sont tous plutôt explicites et simples à suivre. Comprendre les termes "prison chroot" et savoir comment implémenter efficacement les configurations sshd/terminal, etc.

Étant donné que la plupart de vos utilisateurs accèdent à vos terminaux via sshd, vous devriez probablement vous pencher également sur sshd_conifg, le fichier de configuration du démon SSH, pour appliquer certaines restrictions via SSH. Soyez prudent, cependant. Comprenez bien ce que vous essayez de mettre en œuvre, car les ramifications de configurations incorrectes sont probablement plutôt graves.

4
Chuah

Pourquoi n'écris-tu pas ton propre login-shell? Il serait assez simple d'utiliser Bash pour cela, mais vous pouvez utiliser n'importe quelle langue.

Exemple dans Bash

Utilisez votre éditeur préféré pour créer le fichier /root/rbash.sh (cela peut être n’importe quel nom ou chemin, mais devrait être chown root:root et chmod 700):

#!/bin/bash

commands=("man" "pwd" "ls" "whoami")
timestamp(){ date +'%Y-%m-%s %H:%M:%S'; }
log(){ echo -e "$(timestamp)\t$1\t$(whoami)\t$2" > /var/log/rbash.log; }
trycmd()
{
    # Provide an option to exit the Shell
    if [[ "$ln" == "exit" ]] || [[ "$ln" == "q" ]]
    then
        exit

    # You can do exact string matching for some alias:
    Elif [[ "$ln" == "help" ]]
    then
        echo "Type exit or q to quit."
        echo "Commands you can use:"
        echo "  help"
        echo "  echo"
        echo "${commands[@]}" | tr ' ' '\n' | awk '{print "  " $0}'

    # You can use custom regular expression matching:
    Elif [[ "$ln" =~ ^echo\ .*$ ]]
    then
        ln="${ln:5}"
        echo "$ln" # Beware, these double quotes are important to prevent malicious injection

        # For example, optionally you can log this command
        log COMMAND "echo $ln"

    # Or you could even check an array of commands:
    else
        ok=false
        for cmd in "${commands[@]}"
        do
            if [[ "$cmd" == "$ln" ]]
            then
                ok=true
            fi
        done
        if $ok
        then
            $ln
        else
            log DENIED "$cmd"
        fi
    fi
}

# Optionally show a friendly welcome-message with instructions since it is a custom Shell
echo "$(timestamp) Welcome, $(whoami). Type 'help' for information."

# Optionally log the login
log LOGIN "$@"

# Optionally log the logout
trap "trap=\"\";log LOGOUT;exit" EXIT

# Optionally check for '-c custom_command' arguments passed directly to Shell
# Then you can also use ssh user@Host custom_command, which will execute /root/rbash.sh
if [[ "$1" == "-c" ]]
then
    shift
    trycmd "$@"
else
    while echo -n "> " && read ln
    do
        trycmd "$ln"
    done
fi

Tout ce que vous avez à faire est de définir cet exécutable comme shell de connexion. Par exemple, modifiez votre /etc/passwd fichier, et remplacez votre login actuel Shell de cet utilisateur /bin/bash avec /root/rbash.sh.

Ceci est juste un exemple simple, mais vous pouvez le rendre aussi avancé que vous le souhaitez, l’idée est là. Veillez à ne pas vous verrouiller en modifiant le login Shell de votre propre et unique utilisateur. Et testez toujours des symboles et des commandes étranges pour voir si elle est réellement sécurisée.

Vous pouvez le tester avec: su -s /root/rbash.sh.

Attention, assurez-vous de faire correspondre toute la commande et faites attention aux caractères génériques! Mieux vaut exclure les symboles Bash tels que ;, &, &&, ||, $, et des backticks pour en être sûr.

En fonction de la liberté que vous donnez à l'utilisateur, cela ne sera pas beaucoup plus sûr. J'ai constaté que souvent, je devais uniquement créer un utilisateur qui n'a accès qu'à quelques commandes pertinentes. Dans ce cas, c'est vraiment la meilleure solution. Cependant, souhaitez-vous donner plus de liberté, une prison et des autorisations pourraient être plus appropriées. Les erreurs sont faciles à commettre et à remarquer seulement quand il est déjà trop tard.

3
Yeti

Vous voudrez peut-être envisager de créer un prison .

1
tmeisenh

[Divulgation: j'ai écrit sshdo qui est décrit ci-dessous]

Si vous souhaitez que la connexion soit interactive, la configuration d'un shell restreint est probablement la bonne solution. Mais s’il existe un ensemble de commandes que vous souhaitez autoriser (et rien d’autre) et qu’il est correct de les exécuter individuellement via ssh (par exemple, utilisateur ssh @ Host cmd arg blah blah), une commande générique SSH pourrait être ce dont vous avez besoin. Ceci est utile lorsque les commandes sont scriptées d'une manière ou d'une autre du côté du client et que l'utilisateur ne soit pas obligé de taper réellement la commande ssh.

Il existe un programme appelé sshdo pour le faire. Il contrôle quelles commandes peuvent être exécutées via les connexions ssh entrantes. Il est disponible au téléchargement sur:

http://raf.org/sshdo/ (lisez les pages du manuel ici) https://github.com/raforg/sshdo/

Il a un mode de formation pour autoriser toutes les commandes tentées et une option --learn pour produire la configuration nécessaire pour autoriser les commandes apprises de manière permanente. Ensuite, le mode de formation peut être désactivé et aucune autre commande ne sera exécutée.

Il a également une option --unlearn pour arrêter l’autorisation des commandes qui ne sont plus utilisées afin de conserver le moindre privilège strict au fur et à mesure de l'évolution des exigences.

C'est très pointilleux sur ce que cela permet. Cela ne permettra pas une commande avec des arguments. Seules les commandes complètes du shell peuvent être autorisées.

Mais il prend en charge des modèles simples pour représenter des commandes similaires qui ne varient que par les chiffres apparaissant sur la ligne de commande (par exemple, des numéros de séquence ou des horodatages).

C'est comme un pare-feu ou un contrôle de liste blanche pour les commandes ssh.

Et il prend en charge différentes commandes autorisées pour différents utilisateurs.

0
raf

Une autre façon de voir les choses consiste à utiliser les ACL POSIX; cela doit être pris en charge par votre système de fichiers. Cependant, vous pouvez avoir un réglage fin de toutes les commandes sous Linux de la même manière que vous avez le même contrôle sous Windows (sans la meilleure interface utilisateur). ). lien

Une autre chose à examiner est PolicyKit .

Vous devrez faire pas mal de recherches sur Google pour que tout fonctionne, car ce n’est certainement pas une force de Linux pour le moment.

0
Bryan Rehbein