8 votes

Permettre l'exécution automatique de commandes en tant que root sous Linux en utilisant SSH

Quelle est une bonne configuration permettant l'exécution automatique d'une commande ou d'un script sur un serveur distant avec root privilèges en utilisant SSH ?

Je suis conscient (seulement vaguement pour certaines des options) des options suivantes :

  • Permettre une connexion directe par root ( PermitRootLogin ) (et éventuellement en forçant l'authentification des clés).
  • Configuration de sudo de ne pas exiger un mot de passe ( NOPASSWD le drapeau en sudoers ) et TTY ( requiretty drapeau).
  • Configuration de sudo pour permettre l'exécution de commandes/scripts spécifiques, lorsqu'ils sont authentifiés avec une clé privée spécifique.
  • Définition du propriétaire du script en tant que root et la mise en place permission setuid .

Mais d'abord, je ne suis pas sûr des conséquences de ces mesures sur la sécurité. Par exemple, je sais que le fait d'autoriser root La connexion est désapprouvée. Mais je ne suis pas sûr que ce ne soit pas un point de vue obsolète. D'après ce que j'ai compris, il semble qu'une authentification par mot de passe soit le danger. Avec l'authentification par clé publique, le root La connexion pourrait être correcte. Et pour certaines des options, notamment l'option sudo Je ne suis même pas sûr de la configuration nécessaire. Bien que je sois capable de googler tout cela, il pourrait y avoir des considérations de sécurité que je pourrais manquer, c'est pourquoi je demande l'avis d'experts.

Notez, que je demande une côté serveur installation. L'exécution sera déclenchée par un programme, et non par un outil de type ssh donc je ne cherche pas des choses comme l'automatique. client l'authentification.


Le contexte : Être actif dans ssh tag sur Stack Overflow L'une des questions qui reviennent le plus souvent concerne les différents hacks que les gens tentent d'exécuter une commande/script (ou même un serveur SFTP) par SSH sur un serveur Unix/Linux distant en utilisant une clé USB. root compte à l'aide de divers langages de programmation (C#, Java, VB.NET, Python, etc.) et de bibliothèques SSH (SSH.NET, JSch, Paramiko, etc.).

Les implémentations, que les gens tentent, essayent généralement d'utiliser su o sudo . Ces derniers demandent alors un mot de passe. Les implémentations essaient alors de transmettre le mot de passe à l'entrée de commande. Comme su y sudo exigent souvent émulation de terminal pour l'invite de mot de passe, l'implémentation doit exiger PTY. Ce qui, à son tour, cause d'autres problèmes, car les sessions avec l'émulation de terminal utilisent souvent des fonctions interactives, telles que Codes d'échappement ANSI la pagination, etc. Tout cela conduit à des tas d'autres bidouillages peu fiables qui tentent de supprimer ou même d'interpréter les codes d'échappement ANSI ou de simuler un terminal suffisamment grand pour éviter la pagination.

Quelques exemples parmi tant d'autres :

Bien que je puisse généralement fournir une aide pour la mise en œuvre de ces astuces, j'ajoute généralement une suggestion selon laquelle il existe des moyens plus efficaces que l'automatisation. sudo / su . Mais je ne suis pas vraiment sûr de pouvoir fournir des détails sur ces prétendues "de meilleurs moyens" . Une question connexe : です。 sudo presque inutile ?

Donc je cherche un canonique du point de vue d'un super utilisateur, qui peut ensuite être consulté et adapté aux besoins de Stack Overflow.

3voto

porto alet Points 315

Je pense qu'une solution appropriée pour une majorité de cas simples [ c'est-à-dire si un framework comme Puppet/Chef/CfEngine/Ansible est surchargé ], mais qu'un haut niveau de contrôle du système distant est requis est de

(a) Exiger une authentification basée sur une clé (b) verrouiller les emplacements qui peuvent être utilisés par SSH - en particulier pour verrouiller les adresses IP que les utilisateurs root peuvent utiliser (c) S'assurer que les machines ayant cette relation de confiance sont correctement sécurisées.

Je ne crois pas que "se connecter en tant que root soit mal vu", mais plutôt que "se connecter en tant que root pour faire des choses qui ne nécessitent pas les droits de root" soit mal vu. En autorisant les gens à se connecter en tant que root, ils peuvent commettre des erreurs stupides avec une portée plus large, et faire des choses douteuses qui cachent une activité malveillante - mais selon l'architecture, cela peut ne pas avoir de sens.

Ce site XKCD commic souligne qu'en fonction de l'environnement, la compromission d'un compte root peut ne pas avoir d'importance.

La solution la plus simple et la plus efficace pour le cas général est probablement de limiter exactement qui peut se connecter en tant que root en contrôlant les clés conjointement avec la spécification d'une ligne AllowUsers appropriée dans /etc/ssh/sshd.conf. Une ligne appropriée pour autoriser les utilisateurs normaux mais verrouiller l'accès root pourrait ressembler à ceci :

  AllowUsers normaluser1 normaluser2 root@ip.add.re.ss

Bien sûr, il est important que la connexion par mot de passe ne soit pas autorisée, ou que le compte root n'ait pas de mot de passe (c'est-à-dire qu'il y ait un " !" ou un "*" dans le champ du mot de passe du fichier de mot de passe).

Comme vous l'avez suggéré, si un seul (ou un petit nombre de) programme(s) doit être exécuté, vous feriez mieux de configurer un utilisateur spécifique avec une authentification basée sur une clé et d'autoriser un accès sudo approprié aux commandes requises.

Il y a, bien sûr, beaucoup de choses qui peuvent être faites pour "verrouiller" davantage l'accès, en fonction de la valeur des données - selinux, journalisation à distance, Shell limité, contraintes d'heure de la journée, notifications immédiates sur les connexions, surveillance active des journaux comme fail2ban [ en plus des restrictions de réseau que je considère comme non optionnelles] peuvent toutes faire partie d'une solution. Cela dit, si vous contrôlez simplement un système qui peut être détruit et recréé facilement, la plupart de ces mesures sont probablement exagérées.

N'oubliez pas que la sécurité est construite en couches. Pour obtenir l'accès à la racine, un compte doit passer par un certain nombre de couches. Le verrouillage de l'accès, les clés privées SSH, les pare-feu, les restrictions horaires [ et le principe du moindre accès, c'est-à-dire ne donner accès qu'à ce qui est nécessaire, pas plus, la journalisation, les sauvegardes ] devraient tous fonctionner ensemble dans le cadre d'une bonne sécurité.

Supplémentaire - Accès SUDO

Sudo est un mécanisme qui permet à un utilisateur ordinaire d'exécuter certaines commandes avec un accès élevé, et est assez flexible et varié dans sa portée. Bien qu'un résumé de sudo ne soit pas approprié ici (mais il est bien documenté si vous tapez man sudo dans la plupart des distributions, les étapes appropriées pourraient être -

  1. Modifier /etc/sudoers - La plupart des variantes de Linux ont un programme spécial pour faire cela, appelé "visudo", qui doit être exécuté en tant que root, et qui est à peu près équivalent à l'utilisation de l'éditeur système pour modifier /etc/sudoers (qui est une autre façon de le faire - bien que probablement peu connue).

  2. Ajouter/modifier les lignes appropriées pour permettre à un utilisateur donné de faire des choses particulières. Si, par exemple, vous vouliez qu'ils puissent monter des répertoires et sans avoir à entrer un mot de passe, vous entreriez une ligne comme :

    username    ALL=/sbin/mount NOPASSWD: ALL

Pour exécuter cette commande, l'utilisateur approprié devra exécuter quelque chose comme

  sudo mount /dev/xxx /path/to/mount

Vous pouvez lister plusieurs lignes pour plusieurs commandes, utiliser des groupes plutôt que des utilisations - sudoers est un sous-système assez flexible. Dans de nombreuses distributions, il est également possible d'ajouter des fichiers avec des commandes dans un sous-répertoire comme /etc/sudoers.d

2voto

harrymc Points 394411

Voici une réponse tirée du post Unix Stackexchange
Comment exécuter à distance une commande ssh une commande sudo sans mot de passe .

Cette méthode permet à l'administrateur du serveur d'autoriser votre compte à exécuter une commande comme sudo sans spécifier le mot de passe. La commande est probablement l'appel à votre script, et elle est seulement autorisée lorsqu'elle est exécutée sous votre compte. Comme la commande autorisée est entièrement spécifiée, y compris les arguments, je pense que cette méthode est assez sûre.

vous pouvez dire à sudo d'ignorer le mot de passe pour certaines commandes.

Par exemple, dans /etc/sudoers

archemar  ALL = (www-data) NOPASSWD: /bin/rm -rf /var/www/log/upload.*

cela me permet d'utiliser

sudo -u www-data /bin/rm -rf /var/www/log/upload.*

comme Archimar sans mot de passe.

Notez que

sudo -u www-data rm -rf /var/www/log/upload.*

ne fonctionnera pas (demandera un mot de passe) car rm diffèrent de /bin/rm .

Veillez à éditer /etc/sudoers en utilisant visudo commandement.

Une fois que vous aurez atteint un niveau avancé, vous souhaiterez peut-être avoir votre propre sudo fichiers dans /etc/sudoers.d .

1voto

brablc Points 1310

Ma configuration dans une situation similaire est la suivante /home/blesseduser/.ssh/authorized_keys :

no-port-forwarding,command="/usr/local/bin/audited-command" ssh-rsa AAAAB...

A l'intérieur de ce script, je fais un peu de nettoyage de SSH_ORIGINAL_COMMAND (plus quelques vérifications) et extraire la commande que l'utilisateur voulait exécuter. Toutes les commandes autorisées se trouvent dans users /home/blesseduser/bin en tant que liens symboliques vers /usr/local/bin/sudo-runner :

#!/bin/bash -e
sudo /usr/local/bin/$(basename $0) "$@"

Les liens symétriques sont générés par script à partir de l'adresse de l'utilisateur. sudoers dossier. Si aucune commande n'est présente, le contenu de son bin est répertorié. Si vous ne limitez pas le transfert de port, de mauvaises choses peuvent se produire.

1voto

dirdi Points 2838

Considérations générales

  • Lorsque vous utilisez SSH, authentification par mot de passe doit être évitée, c'est-à-dire que l /etc/ssh/sshd_config doit contenir les lignes suivantes :

    PermitRootLogin no
    PasswordAuthentication no
  • Cependant, si l'on doit - pour une raison quelconque - utiliser authentification par mot de passe il convient d'utiliser des outils établis, connus et testés, tels que les suivants sshpass . Ne vous lancez pas tout seul dans le maniement des mots de passe.

  • Si vous utilisez authentification par clé publique il n'y a pas de sens à protéger la clé privée par une phrase de passe, si la phrase de passe est à son tour stockée dans un fichier de configuration ou autre. Si un attaquant est capable d'obtenir un accès en lecture au système de fichiers pour voler le fichier de la clé privée, il sera également capable de voler le fichier de configuration.

  • Toutes les commandes qui peuvent être exécutées avec utilisateur doit être exécuté avec les privilèges utilisateur au lieu de racine privilèges.

  • Le langage de programmation utilisé ne sera pas pris en compte dans cette réponse, puisqu'il n'y a pas de différence entre le langage de programmation Python subprocess.call , Java java.lang.Runtime.exec ou un environnement subshell à l'intérieur d'un Shell Shell en matière de sécurité.

  • Le renforcement de l'hôte distant contre les attaquants externes par la configuration d'un pare-feu, la mise en place de systèmes IDS/IPS et autres ne sera pas non plus pris en compte, car il est hors de portée.

Cela dit, envisageons différents scénarios :

Commandes en cours d'exécution dont une Sous-ensemble fini Nécessite des privilèges root

Il faut utiliser un utilisateur distinct ( adduser --shell /bin/rbash --disabled-password remcmdexec créera un utilisateur avec un Shell restreint, ne pouvant pas faire des connexions locales mais seulement distantes, voir man adduser y man rbash ) en combinaison avec un sudoers qui permet à cet utilisateur de n'exécuter que l'ensemble limité de commandes nécessaires en tant que racine (voir man sudoers ) sur l'hôte distant :

# /etc/sudoers

remcmdexec ALL = (root:root) NOPASSWD: /usr/bin/systemctl reload some.service

Exiger un mot de passe pour exécuter ces commandes avec sudo n'a pas de sens, puisque la connexion locale a été désactivée ( --disabled-password ) et un attaquant qui a pu voler le fichier clé sera également capable de voler le mot de passe requis (voir la première section de la réponse).

El clés_autorisées doit contenir des restrictions supplémentaires pour empêcher, par exemple, le transfert de port, voir man sshd :

restrict ssh-rsa <BASE64-PUBKEY-REPRESENTATION> remcmdexec

Elle devrait en outre être détenue par racine et étant lisible mais non inscriptible par la remcmdexec pour empêcher la suppression des restrictions SSH :

$ ls -l /home/remcmdexec/.ssh/authorized_keys
-rw-r--r-- 1 root root 739 Sep  18 22:47 /home/remcmdexec/.ssh/authorized_keys

Invoquer, par exemple ssh remcmdexec@remhost sudo /usr/bin/systemctl reload some.service pour une commande qui nécessite racine les privilèges. Pour toutes les autres commandes, passez sudo .

Commandes en cours d'exécution dont une Sous-ensemble non fini mais approprié Nécessite des privilèges root

La même configuration que celle présentée dans la section précédente de la réponse peut être utilisée, mais l'option sudoers doit être adapté :

remcmdexec ALL = (ALL:ALL) NOPASSWD: ALL

C'est parce que remcmdexec doit enfin gagner racine les privilèges. Comprenez qu'un attaquant qui est capable de se connecter en tant que remcmdexec est maintenant en mesure de supprimer toutes les restrictions mises en place sur l'hôte distant, quelle que soit la complexité de la manière d'atteindre racine Les privilèges ont été conçus. Par conséquent, toutes ces restrictions sont futiles en ce qui concerne sécurité (Un attaquant volontaire). Cependant, elles ne sont pas futiles en ce qui concerne sécurité (Défaillances du système).

Exécution d'un Ensemble non fini de Commandes dont Tous Exiger les privilèges de la racine

Cela n'a plus de sens d'utiliser sudo . Au lieu de cela, connectez-vous en tant qu'utilisateur avec racine privilèges pour exécuter une commande : ssh root@remhost /usr/bin/somecmd

Par conséquent, la ligne suivante doit être présente au niveau de l'interface de l'utilisateur. /etc/ssh/sshd_config fichier :

PermitRootLogin prohibit-password

Cependant, gardez les restrictions à l'intérieur du clés_autorisées pour préserver certains éléments de base sécurité .

1voto

dirkt Points 15364

Voici une réponse concernant les considérations de sécurité, qui, je pense, n'ont pas été abordées dans les autres réponses.

Quelle est une bonne configuration qui permet l'exécution automatique d'une commande ou d'un script sur un serveur distant avec des privilèges de root en utilisant SSH ?

Il y a plusieurs parties à cela : permettre l'exécution d'un seul script ou d'une commande avec des privilèges élevés (root), et utiliser SSH. Ces éléments ne sont pas nécessairement dépendants.

  • Autoriser une connexion directe par root (PermitRootLogin) (et éventuellement forcer l'authentification par clé).

Cela permettra à n'importe qui d'avoir des privilèges complets de root (non limités à votre unique commande/script). Cela permettra également à quiconque d'essayer de s'introduire dans votre système à distance, en essayant les mots de passe, etc.

  • Configurer sudo pour ne pas exiger un mot de passe (drapeau NOPASSWD dans sudoers) et un TTY (drapeau requiretty).

Cela permettra à n'importe quel utilisateur d'avoir tous les privilèges de l'administrateur, à condition qu'il soit connecté. En termes de sécurité, ce n'est pas beaucoup mieux que d'autoriser la connexion de l'utilisateur root, bien qu'il y ait moins de tentatives automatisées de pénétrer dans les autres comptes d'utilisateurs.

  • Configuration de sudo pour permettre l'exécution de commandes/scripts spécifiques, lorsqu'on est authentifié avec une clé privée spécifique.

Je ne suis pas sûr de la manière dont cela pourrait être mis en œuvre - sudo ne sait rien des clés SSH, du moins les variantes de sudo que je connais.

Configurer sudo pour n'autoriser que l'exécution de commandes/scripts spécifiques est bien meilleur du point de vue de la sécurité (car plus restrictif).

  • Définir le propriétaire du script/commande comme root et définir la permission setuid.

Cela permettra à tout utilisateur d'exécuter ce script en tant que root. Vous ne pouvez pas restreindre cela à des utilisateurs particuliers, et les bits setuid ont leurs propres faiblesses de sécurité potentielles.


En fin de compte, je ne pense pas qu'il y ait un seul canonique Réponse : la meilleure solution dépend de votre situation et de vos besoins. Ainsi, comme pour tout ce qui touche à la sécurité, vous devez d'abord vous asseoir et définir vos besoins : Dans quelle mesure voulez-vous être permissif et flexible ? Quel est le cas d'utilisation réel ? Jusqu'à quel point avez-vous besoin d'ancrer le système ? Etc.

Cela dit, permettez-moi d'ajouter une alternative très restrictive que vous n'avez pas mentionnée :

Créez un compte utilisateur spécifique qui n'est utilisé que pour exécuter ce script/commande particulier. N'autorisez la connexion SSH de cet utilisateur qu'avec une paire de clés (désactivez les mots de passe). Configurez sudo pour permettre à cet utilisateur d'exécuter la commande particulière/script en tant que root.

Cela a les conséquences suivantes en matière de sécurité :

  • Les pirates externes ne peuvent pas craquer le mot de passe du compte spécifique en utilisant la force brute.

  • Toute personne ayant accès à ce compte ne pourra exécuter que l'unique script/commande.

  • Les autres utilisateurs n'obtiennent pas de privilèges élevés grâce à cette construction.

  • Aucune faiblesse de setuid.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X