Почему небезопасно использовать комбинацию -execdir
действия поиска при использовании -exec
- нет?
Когда я запускаю указанную ниже команду, я получаю следующее сообщение:
/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)
Что может вызвать появление этого приглашения?
-execdir
действие выполняет Вашу команду из каталога, который содержит найденный файл (файлы). Когда $PATH
содержит относительные пути, такой как .
или что-либо, что не запускается с /
, -execdir
небезопасно, потому что каталог, где файл найден (или другой каталог, разрешенный относительно него), мог также содержать исполняемый файл того же имени как то, которое Вы пытаетесь выполнить. Тот потенциально недоверяемый исполняемый файл затем выполнить вместо этого.
Это могло быть сознательно использовано другим пользователем, чтобы заставить Вас запускать их программу, которая могла бы нанести ущерб или нарушить безопасность данных вместо программы, которую Вы пытаетесь запустить. Или менее часто это могло бы просто привести к неправильной программе, непреднамеренно выполняемой, даже ни с кем пытающимся заставить проблему произойти.
Если все в Вашем PATH
переменная среды является полным путем, эта ошибка не должна происходить, даже если каталог Вы ищете и -execdir
луг от содержится в PATH
. (Я проверил, что это работает.), Если Вы верите, у Вас нет относительных каталогов в $PATH
но все еще получают эту ошибку, обновите свой вопрос с деталями включая вывод echo "$PATH"
.
Как пример того, что могло пойти не так, как надо, предположите:
.
в ней $PATH
потому что она хочет смочь запустить программы в любом каталоге, она cd
'd к, не потрудившись предварительно ожидать их имена с ./
./home/eve/shared
с Alice..c
файлы Eve совместно использовали с нею.Так выполнения Alice:
find ~eve/shared -name \*.c -execdir wc {} \;
К сожалению для Alice Канун создал ее собственный сценарий, названный им wc
, установите его исполняемый файл (chmod +x
), и помещенный это тайно в один из каталогов под /home/eve/shared
. Сценарий кануна похож на это:
#!/bin/sh
/usr/bin/wc "$@"
do_evil # Eve replaces this command with whatver evil she wishes to do
Таким образом, когда Alice использует find
с -execdir
работать wc
на файлах Eve совместно использовала, и это добирается до файлов в том же каталоге как пользовательская Eve wc
сценарий, Eve wc
выполнения - со всеми полномочиями Alice!
(бывший лукавым, Eve сделала ее wc
действие сценария как обертка для системы wc
, таким образом, Alice не будет даже знать, что что-то пошло не так, как надо, т.е. это do_evil
был выполнен. Однако более простой - и также более сложный - изменения возможны.)
find
предотвращает это.find
предотвращает эту проблему безопасности, отказываясь брать -execdir
действие, когда $PATH
содержит относительный каталог.
find
предложения два сообщения диагностики в зависимости от определенной ситуации.
Если .
находится в $PATH
, затем (как Вы видели) это говорит:
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)
Это, вероятно, имеет специальное сообщение для .
случай, поскольку это особенно распространено.
Если относительный путь кроме .
- скажите, foo
- появляется в $PATH
и Вы работаете find
с -execdir
, это говорит:
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
$PATH
вообще.Риск наличия .
или другие относительные пути в $PATH
особенно усилен при использовании утилиты, которая автоматически изменяет каталог, который является почему find
не позволит Вам использовать -execdir
в этой ситуации.
Но имея относительные пути, особенно .
, в Вашем $PATH
по сути опасно и действительно лучше всего избегается так или иначе. Рассмотрите вымышленную ситуацию в примере выше. Предположим вместо выполнения find
, Alice просто cd
s к ~eve/shared/blah
и выполнения wc *.c
. Если blah
содержит Eve wc
сценарий, do_evil
выполнения как Alice.
Существует много подробной информации здесь . Другая превосходная ссылка здесь . Заключить в кавычки из первой ссылки:
опция-execdir является более современной опцией, представленной в находке GNU, попытка создать более безопасную версию - должностное лицо. Это имеет то же, семантическое как - должностное лицо с двумя важными улучшениями:
Это всегда обеспечивает, полный путь в файл (использующий относительный путь для файла действительно опасно в случае - должностное лицо).
В дополнение к обеспечению полного пути это также проверяет переменную ПУТИ на безопасность (если точка присутствует в переменной ENV ПУТИ, Вы можете исполняемый файл погрузки из неправильного каталога)
Из второй ссылки:
†-execdir’ действие отказывается делать что-либо, если текущий каталог включен в переменную среды $PATH. Это необходимо, потому что †-execdir’ запускает программы в том же каталоге, в котором он находит файлы †“в целом, такой каталог мог бы быть перезаписываем недоверяемыми пользователями. По подобным причинам †-execdir’ не позволяет †{} ’, казаться, от имени команды быть выполненным.
Основная проблема со значением системной переменной PATH
который содержит относительные папки в нем, таким образом, из соображений безопасности find
команда не позволит Вам выполнять двоичные файлы, потому что потенциально она может выполнить неправильные программы.
Так, например, если у Вас есть свой текущий dir в Вашем ПУТИ согласно предупреждению, которое Вы получаете:
Текущий каталог включен в переменную окружения PATH.
и Вы выполните свою команду:
find . -type f -name 'partOfFileNames*' -execdir rm -- {} +
в случае, если у Вас будет локальный сценарий (rm
с исполняемыми флагами) содержащий rm -fr /
в нем он может удалить все Ваши файлы, потому что вместо того, чтобы выполниться ожидал /bin/rm
, Вы выполнитесь rm
от текущего dir так вероятно, это не то, что Вы хотели.
Как примечание стороны, это известно проблема в Travis CI (GH № 2811), когда это перестало работать с ошибкой:
найдите: относительный путь './node_modules/.bin' включен в переменную окружения PATH, которая небезопасна в сочетании с-execdir действием находки. Удалите ту запись из $PATH
Таким образом, решение состоит в том, чтобы удалить затронутую запись из переменной ПУТИ, например.
PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'`
как предложено drogus. Прогресс этой ошибки, может сопровождаться в № 4862 GH.
Вот обходное решение версии Bash:
PATH=${PATH//:\.\/node_modules\/\.bin/}
Использование в качестве примера (передающий фильтрованный PATH
к определенной команде):
env PATH=${PATH//:\.\/node_modules\/\.bin/} find . -type f
xargs
и bash -c cd
обходное решение
хорошо, я сдаюсь:
find . -type f |
xargs -I '{}' bash -c 'cd "$(dirname "{}")" && pwd && echo "$(basename "{}")"'
sed
обходное решение
Немного менее хороший, чем предыдущее обходное решение:
PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" find . -execdir echo '{}' \;
тестовый сценарий А:
[ "$(printf '/a/b::c/d:/e/f\n' | sed -E 's/(^|:)[^\/][^:]*//g')" = '/a/b:/e/f' ] || echo fail
Для rename
а именно, можно также работать вокруг с некоторым Perl regex-fu: https://надежда stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971
RTFS, сокрушительная
Для тех, у кого есть надежды, что там существует способ проигнорировать find
самоуверенность, позвольте мне сокрушить это с некоторым источником:
От этого, мы видим, что там, кажется, не способ выключить проверку пути.
точное правило, которое это проверяет: перестали работать, если эти PATH
или пусто или не запускается с /
.
Временное решение - передать пользовательский ПУТЬ перед командой, например
PATH=/usr/bin find . -type f -name 'partOfFileNames*' -execdir echo rm -- {} +
Вышеупомянутый обходной путь предотвратит загрузку глобального $ PATH
, но нашего собственного.
Вот еще один пример (более гибкий), предполагающий, что мы хотим запустить команду cat
:
PATH=$(dirname $(which find)):$(dirname $(which cat)) find /etc -name hosts -execdir cat {} ';'
или:
PATH=$(dirname $(which cat find) | paste -sd:) find ...
, запустив $ (dirname $ (which cat))
мы вычисляем, где находится наша команда для запуска.