Autoriser les utilisateurs réguliers à SSH à l'aide d'une clé privée qu'ils ne peuvent pas lire


8

Disons que j'ai un ensemble de machines (appelées ici les machines des clients) dans lesquelles seule une petite liste de personnes (appelées le personnel de support) est autorisée à SSH, en utilisant un seul compte par machine (le compte d'accès au support).

Le personnel d'assistance est uniquement censé se connecter aux machines des clients à l'aide de clés. De plus, le personnel de support peut évoluer, de sorte qu'une personne qui quitte le personnel de support n'est pas autorisée à se connecter à une machine client. Par conséquent, il est interdit aux employés de lire les clés privées utilisées pour se connecter aux machines des clients. De plus, il est interdit de modifier le authorized_keysfichier sur les machines des clients.

Pour réaliser cette configuration, j'ai eu l'idée d'utiliser un proxy SSH auquel le personnel de support se connectera (avec l'authentification LDAP, mais c'est un autre problème) et qui contient les clés privées.

La question est: comment autoriser le personnel de support à utiliser la clé privée SSH sans pouvoir la lire?

Je crois que je dois faire un démon fonctionnant en tant que root sur la machine proxy qui acceptera la demande d'un utilisateur et ouvrira une session SSH pour lui, mais je ne sais pas comment le faire. Des idées?


Modification de la question car les "machines clientes" peuvent être difficiles à comprendre (ne signifie pas le contraire du serveur).
Raspbeguy

C'est énormément d'audace, et la plupart semble étrangère. C'est distrayant. Pensez-vous qu'à l'avenir, vous pourriez utiliser beaucoup moins d'audace? Je vous remercie.
DW

Je suppose que la restriction authorized_keys se réfère uniquement aux changements dynamiques (par exemple, lorsqu'un nouveau membre du support rejoint / quitte), car vous avez besoin d' une configuration initiale dans la machine client.
Ángel

Réponses:


6

Je suggérerais quelques options.

  1. Protégez la clé ssh et exigez l'utilisation de la sudopart de votre équipe d'assistance. Vous pouvez le faire de manière transparente avec un wrapper. Appelez le wrapper, disons, /usr/local/bin/ssh-supportet faites-le contenir quelque chose comme ceci (non testé):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1

    Cela nécessiterait une entrée dans le sudoersfichier qui permettrait aux utilisateurs du supportgroupe d'utiliser l'outil. Cette commande leur permet d'exécuter l' ssh-supportoutil en tant ssupportqu'utilisateur - que vous devez créer. Il ne confère aucun privilège root.

    %support ALL = (ssupport) /usr/local/bin/ssh-support

    Si vous êtes heureux que les utilisateurs de soutien ne doivent pas besoin de fournisseur leur propre mot de passe pour exécuter l'outil (tel que demandé par l' sudoinvocation dans le script lui - même) , vous pouvez modifier la sudoersdéfinition ainsi:

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support

    En supposant PATHcontenu que /usr/local/bin/vous appelleriez alors avec ssh-support clientname. En supposant également que vous avez créé l' ssupportutilisateur comme /home/ssupportvous le feriez /home/ssupport/.ssh/id_rsa_clientnameet en /home/ssupport/.ssh/id_rsa_clientname.pubtant que paire de certificats, et que vous avez une entrée d'hôte /home/ssupport/.ssh/configpour clientnamecelle définie l'utilisateur, l'hôte, le port, etc. pour la machine cible. Vous désactiveriez probablement la redirection X11, la redirection de port, etc. explicitement. Comme d'habitude, le /home/ssupport/.sshrépertoire devra être protégé avec des autorisations 0700.

  2. Donnez à chaque membre du support leur propre compte utilisateur local et demandez à chaque personne d'utiliser sa propre clé ssh privée pour accéder aux serveurs du client. Lorsqu'une personne quitte le groupe de support, vous supprimez sa clé ssh des serveurs du client. Cela signifie que vous n'avez plus à vous soucier d'empêcher votre personnel de connaître la clé ssh privée.


La deuxième option n'est pas valide. Comme je l'ai dit, il n'y a qu'un seul compte de support sur les serveurs clients et vous ne pouvez pas ajouter de clés publiques à la configuration ssh, ce sont les règles. En fait, vous ne pouvez rien modifier sur la configuration ssh sur les machines clientes.
Raspbeguy

4
Soit dit en passant, cette réponse est un exemple typique de (ab) en utilisant sudo. J'ai écrit un article sur le sujet ( dmitry.khlebnikov.net/2015/07/… ), il semble qu'il y ait une tendance à essayer de résoudre quoi que ce soit en utilisant sudo. Cependant, cela n'affaiblit que la sécurité de vos systèmes et ne l'améliore pas.
galaxy

1
@Raspbeguy, bien sûr, ils ne le feront pas. La sudoersligne limite l'accès à la commande unique
roaima

1
Vous passez des options non contrôlées à ssh avec "$ @" qui s'exécute en tant que root! Je peux penser à différentes façons de fichiers système corrompus éther (utilisation -Eà append), avant ports privilégiés ( -L,-R,-D) ou racine simplement gain ( -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'le commentaire de la galaxie d'abuser sudo est sur le bon endroit.!
nkms

1
@roaima: Quoi qu'il en soit, votre idée sudo to root a des problèmes, mais ce sont des problèmes différents de ceux dont le blog de galaxie a parlé. Il parle de ssh root@somewhereclés, ssh user@somewherepuis de sudo. C'est en fait un très bon point. Cependant, la seule façon dont il s'applique à ce cas est que ssh keyowner@localhost ssh_to_client client.example.org c'est une alternative à sudo -u keyowner ssh_to_client client.example.org. Semblable à sudo, SSH peut limiter les commandes qu'un utilisateur est autorisé à exécuter. Nous parlons de sudo sans mot de passe à non-root, pas du cas d'utilisation de Galaxy.
Peter Cordes du

11

Ce que vous voulez vraiment faire, c'est utiliser l'AC SSH et signer les clés utilisées par chaque personne de support (elles doivent avoir leurs propres clés ssh, comme les passeports) et configurer les serveurs de vos clients pour utiliser le TrustedUserCAKeys /etc/ssh/users_ca.pubdans / etc / ssh / sshd_config. De cette façon, le serveur acceptera n'importe quelle clé signée par la clé CA (à laquelle vous avez accès) et vous pourrez révoquer les clés de personnes qui ne sont plus en charge sans même toucher les touches autorisées.

Une recherche rapide de "ssh ca" a indiqué ce didacticiel: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu ( faites défiler jusqu'à "Comment configurer les clés utilisateur") - bien que le tutoriel mentionne Ubuntu, il est indépendant de la distribution, mais vous avez besoin d'une nouvelle version d'OpenSSH qui prend en charge SSH CA

Une autre bonne entrée de blog sur le sujet est https://ef.gy/hardening-ssh (faites défiler jusqu'à "Certificats SSH").

Faites particulièrement attention à ce que vous puissiez signer la clé pour qu'elle soit valide pour une durée limitée, afin qu'elle expire automatiquement!


Ce serait une bonne idée si les machines des clients avaient accès à Internet (pour mettre à jour la validité d'une signature), ce qui n'est pas toujours le cas. Nous nous connectons à ces machines via un VPN fourni par le client.
Raspbeguy

Eh bien, c'est aussi proche que possible sans divulguer une clé avec une personne qui quitte votre entreprise. Je vous ai fourni le mécanisme, vous pouvez l'automatiser, par exemple, vous pouvez avoir un officier de permanence qui prend en charge vos RH lorsque les gens quittent l'entreprise et vous pouvez définir une procédure sur la façon de révoquer les clés.
galaxy

1
De plus, vous pouvez signer une clé (celle de la personne de soutien) pour une durée limitée - par exemple, vous pouvez la signer juste pendant 8 heures (pour leur quart de travail), après 8 heures, elle expirera et le serveur ne les laissera pas entrer.
galaxy

3
Concernant votre partie LDAP - je travaille actuellement dans une entreprise qui gère des centaines d'instances et nous travaillons sur une solution open source pour intégrer SAML 2.0 et SSH CA. L'idée est qu'une personne s'authentifie à l'aide de l'authentification unique et si elle est autorisée à faire signer ses clés pour une période de temps définie (par exemple 5 minutes). Tout cela est assez transparent pour l'utilisateur et est implémenté à l'aide du ProxyCommand de ~ / .ssh / config.
galaxy

2

Il existe quelques réponses différentes impliquant un script wrapper pour ssh invoqué via sudo ou setuid-executable (vers un compte non root à usage spécial ). Comme le dit nkms , le passage de tous les arguments à ssh permet à l'utilisateur de faire des choses arbitraires avec les clés ssh que nous essayons de protéger. L'autre extrême que certains ont trouvé est de n'autoriser qu'un nom d'hôte.

L'OP dit que les administrateurs doivent pouvoir télécharger des choses.

Vous pouvez avoir deux wrappers d'arguments fixes à ssh différents. Un pour un shell de connexion, un autre pour scp. Aucun argument fourni par l'utilisateur autre que le nom d'hôte (et le nom de fichier à télécharger).

Ou un script wrapper qui s'utilise getoptlui-même pour analyser des options très limitées et brancher des choses dans une commande ssh principalement fixe. Ignorer (ou commettre des erreurs) les options non reconnues serait la voie à suivre.

N'essayez pas de filtrer les options ssh «dangereuses», écrivez simplement un wrapper qui peut faire deux choses: une connexion interactive ou télécharger un fichier (noms de fichiers locaux et distants). Vous devez encore faire un peu de désinfection là-bas, je suppose.

En fait, il est toujours facile de se tromper. Vous devez trouver un moyen d'empêcher l'utilisateur de donner le fichier contenant les clés ssh comme fichier local. Donc, vous essayez toujours de penser à tout ce qui doit être interdit, au lieu de commencer à ne rien autoriser. Ce serait un début pour vous assurer que les noms de fichiers ne contiennent aucun @ou :.


L'idée du wrapper est la solution en effet, mais cela implique une faille de sécurité qui doit être comblée.
Raspbeguy

Je suis étonné de voir comment les gens réinventent la roue alors qu’elle n’en a pas besoin. La fonctionnalité SSH CA a été introduite dans OpenSSH exactement pour les raisons et la situation comme la question d'origine. Ma solution n'a pas utilisé d'emballages et a répondu exactement à ce qui était demandé, mais pour une raison quelconque, @Raspbeguy a décidé d'opter pour le bricolage avec des implications de sécurité discutables. :)
galaxy

@galaxy: oui, votre solution CA SSH est la meilleure à coup sûr, sauf si vous avez une exigence absolue que vous ne pouvez pas apporter une modification unique aux systèmes distants pour configurer leur sshd pour l'utiliser. Cela semble parfait et facile à bien faire.
Peter Cordes

@galaxy: votre solution est vraiment élégante, mais pas applicable dans mon cas comme je vous l'ai dit plus tôt. J'aime vraiment l'idée, j'en ai parlé à mon patron mais c'est toujours impossible. Pas besoin de s'énerver.
Raspbeguy

1
@Raspbeguy, je ne suis pas contrarié, je ne comprends tout simplement pas pourquoi votre entreprise veut sacrifier sa sécurité et mettre en œuvre quelque chose à l'aide de «ruban adhésif» alors qu'il existe un moyen approprié de le faire. Et votre commentaire était que ce serait une bonne solution, mais vous n'aimiez pas que vous ne puissiez pas automatiser la révocation - et je vous ai également fourni la solution à cela (en signant des clés pour le quart de travail uniquement). Quoi qu'il en soit, vous avez choisi votre réponse, passons à autre chose :)
galaxy

1

Si vous configurez un serveur proxy SSH, vous pouvez faire en sorte que le shell (in /etc/passwd) de vos utilisateurs ne soit pas défini sur un shell tel que bash, mais plutôt sur un script simple qui n'autorise pas l'accès au shell. Au lieu de cela, il demanderait alors un nom d'hôte cible ( read target) exec ssh "support@$target".

Notez que l'utilisation d'un proxy comme celui-ci peut rendre difficile l'utilisation d'outils tels que scple transfert de fichiers vers / depuis les machines client. Cela peut être un problème ou un avantage!


Cette idée de script wrapper est similaire à l'idée de @ roaima. Vous y donnez accès avec ssh, mais ça sudomarche aussi. Sa réponse suggère d'utiliser l'utilisateur root local, mais un utilisateur non root fonctionnerait aussi. Voir mes commentaires sur sa réponse pour en discuter. (Mon ssh keyowner@localhostidée est la même que la vôtre.)
Peter Cordes

@Peter - tout à fait raison: root n'est absolument pas le bon utilisateur pour cela!
Toby Speight du

Les gars de support doivent télécharger des choses, donc cette solution peut ne pas fonctionner.
Raspbeguy

@Raspbeguy: a publié une réponse qui résout ce problème. À utiliser en combinaison avec la configuration non root de roaima sudo.
Peter Cordes

0

Vos assistants se connectent toujours via cette machine proxy, et uniquement à partir de celle-ci, afin que les clients puissent simplement authentifier la machine proxy à l'aide de HostbasedAuthentication .

Disons que la machine proxy est supporters.pcet que vous fournissez un support àcustomer.pc

customer.pc aura HostbasedAuthentication yes in /etc/ssh/ssd_config, supporters.pc listés dans /etc/ssh/shosts.equivet sa clé publique dans /etc/ssh/ssh_known_hosts.

Lorsque votre personnel de support se connecte à support@supporters.pc et exécute ssh customer.pc, il générera ssh-keysign (8) (qui doit être défini), qui gérera la signature de la clé avec le fichier que vous ne pouvez pas lire et fournir à supporters.pc la preuve que la connexion provient bien de supporters.pc . En tant que customer.pc fait confiance à supporters.pc , votre membre du personnel est connecté en tant que support .


C'est une solution terrible du point de vue de la sécurité car si vous accordez l'accès à une machine dans son ensemble et que vous perdez la responsabilité de qui a fait quoi. La confiance de machine à machine devrait être interdite dans le monde moderne où la sécurité informatique a commencé à émerger en tant que sujet assez brûlant.
galaxy

@galaxy, d'après l'OP, je crois comprendre qu'ils font déjà essentiellement cela. La confiance dans cette machine est dans la spécification . Notez spécifiquement qu'ils "n'utilisent qu'un seul compte par machine (le compte d'accès au support)", il est possible qu'ils utilisent un compte partagé dans customer.pc, mais se connectent au serveur en tant que leur propre utilisateur. Changer les autorisations de ssh et ssh-keygen afin de forcer un support sudo -u ssh… résoudrait cela et ajouterait également une entrée de journal.
Ángel

0

Utilisez un binaire wrapper

Pour ce cas d'utilisation particulier (voir la note importante ci-dessous), une possibilité est de créer un utilisateur (par exemple support-ssh) spécifiquement pour ces connexions SSH sortantes, puis d'installer un petit binaire wrapper qui s'exécute /usr/bin/ssh.

  • Ne copiez pas + chmod le sshbinaire lui-même, car vous ne vous souviendrez pas de le recopier à chaque fois que vous appliquez des mises à jour de sécurité.
  • Et ne l'utilisez pas en roottant qu'utilisateur plus privilégié, pour des raisons en lesquelles j'ai confiance sont évidentes.

Il s'agit d'une alternative fonctionnellement équivalente à l'utilisation sudopour élever les privilèges à ceux du support-sshcompte avec les compromis suivants:

  • C'est plus petit et plus léger que sudo, donc il y a moins de risques d'erreur de configuration qui s'ouvre plus que vous ne le pensiez.
  • Il est de votre responsabilité de le coder correctement - ne le faites que si vous êtes extrêmement prudent et (idéalement) avez une expérience du codage critique pour la sécurité.
  • Il peut être personnalisé pour être plus spécifique que sudo(mais plus vous écrivez de code, plus vous devez auditer pour la sécurité).

Le binaire wrapper doit être défini HOMEsur le support-sshrépertoire personnel de l' utilisateur, de sorte que sshla ssh_configclé privée et appropriée sera récupérée . Mais l'utilisateur invoquant ne devrait pas être autorisé à lire ~support-ssh/.ssh/ou à lire son contenu.

L'emballage peut être aussi simple que:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    setenv("HOME", "/home/support-ssh", 1);
    /* allow only a single, non-option argument */
    if (argc!=2 || *argv[1]=='-') {
        fprintf(stderr, "Usage: %s <hostname>", argv[0]);
        exit(EXIT_FAILURE);
    }
    execv("/usr/bin/ssh", argv);
    return EXIT_FAILURE;
}

Vous voudrez peut-être être plus restrictif et vérifier que l'argument se argv[1]trouve dans un ensemble de noms d'hôtes autorisés. Ou moins restrictif et autorisez (un sous-ensemble de) les arguments d'option. Vous pouvez remplacer complètement les variables d'environnement (mais garder les importants tels que TERM, LC_*, etc.); notez cela LD_LIBRARY_PATHet LD_PRELOADsont particulièrement dangereux.

Un programme wrapper similaire pourrait être fourni scpsi nécessaire.

Une note sur l'applicabilité

Cette réponse répond aux circonstances spécifiques de la question, où les utilisateurs sont contractuellement obligés de suivre les procédures, et il y a des sanctions (par exemple, licenciement) pour les violer. Cela suppose que vous souhaitiez empêcher les employés de copier des clés privées avec désinvolture, plutôt que d'empêcher un attaquant déterminé d'obtenir un accès non autorisé.

Je suis d'avis que la sécurité est obtenue à la fois par des moyens de défense techniques et non techniques, et que l'équilibre obtenu ici ou en utilisant sudoest approprié à la situation présentée.


Vous passez des arguments non vérifiés à ssh en cours d'exécution en tant qu'un autre utilisateur, voir mon commentaire sur la réponse ci-dessus. Je peux toujours lire la clé ... et je ne compterais pas sur des vérifications strictes des arguments, ssh n'est pas censé être exécuté de cette façon.
nkms

@nkms - J'ai rendu le wrapper plus restrictif. Il peut être rendu plus ouvert si nécessaire, mais vous avez raison de verrouiller les choses, sauf indication contraire, plutôt que l'inverse.
Toby Speight

@TobySpeight: yup, semble bon. J'ai mis la plupart de ce que j'ai dit dans les commentaires dans ma propre réponse.
Peter Cordes

1
Il serait préférable d'utiliser sudo qu'un wrapper binaire. Contrairement à ce que vous prétendez, utiliser sudo est beaucoup moins risqué que de rouler le vôtre. Sudo a des valeurs par défaut sûres. Êtes-vous sûr que vous n'avez pas oublié de supprimer une variable d'environnement qui pourrait influencer ssh?
Gilles 'SO- arrête d'être méchant'
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.