Existe-t-il un shell qui vérifie que le code est signé?

19

Je déconnais avec PowerShell cette semaine et j'ai découvert que vous devez signer vos scripts pour qu'ils puissent être exécutés. Existe-t-il des fonctionnalités sécurisées similaires sous Linux qui empêchent l'exécution des scripts bash?

La seule fonctionnalité similaire à celle-ci, à ma connaissance, est celle de SSH nécessitant une certaine clé.

leeand00
la source
2
Cela ressemble un peu à une solution ad hoc pour la signature de packages pour moi. Je ne sais pas si Windows a un package cryptographique signant comme Linux.
Wildcard
6
@ leeand00 Un script est un cas particulier d'un progiciel et je ne vois aucun intérêt à distinguer ce cas.
Gilles 'SO- arrête d'être méchant'
2
Le mécanisme que j'aime le plus est la façon dont ChromeOS procède: placer le seul système de fichiers non signalé noexecsur une partition en lecture seule sur un périphérique bloc signé dm-verity.
Charles Duffy
1
source.android.com/security/verifiedboot parle de l'adoption par Android de cette fonctionnalité (initialement ChromeOS).
Charles Duffy
1
Vous pouvez considérer bash comme un tas de commandes qui peuvent être saisies manuellement dans l'interface de ligne de commande. Quel est l'intérêt de restreindre les scripts quand vous pouvez quand même taper le contenu en ligne de commande?
Ding-Yi Chen

Réponses:

11

Si vous bloquez la capacité des utilisateurs à exécuter des scripts via, sudovous pouvez utiliser la digestfonctionnalité.
Vous pouvez spécifier le hachage d'un script / exécutable dans sudoerslequel sera vérifié sudoavant d'être exécuté. Donc, bien que ce ne soit pas la même chose que la signature, cela vous donne une garantie de base que le script n'a au moins pas été modifié sans que les sudoers soient également modifiés.

Si un nom de commande est précédé d'un Digest_Spec, la commande ne correspondra correctement que si elle peut être vérifiée à l'aide du résumé SHA-2 spécifié. Cela peut être utile dans les situations où l'utilisateur invoquant sudo a un accès en écriture à la commande ou à son répertoire parent. Les formats de résumé suivants sont pris en charge: sha224, sha256, sha384 et sha512. La chaîne peut être spécifiée au format hexadécimal ou base64 (base64 est plus compact). Il existe plusieurs utilitaires capables de générer des résumés SHA-2 au format hexadécimal tels que openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

http://www.sudo.ws/man/1.8.13/sudoers.man.html

batfastad
la source
Cela me retiendra jusqu'à ce que je lise SE Linux et que je le fasse correctement.
leeand00
13

Oui et non.

La distribution de logiciels Linux fonctionne quelque peu différemment de la distribution de logiciels Windows. Dans le monde Linux (non intégré), la principale méthode de distribution de logiciels est via une distribution (Ubuntu, Debian, RHEL, Fedora, Arch, etc.). Toutes les principales distributions signent systématiquement leurs packages depuis environ une décennie.

Lorsque le logiciel est distribué indépendamment, c'est au vendeur de décider comment il expédiera son logiciel. Les bons fournisseurs fournissent des sources de packages compatibles avec les principales distributions (il n'y a pas de mécanisme de distribution unifié pour tout Linux: la distribution de logiciels est l'un des principaux points de différenciation entre les distributions) et qui sont signées avec la clé du vendeur. Les distributions Linux agissent rarement en tant qu'autorité de signature pour les fournisseurs tiers (Canonical le fait avec les partenaires Ubuntu, mais cela couvre très peu de fournisseurs), et je pense que toutes les distributions principales utilisent le Web de confiance PGP plutôt que l'infrastructure de clé publique TLS, donc c'est à l'utilisateur de déterminer s'il veut faire confiance à une clé.

Il n'y a pas de mécanisme spécial qui distingue les packages logiciels consistant en un seul script des packages logiciels constitués d'un exécutable natif, d'un fichier de données ou de plusieurs fichiers. Aucune vérification de signature n'est intégrée à aucun interpréteur de script commun, car la vérification d'un progiciel est une préoccupation complètement orthogonale lors de l'exécution d'un script.

Je pense que Windows annote les fichiers avec leur origine et nécessite une confirmation de l'utilisateur pour exécuter un fichier dont l'origine est «téléchargée» plutôt que «locale». Linux n'a pas vraiment de mécanisme similaire. La chose la plus proche est la permission d'exécution: un fichier téléchargé n'a pas de permission d'exécution, l'utilisateur doit l'activer explicitement ( chmod +xsur la ligne de commande, ou l'action équivalente dans un gestionnaire de fichiers).

Gilles 'SO- arrête d'être méchant'
la source
2
FWIW, en plus de ce PowerShell peut être configuré (par les paramètres de stratégie) pour exécuter uniquement des scripts signés et cette stratégie peut être configurée de sorte que tous les scripts doivent être signés ou uniquement des scripts "d'origine distante", ou aucun script. Il fonctionne mieux dans un environnement AD avec une gestion des clés et une gestion centrale des politiques. Il peut être contourné :-)
Stephen Harris
@StephenHarris Eh bien oui, si vous le définissez pour contourner ...
leeand00
@ leeand00 - Apparemment, le codage base64 fonctionne également comme un contournement, mais je ne sais pas s'il a été fermé dans les nouvelles versions de PowerShell.
Stephen Harris
1
@ leeand00 - voir darkoperator.com/blog/2013/3/5/… pour vous amuser :-) Basiquement, passez le script encodé en base64 comme paramètre sur la ligne de commande :-) Assez facile à emballer!
Stephen Harris
2
SeLinux annote les fichiers avec leur origine. C'est l'un de ses locaux principaux.
loa_in_
10

Linux ne permet pas de limiter l'exécution des scripts bash basés sur des signatures numériques.

Il y a du travail sur l'authentification des exécutables binaires. Voir https://lwn.net/Articles/488906/ pour plus d'informations.

Quentin Fennessy
la source
Votez pour une réponse directe sans suggérer de solution de contournement.
user394
8

En un mot, "non".

Linux ne fait pas vraiment de différence entre les exécutables et les scripts; le #!début est une façon de dire au noyau quel programme à exécuter pour évaluer l'entrée , mais ce n'est pas le seul moyen d' un script peut être exécuté.

Ainsi, par exemple, si j'ai un script

$ cat x
#!/bin/sh 
echo hello

Ensuite, je peux l'exécuter avec la commande

$ ./x

Cela amènera le noyau à essayer de l'exécuter, à repérer #!puis à exécuter à la /bin/sh xplace.

Cependant, je pourrais également exécuter l'une de ces variantes:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

ou même

. ./x

Donc, même si le noyau a essayé d'imposer la signature au niveau de la execcouche, nous pouvons contourner cela en exécutant uniquement l'interpréteur avec le script comme paramètre.

Cela signifie que le code de signature devrait être dans l'interpréteur lui-même. Et qu'est-ce qui empêcherait un utilisateur de compiler sa propre copie d'un shell sans le code d'application de la signature?

La solution standard à cela n'est pas d'utiliser la signature, mais d'utiliser des contrôles d'accès obligatoires (MAC), tels que SELinux. Avec les systèmes MAC, vous pouvez spécifier exactement ce que chaque utilisateur est autorisé à exécuter et à transposer les couches. Ainsi, par exemple, vous pouvez dire "les utilisateurs normaux peuvent exécuter n'importe quoi, mais le serveur Web et les processus CGI ne peuvent accéder qu'aux éléments du /var/httpdrépertoire; tout le reste est rejeté".

Stephen Harris
la source
1
This means that signing code would have to be in the interpreter itself. And what would stop a user from compiling their own copy of a shell without the signing enforcement code?Ne pas permettre l' exécution de toute executables non signés le ferait, si l'utilisateur ne possède pas la clé de signature. Il existe déjà divers projets * nix pour cela.
alzee
2

Les distributions Linux ont généralement gnupg . Il me semble que tout ce que vous voulez est un simple wrapper bash qui vérifie une signature gpg détachée par rapport au script d'argument et ne procède à l'exécution du script que si la vérification réussit:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
PSkocik
la source
La seule chose que cela ne présente pas est l'exécution d'un script que quelqu'un vient de
créer
2

La contre-question qui vient immédiatement à l'esprit est "Pourquoi voudriez-vous jamais empêcher les utilisateurs d'exécuter les programmes qu'ils ont écrits? " Plusieurs possibilités existent:

  1. Il est littéralement impossible de détecter qui a créé le code en premier lieu. Le propriétaire du fichier de script est celui qui a réellement enregistré le contenu de ce fichier, quelle que soit sa provenance. L'application d'une signature n'est donc qu'un substitut compliqué d'une boîte de dialogue de confirmation: "Êtes-vous sûr de vouloir le faire?" Sous Linux, une partie de ce problème est résolue de manière transparente avec des packages signés et atténuée par le fait que les utilisateurs ont un accès limité par défaut. L'utilisateur doit également savoir que l'exécution du code d'autrui peut être dangereuse *.
  2. Dans la même veine, la signature d'un script est une opération beaucoup plus complexe que l'enregistrement d'un fichier. Dans le meilleur des cas, cela incite l'utilisateur à réaliser qu'il effectue une action similaire à la signature d'un document et doit inspecter ce qu'il dit avant de continuer. Très probablement, il garantit simplement un niveau très minimal de compétence technique de la part de l'utilisateur pour être autorisé à exécuter le script. Dans le pire des cas, cela démontre une volonté de sauter à travers une longue série de cerceaux pour exécuter ce qu'ils voulaient. La compétence technique est supposée sous Linux *.
  3. Il est plus probable que les gens détectent un code manifestement malveillant lorsqu'ils tapent / collent une série de commandes sur leur ligne de commande. Les extraits de texte en clair destinés à être copiés et collés sont généralement plus petits que la série de commandes nécessaires pour faire quelque chose de bien néfaste. L'utilisateur peut également copier et coller soigneusement chaque ligne séparément, en comprenant ce qui se passe au fur et à mesure. Avec un script, il est possible que l'utilisateur n'ait jamais regardé le code du tout. Cela peut être une application utile de scripts signés, au prix trop complaisant de la complaisance après la 12e fois que vous devez le faire.

* Cela devient probablement de moins en moins vrai à mesure que de plus en plus de personnes utilisent Linux

l0b0
la source
1

La raison pour laquelle les systèmes ont évolué différemment est que Linux a l'attribut de fichier "exec" et Windows utilise des extensions de fichier pour déterminer l'exécutabilité.

Ainsi, sous Windows, il est facile d'inciter l'utilisateur à télécharger un fichier avec une extension ".exe", ".bat", ".scr", qui sera masquée par défaut . Double-cliquer sur ce fichier vous donnerait l'exécution de code arbitraire. Par conséquent, un grand mécanisme de suivi de l'origine et de signature des exécutables / scripts a été créé pour atténuer ce risque.

Sous Linux, vous pouvez peut-être obtenir un fichier pour l'utilisateur, mais vous ne pouvez pas facilement forcer le bit «exec» à être défini. De plus, il est possible de créer des systèmes de fichiers entiers «noexec».

Dans tous les cas, vous pouvez exécuter un script explicitement en appelant l'interpréteur. Vous pouvez même créer des scripts shell lors de l'exécution et les diriger vers "sh", ou exécuter "sh -c".

pjc50
la source
0

Par coutume, de nombreux programmes d'archivage ne conservent pas le bit d'exécution sur les fichiers contenus. Cela rend impossible l'exécution d'exécutables arbitraires. Enfin presque.

Le fait est que ce qui a été décrit dans une autre réponse selon lequel le manque de bits d'exécution ne vous empêche pas de passer directement un tel script à bash. Bien que l'on bashpuisse soutenir que la plupart de ces scripts sont des scripts, le shebang peut spécifier n'importe quel programme comme interprète. Cela signifie qu'il appartient à l'utilisateur d'exécuter l'interpréteur approprié s'il décide d'ignorer la sémantique exécutable.

Bien que ce ne soit pas grand-chose, cela couvre à peu près la prévention de l'exécution d'exécutables non fiables sur * nixes avec uniquement le noyau et le shell .

Comme je l'ai mentionné dans l'un des commentaires, il existe une autre couche de protection - SeLinux- qui suit l'origine des fichiers en fonction d'un ensemble de règles. Une configuration SeLinuxne permettrait pas par exemple à root d'exécuter un exécutable avec un ensemble de bits exécutables téléchargé depuis Internet, même si vous copiez et déplacez le fichier. On peut ajouter une règle selon laquelle de tels fichiers ne peuvent être exécutés que via un autre binaire qui vérifierait la signature, contrairement à ce que vous avez mentionné dans votre question.

Donc, en fin de compte, c'est une question de configuration des outils couramment préinstallés, et la réponse est oui .

loa_in_
la source
de nombreux programmes d'archivage ne conservent pas le bit d'exécution sur les fichiers contenus . eh bien, c'est une sorte de handicap lorsque vous voulez réellement l'utiliser pour l'archivage. Heureusement tar ne conserver Execute peu.
pjc50
Vous devez utiliser tar -p source
loa_in_
-p, --preserve-permissions, --same-permissionssignifie extraire des informations sur les autorisations de fichiers (par défaut pour le superutilisateur)
loa_in_
Non, vous n'avez PAS besoin de -p. Je vois ce que dit la page de manuel, mais ce n'est pas ce qui se passe. touch permtest; chmod +x permtest; tar cf permtest.tar.gz permtest; rm permtest; tar xf permtest.tar.gz; ls -l permtest- c'est exécutable ici, et je ne suis pas root.
domen
J'essaierai alors d'améliorer ma réponse.
loa_in_