Почему действие '-execdir' небезопасно для каталога, который находится в PATH?
Почему небезопасно использовать комбинацию -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)
Что может вызвать появление этого приглашения?
4 ответа
Вы можете запустить не ту программу. Кто-то может заставить вас запустить их программу.
-execdir
action запускает вашу команду из каталога, в котором находятся найденные файлы. когда $PATH
содержит относительные пути, такие как .
или что-нибудь, что не начинается с /
, -execdir
небезопасен, поскольку каталог, в котором находится файл (или другой каталог, разрешенный относительно него), также может содержать исполняемый файл с тем же именем, что и файл, который вы пытаетесь запустить. Этот потенциально ненадежный исполняемый файл затем будет запущен.
Это может быть намеренно использовано другим пользователем, чтобы заставить вас запустить его программу, которая может нанести вред или нарушить безопасность данных, вместо программы, которую вы пытаетесь запустить. Или, реже, это может привести к непреднамеренному запуску неправильной программы, даже если никто не попытается решить проблему.
Если все в вашем PATH
Переменная окружения является абсолютным путем, эта ошибка не должна возникать, даже если каталог, который вы ищете, и -execdir
Из этого содержится в PATH
, (Я проверил, что это работает.) Если вы считаете, что у вас нет относительных каталогов в $PATH
но все еще получаете эту ошибку, пожалуйста, обновите ваш вопрос с деталями, включая вывод echo "$PATH"
,
Конкретный пример.
В качестве примера того, что может пойти не так, предположим:
- Алиса имеет
.
в ее$PATH
потому что она хочет иметь возможность запускать программы в любом каталоге онаcd
не потрудившись приписать их имена./
, - Ева Алиса поделилась
/home/eve/shared
с Алисой - Алиса хочет статистику (строки, слова, байты) на
.c
файлы, которыми Ева поделилась с ней.
Итак, Алиса бежит:
find ~eve/shared -name \*.c -execdir wc {} \;
К сожалению для Алисы, Ева создала свой собственный сценарий, назвал его wc
установите его исполняемым (chmod +x
) и поместил его тайно в один из каталогов под /home/eve/shared
, Сценарий Евы выглядит так:
#!/bin/sh
/usr/bin/wc "$@"
do_evil # Eve replaces this command with whatver evil she wishes to do
Поэтому, когда Алиса использует find
с -execdir
бежать wc
в файлах, которыми поделилась Ева, и он попадает в файлы в том же каталоге, что и пользовательские файлы Евы wc
сценарий Евы wc
работает - со всеми привилегиями Алисы!
(Будучи хитрым, Ева сделала ее wc
скрипт действует как обёртка для системы wc
Алиса даже не узнает, что что-то пошло не так, т.е. 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
Алиса просто cd
с ~eve/shared/blah
и работает wc *.c
, Если blah
содержит Еву wc
сценарий, do_evil
работает как Алиса.
Здесь очень подробная информация. Еще одна отличная ссылка здесь. Цитировать из первой ссылки:
Опция -execdir - более современная опция, введенная в GNU find - попытка создать более безопасную версию -exec. Он имеет ту же семантику, что и -exec, с двумя важными улучшениями:
Он всегда предоставляет абсолютный путь к файлу (использование относительного пути к файлу действительно опасно в случае -exec).
Помимо обеспечения абсолютного пути, он также проверяет переменную PATH на безопасность (если точка присутствует в переменной PATH env, вы можете забрать исполняемый файл из неправильного каталога)
Из второй ссылки:
Действие '-execdir' отказывается что-либо делать, если текущий каталог включен в переменную среды $PATH. Это необходимо, потому что "-execdir" запускает программы в том же каталоге, в котором он находит файлы - в общем, такой каталог может быть доступен для записи ненадежным пользователям. По тем же причинам "-execdir" не позволяет отображать "{}" в названии команды для запуска.
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: https://stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971
RTFS надеюсь, что сокрушительный
Для тех, кто надеется, что существует способ игнорировать find
Самоуверенность, позвольте мне раздавить это из некоторого источника:
- https://git.savannah.gnu.org/cgit/findutils.git/tree/find/parser.c?h=v4.6.0#n2847
- https://git.savannah.gnu.org/cgit/findutils.git/tree/find/parser.c?h=v4.6.0#n2944
Из этого мы видим, что, похоже, нет способа отключить проверку пути.
Точное правило, которое он проверяет: сбой, если PATH
либо пусто, либо не начинается с /
,
Основная проблема со значением системной переменной PATH
который содержит относительные папки в нем, поэтому по соображениям безопасности find
Команда не позволит вам выполнять двоичные файлы, потому что потенциально она может выполнять неправильные программы.
Так, например, если у вас есть текущая директория в вашей переменной PATH согласно предупреждению, которое вы получаете:
Текущий каталог включен в переменную окружения PATH.
и вы запустите свою команду:
find . -type f -name 'partOfFileNames*' -execdir rm -- {} +
на случай если у вас будет локальный скрипт (rm
с исполняемыми флагами), содержащий rm -fr /
в нем он может удалить все ваши файлы, потому что вместо ожидаемого выполнения /bin/rm
исполнишь rm
из текущего каталога, так что, вероятно, это не то, что вы хотели.
В качестве примечания, это известная проблема в Travis CI ( GH # 2811), когда происходит сбой с ошибкой:
find: Относительный путь `./node_modules/.bin'включен в переменную среды PATH, которая небезопасна в сочетании с действием -execdir команды find. Пожалуйста, удалите эту запись из $PATH
Таким образом, решение состоит в том, чтобы удалить затронутую запись из переменной PATH, например
PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'`
как предложил Дрогус. Прогресс этой ошибки, можно следить на GH # 4862.
Вот обходное решение Bash версии:
PATH=${PATH//:\.\/node_modules\/\.bin/}
Пример использования (прохождение фильтруется PATH
к конкретной команде):
env PATH=${PATH//:\.\/node_modules\/\.bin/} find . -type f
Обходной путь - передать пользовательский 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))
мы вычисляем, где находится наша команда для запуска.