web-dev-qa-db-fra.com

Pourquoi l'utilisation de l'action '-execdir' n'est-elle pas sécurisée pour le répertoire qui se trouve dans PATH?

Pourquoi ne pas utiliser la combinaison de l'action -execdir find en utilisant -exec non?

Lorsque j'exécute la commande ci-dessous, le message d'invite suivant s'affiche:

/path/to/currentDir/$ find . -type f -name 'partOfFileNames*' -execdir rm -- {} +

find: The current directory is included in the PATH environment variable, which is insecure 
in combination with the -execdir action of find.  Please remove the current directory 
from your $PATH (that is, remove "." or leading or trailing colons)

Qu'est-ce qui a pu faire apparaître cette invite?

18
αғsнιη

Vous pourriez exécuter le mauvais programme. Quelqu'un pourrait vous faire exécuter son programme.

L'action -execdir exécute votre commande à partir du répertoire contenant le ou les fichiers trouvés. Lorsque $PATH contient des chemins relatifs, tels que . ou tout ce qui ne commence pas par /, -execdir n'est pas sécurisé car un répertoire dans lequel un fichier est trouvé (ou un autre répertoire résolu par rapport à celui-ci) pourrait également contenir un exécutable du même nom que celui que vous essayez d’exécuter. Ce fichier exécutable potentiellement non fiable serait alors exécuté.

Cela pourrait être délibérément exploité par un autre utilisateur pour vous faire exécuter son programme, ce qui pourrait être dommageable ou violer la sécurité des données, au lieu du programme que vous essayez d'exécuter. Ou, moins souvent, le mauvais programme pourrait être exécuté par inadvertance, même sans que personne ne tente de résoudre le problème.

Si tout ce qui se trouve dans votre variable d’environnement PATH correspond à un chemin absolu, cette erreur ne doit pas se produire, même si le répertoire dans lequel vous recherchez et où -execdiring est est contenu dans PATH. (J'ai vérifié que cela fonctionne.) Si vous pensez que vous n'avez pas de répertoires relatifs dans $PATH mais que vous rencontrez toujours cette erreur, veuillez mettre à jour votre question avec les détails, y compris la sortie de echo "$PATH".

Un exemple concret.

Comme exemple de ce qui pourrait mal tourner, supposons:

  • Alice a . dans son $PATH car elle veut pouvoir exécuter des programmes dans le répertoire dans lequel elle est cd 'd, sans avoir à ajouter leur nom avec ./.
  • La frenemy d'Alice Eve a partagé /home/eve/shared avec Alice.
  • Alice veut des statistiques (lignes, mots, octets) sur les fichiers .c que Eve a partagés avec elle.

Alors Alice court:

find ~eve/shared -name \*.c -execdir wc {} \;

Malheureusement pour Alice, Eve a créé son propre script, l'a nommée wc, l'a défini comme exécutable (chmod +x) et l'a placé clandestinement dans l'un des répertoires sous /home/eve/shared. Le script d'Eve ressemble à ceci:

#!/bin/sh
/usr/bin/wc "$@"
do_evil    # Eve replaces this command with whatver evil she wishes to do

Ainsi, lorsque Alice utilise find avec -execdir pour exécuter wc sur les fichiers partagés par Eve, et que les fichiers du répertoire se trouvent dans le même répertoire que le script personnalisé wc d'Eve, Eve wc s'exécute - avec tous les privilèges d'Alice!

(Étant rusée, Eve a fait en sorte que son script wc serve de wrapper pour le système wc, de sorte que Alice ne saura même pas que quelque chose s'est mal passé, c'est-à-dire que do_evil a été exécuté. Cependant, des variations plus simples et plus sophistiquées sont possibles.)

Comment find l'empêche.

find évite ce problème de sécurité en refusant d'effectuer l'action -execdir lorsque $PATH contient un répertoire relatif.

find offre deux messages de diagnostic en fonction de la situation spécifique.

  • Si . est dans $PATH, alors (comme vous l'avez vu), il est écrit:

    find: The current directory is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove the current directory from your $PATH (that is, remove "." or leading or trailing colons)

    Il contient probablement un message spécial pour le cas ., car il est particulièrement courant.

  • Si un chemin relatif autre que .-- dit, foo - apparaît dans $PATH et que vous exécutez find avec -execdir, il indique:

    find: The relative path `foo' is included in the PATH environment variable, which is insecure in combination with the -execdir action of find. Please remove that entry from $PATH

Il vaut mieux ne pas avoir de chemins relatifs dans $PATH.

Le risque d'avoir . ou d'autres chemins relatifs dans $PATH est particulièrement accru lorsque vous utilisez un utilitaire qui modifie automatiquement le répertoire. C'est pourquoi find ne vous laissera pas utiliser -execdir dans cette situation.

Mais avoir des chemins relatifs, en particulier ., dans votre $PATH est intrinsèquement risqué et il vaut mieux éviter de toute façon. Considérez la situation fictive dans l'exemple ci-dessus. Supposons qu'au lieu d'exécuter find, Alice mette simplement cds à ~eve/shared/blah et exécute wc *.c. Si blah contient le script wc d'Eve, do_evil s'exécute en tant que Alice.

20
Eliah Kagan

Il y a beaucoup d'informations détaillées ici . Une autre excellente référence est ici . Pour citer la première référence:

L'option -execdir est une option plus moderne introduite dans GNU. Find est une tentative de création d'une version plus sûre de -exec. Il a la même sémantique que -exec avec deux améliorations importantes:

Il fournit toujours le chemin absolu du fichier (utiliser un chemin relatif vers un fichier est vraiment dangereux en cas de -exec).

En plus de fournir un chemin absolu, il vérifie également la sécurité de la variable PATH (si dot est présent dans la variable env. PATH, vous pouvez extraire le fichier exécutable à partir du mauvais répertoire).

De la deuxième référence:

L’action ‘-execdir’ refuse de faire quoi que ce soit si le répertoire en cours est inclus dans la variable d’environnement $ PATH. Cela est nécessaire car ‘-execdir’ exécute des programmes dans le même répertoire où se trouvent les fichiers. En général, un tel répertoire peut être accessible en écriture à des utilisateurs non fiables. Pour des raisons similaires, "-execdir" ne permet pas à "{}" d'apparaître dans le nom de la commande à exécuter.

5
Ron

Le problème principal concerne la valeur de la variable système PATHqui contient des dossiers relatifs. Ainsi, pour des raisons de sécurité, la commande findne vous permettra pas d’exécuter des fichiers binaires, car elle pourrait éventuellement exécuter de mauvais programmes.


Ainsi, par exemple, si vous avez votre répertoire actuel dans votre variable PATH conformément à l’avertissement, vous obtenez:

Le répertoire en cours est inclus dans la variable d’environnement PATH.

et vous exécuterez votre commande:

find . -type f -name 'partOfFileNames*' -execdir rm -- {} +

si vous avez un script local (rmavec des indicateurs exécutables) contenant rm -fr /, il peut supprimer tous vos fichiers, car au lieu d'exécuter le /bin/rm attendu, vous exécuterez rmà partir du répertoire en cours, ce qui signifie que ce n'est probablement pas ce que vous vouliez .


En remarque, c'est un problème connu dans Travis CI ( GH # 2811 ) lorsqu'il échoue avec l'erreur:

find: le chemin relatif `./node_modules/.bin 'est inclus dans la variable d'environnement PATH, qui n'est pas sécurisée en combinaison avec l'action -execdir de find. Veuillez supprimer cette entrée de $ PATH

La solution consiste donc à supprimer l’entrée concernée de la variable PATH, par exemple.

PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'`

tel que proposé par drogus . La progression de ce bogue peut être suivie à partir de GH # 4862 .


Voici la solution de contournement de la version Bash:

PATH=${PATH//:\.\/node_modules\/\.bin/}

Exemple d'utilisation (passage de PATHfiltré à une commande spécifique):

env PATH=${PATH//:\.\/node_modules\/\.bin/} find . -type f
3
kenorb

xargs et bash -c cd solution de contournement

OK, j'abandonne:

find . -type f |
  xargs -I '{}' bash -c 'cd "$(dirname "{}")" && pwd && echo "$(basename "{}")"'

sed solution de contournement

Un peu moins sympa que la solution précédente:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" find . -execdir echo '{}' \;

Un test case:

[ "$(printf '/a/b::c/d:/e/f\n' | sed -E 's/(^|:)[^\/][^:]*//g')" = '/a/b:/e/f' ] || echo fail

Pour rename en particulier, vous pouvez également contourner certains Perl regex-fu: https://stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in- linux/54163971 # 54163971

RTFS espère écraser

Pour ceux qui espèrent qu’il existe un moyen d’ignorer l’opinion exprimée par find, laissez-moi l’écraser avec une source:

À partir de là, nous constatons qu’il semble impossible de désactiver la vérification du chemin.

La règle exacte à vérifier est la suivante: échec si la PATH est vide ou ne commence pas par /.