Por que o uso da ação '-execdir' é inseguro para o diretório que está no PATH?


19

Por que é inseguro usar a combinação de -execdiração de encontrar enquanto o uso -execnão é?

Quando estou executando o comando abaixo, recebo a seguinte mensagem de prompt:

/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)

O que pode ter causado esse prompt aparecer?

Respostas:


22

Você pode executar o programa errado. Alguém poderia fazer você executar o programa deles.

A -execdiração executa seu comando no diretório que contém os arquivos encontrados. Quando $PATHcontém caminhos relativos, como .ou qualquer coisa que não comece/ , -execdiré inseguro porque um diretório em que um arquivo é encontrado (ou outro diretório resolvido em relação a ele) também pode conter um executável com o mesmo nome que você está tentando para correr. Esse executável potencialmente não confiável seria executado.

Isso pode ser deliberadamente explorado por outro usuário para fazer com que você execute o programa dele, o que pode causar danos ou violar a segurança dos dados, em vez do programa que você está tentando executar. Ou, com menos frequência, isso pode resultar simplesmente na execução inadvertida do programa errado, mesmo sem que ninguém tente fazer o problema acontecer.

Se tudo em sua PATHvariável de ambiente é um caminho absoluto, este erro não deve ocorrer, mesmo que o diretório que você está pesquisando e -execdiring de está contido no PATH. (Verifiquei se isso funciona.) Se você acredita que não possui nenhum diretório relativo, $PATHmas ainda está recebendo esse erro, atualize sua pergunta com detalhes, incluindo a saída de echo "$PATH".

Um exemplo concreto.

Como um exemplo do que poderia dar errado, suponha:

  • Alice tem .nela $PATHporque quer ser capaz de executar programas em qualquer diretório que deseje cd, sem se preocupar em acrescentar seus nomes ./.
  • Eve frenemy de Alice compartilhou /home/eve/sharedcom Alice.
  • Alice deseja estatísticas (linhas, palavras, bytes) nos .carquivos que Eve compartilhou com ela.

Então Alice corre:

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

Infelizmente para Alice, Eve criou seu próprio script, nomeou-o wc, definiu-o como executável ( chmod +x) e o colocou clandestinamente em um dos diretórios abaixo /home/eve/shared. O script de Eve é assim:

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

Então, quando Alice usa findcom -execdirpara executar wcnos arquivos que Eve compartilhou, e chega aos arquivos no mesmo diretório que o wcscript personalizado de Eve, ela é wcexecutada - com todos os privilégios de Alice!

(Sendo esperta, Eve fez seu wcscript atuar como um invólucro para o sistema wc, para que Alice nem saiba que algo deu errado, isto é, do_evilfoi executado. No entanto, variações mais simples - e também mais sofisticadas - são possíveis. )

Como findevita isso.

findevita que esse problema de segurança ocorra ao recusar a -execdiração quando $PATHcontém um diretório relativo.

find oferece duas mensagens de diagnóstico, dependendo da situação específica.

  • Se .estiver dentro $PATH, então (como você viu) diz:

    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)

    Provavelmente tem uma mensagem especial para o .caso, pois é especialmente comum.

  • Se um caminho relativo que não .--say, foo--appears em $PATHe você corre findcom -execdir, ele diz:

    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

É melhor não ter caminhos relativos $PATH.

O risco de ter .ou outros caminhos relativos $PATHé especialmente aumentado ao usar um utilitário que altera automaticamente o diretório, e é por isso findque não o deixa usar -execdirnessa situação.

Mas ter caminhos relativos, especialmente .no seu, $PATHé inerentemente arriscado e é realmente melhor evitado de qualquer maneira. Considere a situação fictícia no exemplo acima. Suponha que, em vez de correr find, Alice simplesmente cd~eve/shared/blahe corra wc *.c. Se blahcontém o wcscript de Eve , do_evilé executado como Alice.


2
Eu não sei se você já ouviu isso antes, que você seria um professor muito bom :) #
214 heemayl

5
@heemayl todos os que escrevem coisas úteis na net, já são professores :-)
Ciro Santilli 13 改造 中心 法轮功 六四

5

Há uma informação muito detalhada aqui . Outra excelente referência está aqui . Para citar a primeira referência:

A opção -execdir é uma opção mais moderna introduzida no GNU. É uma tentativa de criar uma versão mais segura do -exec. Tem a mesma semântica que -exec, com dois aprimoramentos importantes:

Ele sempre fornece caminho absoluto para o arquivo (usar o caminho relativo para um arquivo é realmente perigoso no caso de -exec).

Além de fornecer um caminho absoluto, ele também verifica a segurança da variável PATH (se houver um ponto presente na variável env PATH, você pode obter o executável no diretório errado)

Da segunda referência:

A ação '-execdir' se recusa a fazer qualquer coisa se o diretório atual estiver incluído na variável de ambiente $ PATH. Isso é necessário porque '-execdir' executa programas no mesmo diretório em que encontra arquivos - em geral, esse diretório pode ser gravável por usuários não confiáveis. Por razões semelhantes, '-execdir' não permite que '{}' apareça no nome do comando a ser executado.


Você pode, por favor, estender sua resposta por que "se o ponto está presente na variável env PATH, você pode pegar o executável no diretório errado" ? qual diretório errado ? E por que temos que fazer isso para torná-lo seguro ? Obrigado
αғsнιη

Espero que o segundo link no meu post atualizados irá responder à sua pergunta
Ron

3

O principal problema está no valor da variável do sistema PATHque contém pastas relativas, portanto, por razões de segurançafind comando não permitirá a execução de binários, porque potencialmente ele pode executar programas errados.


Então, por exemplo, se você tem o seu diretório atual no seu PATH conforme o aviso que você recebe:

O diretório atual está incluído na variável de ambiente PATH.

e você executará seu comando:

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

caso você tenha um script local ( rmcom sinalizadores executáveis) rm -fr /, ele poderá remover todos os seus arquivos, porque, em vez de executar o esperado /bin/rm, você executarárm partir do diretório atual, portanto, provavelmente não é o que você queria.


Como observação lateral, esse é um problema conhecido no Travis CI ( GH # 2811 ) quando falha com o erro:

find: O caminho relativo `./node_modules/.bin 'está incluído na variável de ambiente PATH, que é insegura em combinação com a ação -execdir de find. Remova essa entrada de $ PATH

Portanto, a solução é remover a entrada afetada da variável PATH, por exemplo

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

como proposto por drogus . O progresso deste bug pode ser acompanhado em GH # 4862 .


Aqui está a solução alternativa da versão Bash:

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

Exemplo de uso (passando filtrado PATHpara um comando específico):

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

Aqui está um sedque parece remover todas as coisas findque não gosta: askubuntu.com/questions/621132/…
Ciro Santilli Enviado em 13/01

3

xargse bash -c cdsolução alternativa

Ok eu desisto:

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

sed Gambiarra

Um pouco menos agradável que a solução alternativa anterior:

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

Um testcase:

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

Para renameespecificamente, você também pode solucionar com algum Perl regex-fu: /programming/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971

RTFS espera esmagamento

Para aqueles que têm esperanças de que exista uma maneira de ignorar finda opinião de opinião, deixe-me esmagar isso com alguma fonte:

A partir disso, vemos que parece não haver maneira de desativar a verificação do caminho.

A regra exata que ele verifica é: falha se PATHestiver vazia ou não começar /.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.