Restriction des commandes SSH sur clés publique /privée

Afin d’effectuer la sauvegarde d’un serveur par un autre, il est courant d’utiliser un couple de clé SSH publique/privée sans mot de passe.

Tout commence par la génération du couple de clé :

fhh@mafalda ~ $ ssh-keygen -b4096 -C "Clé de sauvegarde" -f ~/.ssh/Saves
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): # rien
Enter same passphrase again: # rien
Your identification has been saved in /home/fhh/.ssh/Saves.
Your public key has been saved in /home/fhh/.ssh/Saves.pub.
The key fingerprint is:
80:f8:8e:69:e3:95:6a:98:a7:d3:e4:89:53:be:dc:68 Clé de sauvegarde
The key's randomart image is:
+--[ RSA 4096]----+
...
+-----------------+
fhh@mafalda ~ $ ls .ssh/Saves*
.ssh/Saves  .ssh/Saves.pub

… et ce poursuit par la copie de la clé publique (.ssh/Saves.pub) dans le fichier « .ssh/authorized_keys » du serveur à sauvegarder :

fhh@mafalda ~ $ cat .ssh/Saves.pub | ssh srv.rez0.lan 'cat >> .ssh/authorized_keys'
Password:
fhh@mafalda ~ $ ssh -i .ssh/Saves srv.rez0.lan 'cat .ssh/authorized_keys'
...
ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde

… pour finir par l’ajout de la clé associée au serveur dans « .ssh/config » :

fhh@mafalda ~ $ cat .ssh/config
...
Host=srvtobackup1
Hostname=srv.rez0.lan
User=fhh
Port=22
Compression=yes
IdentityFile=~/.ssh/Saves
...
fhh@mafalda ~ $ ssh srvtobackup1
fhh@srv ~ $

Le travail consiste ensuite à sécuriser cet accès au serveur à sauvegarder avec ce couple de clé :

  • seul le serveur de sauvegarde devra être autorisé à ce connecter avec la clé privée.
  • seul les commandes effectuant la sauvegarde devront être autorisée par cette connexion.

Toutes ces restrictions ce mettent en place sur le serveurs à sauvegarder directement dans le fichier « .ssh/authorized_keys ».

Limiter les machines autorisées à ce connecter avec la clé privée

Le champs « from=XXX » sur le serveur à sauvegarder restreint l’accès par cette clé aux machines spécifiées. »XXX » peu désigner :

  • le FQDN d’une machine, ex : machine.rez0.lan (seul cette machine sera authorisée à ce connecter en utilisant cette clé) ;
  • une adresse IP, ex : 10.0.2.2 (comme pour le FQDN mais avec l’IP) ;
  • une plage IP, ex : 10.0.2.* (toutes les machines de cette plage pourront utiliser cette clé pour ce connecter) ;
  • un domaine, ex : *.rez0.lan (comme pour la plage IP mais avec le domaine) ;
  • une liste restrictive de machine, ex : « *.rez0.lan, !ns1.rez0.lan » ;
  • des noms de machines utilisant les jokers habituels, ex : « ns?.rez0.lan ».

En reprenant notre exemple, seul la machine « mafalda.rez0.lan » doit être autorisée à ce connecter au serveur devant être sauvegardé :

fhh@mafalda ~ $ ssh srvtobackup1
fhh@srv ~ $ vi .ssh/authorized_keys
...
## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>)
from="mafalda.rez0.lan" ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde
...
fhh@srv ~ $ exit
Connection to srv.rez0.lan closed.
fhh@mafalda ~ $ ssh srvtobackup1
fhh@srv ~ $

mais depuis une autre machine disposant également de la clé privée et des mêmes paramètres dans « .ssh/config », le mot de passe est demandé :

fhh@asus ~ $ ssh srvtobackup1
Password:

Limiter les fonctionnalités de la clé

La clé étant destinée uniquement à lancer une sauvegarde, les fonctionnalités tel que le X11 forwarding ou le port forwarding peuvent être suspendues. En fonction de l’utilisation faite de la clé, l’accès à un tty peut également être suspendu afin de ne plus offrir un shell interactif.

Avec une configuration du type :

fhh@srv ~ $ cat .ssh/authorized_keys
...
## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>)
from="mafalda.rez0.lan",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty  ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde
...

Nous obtenons un comportement plutôt restrictif :

fhh@mafalda ~ $ ssh srvtobackup1
PTY allocation request failed on channel 0
Killed by signal 15.
fhh@mafalda ~ $ ssh srvtobackup1 'ls'
0493.pdf
fic1.txt
...

mais pas encore suffisamment :

fhh@mafalda ~ $ ssh srvtobackup1 '/bin/bash'
ls
0493.pdf
fic1.txt
...
cat /etc/passwd
root:x:0:0:Compte administrateur local:/root:/bin/bash
...

Limiter les commandes utilisable

Le couple de clé généré est, nous l’avons déjà dit, destiné à sauvegarder les données du serveur « SRV » au travers du réseau. La commande qui sera passée au serveur à sauvegardé sera donc toujours la même et, pour des raisons de sécurité, il est préférable de n’autoriser le lancement QUE de cette commande. Malheureusement, SSH ne dispose pas d’un système de restriction nous permettant de sélectionner les commandes lancées sur une connexion. En revanche, l’option command= »string » lance automatiquement UNE commande à chaque connexion utilisant le couple clés privée/publique auquel elle est appliquée.

Par exemple :

## Clé de sauvegarde depuis MAFALDA (mafalda.rez0.lan <10.0.2.2>)
from="mafalda.rez0.lan",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="ls" ssh-rsa AAAAB...OA6s3H0c= Clé de sauvegarde

retourne le retour de « ls » quelque soit les paramètres passés lors de la connexion :

fhh@mafalda ~ $ ssh srvtobackup1 'cat /etc/passwd'
0493.pdf
fic1.txt
...
fhh@mafalda ~ $ ssh srvtobackup1 'cat /bin/bash'
0493.pdf
fic1.txt
...

Pour restreindre l’accès à une commande autorisées, nous lançons un script shell, dès l’établissement de la connexion, qui examine la chaîne de caractère passée en argument à SSH, la valide (afin d’éviter une attaque par injection, ex : si « ls* » est seul autorisé, la commande « ls ; /bin/bash » l’est aussi), et, si elle est valide l’exécute.

Voici une proposition de script :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/bin/bash
 
# Commande autorisée :
AUTHORIZED_CMD="ls /tmp/"
 
# Validation de la commande :
case "$SSH_ORIGINAL_COMMAND" in
#       Si elle contient des caractère sensible, on la logue, on la rejette
# et on sort :
        *\&* | *\(* | *\{* | *\;* | *\<* | *\`* | *\|* )
                logger "BAD SSH SEQUENCE : \"$SSH_ORIGINAL_COMMAND\"." ;
                echo "Rejected" ;
                exit 1 ;
                ;;
#       Si la commande autorisée match, elle est exécutée et sort :
        ${AUTHORIZED_CMD})
                logger "SSH EXECUTING \"$SSH_ORIGINAL_COMMAND\"" ;
                $SSH_ORIGINAL_COMMAND ;
                exit $? ;
                ;;
        *)
#       Tout autre commande est rejetée et loguée :
                logger "BAD SSH SEQUENCE : \"$SSH_ORIGINAL_COMMAND\"." ;
                echo "Rejected" ;
                exit 1
                ;;
esac
# Si on en arrive là, il y a un problème :
logger "ERROR SSH : \"$SSH_ORIGINAL_COMMAND\"" ;
echo "Error"
exit 1 ;

Télécharger le script « ssh-validation ».

Qui donne à l’exécution :

fhh@mafalda ~ $ ssh srvtobackup1 'ls /tmp/'
conftest19483
test
fhh@mafalda ~ $ ssh srvtobackup1 'ls -al /tmp/'
Rejected

et dans les logs :

...
Sep 17 19:41:11 srv logger: SSH EXECUTING "ls /tmp/"
...
Sep 17 19:41:14 srv logger: BAD SSH SEQUENCE : "ls -al /tmp/".
...

Ce script n’est qu’une base, toute proposition d’amélioration est la bienvenue.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *