Почему действие '-execdir' небезопасно для каталога, который находится в PATH?

19

Почему небезопасно использовать комбинацию -execdirдействия find во время использования -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)

Что может вызвать появление этого приглашения?

αғsнιη
источник

Ответы:

22

Вы можете запустить не ту программу. Кто-то может заставить вас запустить их программу.

-execdirДействие запускает вашу команду из каталога , который содержит файл (ы). Когда $PATHсодержит относительные пути, такие как .или что-либо, с чего не начинается/ , -execdirнебезопасно, потому что каталог, в котором находится файл (или другой каталог, разрешенный относительно него), также может содержать исполняемый файл с тем же именем, что и тот, который вы пытаетесь бежать. Этот потенциально ненадежный исполняемый файл затем будет запущен.

Это может быть намеренно использовано другим пользователем, чтобы заставить вас запустить его программу, которая может нанести вред или нарушить безопасность данных, вместо программы, которую вы пытаетесь запустить. Или, реже, это может привести к непреднамеренному запуску неправильной программы, даже если никто не попытается решить проблему.

Если все в вашей PATHпеременной окружения это абсолютный путь, эта ошибка не должна возникать, даже если каталог , который вы ищете , и -execdirИНГ от это содержится в PATH. (Я проверил, что это работает.) Если вы считаете, что у вас нет относительных каталогов, $PATHно вы все еще получаете эту ошибку, пожалуйста, обновите ваш вопрос с подробностями, включая вывод echo "$PATH".

Конкретный пример.

В качестве примера того, что может пойти не так, предположим:

  • У Алисы есть .она, $PATHпотому что она хочет иметь возможность запускать программы в любом каталоге, к которому она хочет cd, не удосуживаясь добавить их имена ./.
  • Ева в ярости Ева поделилась /home/eve/sharedс Алисой.
  • Алиса хочет получить статистику (строки, слова, байты) в .cфайлах, которыми Ева поделилась с ней.

Итак, Алиса бежит:

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

К сожалению для Алисы, Ева создала свой собственный сценарий, назвал его wc, установил его executeable ( 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)

    Это, вероятно, имеет специальное сообщение для .случая, поскольку это особенно распространено.

  • Если относительный путь, кроме .--say, foo--appears в $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запускается как Алиса.

Элия ​​Каган
источник
2
Я не знаю, слышал ли ты это раньше, что ты стал бы очень хорошим учителем :)
Heemayl
5
@heemayl Все те, кто пишет полезные вещи в сети, уже являются учителями :-)
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件
5

Существует гораздо более подробная информация здесь . Еще одна отличная ссылка здесь . Цитировать из первой ссылки:

Опция -execdir - более современная опция, введенная в GNU find - попытка создать более безопасную версию -exec. Он имеет ту же семантику, что и -exec, с двумя важными улучшениями:

Он всегда предоставляет абсолютный путь к файлу (использование относительного пути к файлу действительно опасно в случае -exec).

Помимо обеспечения абсолютного пути, он также проверяет переменную PATH на безопасность (если точка присутствует в переменной PATH env, вы можете забрать исполняемый файл из неправильного каталога)

Из второй ссылки:

Действие '-execdir' отказывается что-либо делать, если текущий каталог включен в переменную среды $ PATH. Это необходимо, поскольку «-execdir» запускает программы в том же каталоге, в котором он находит файлы - в общем случае такой каталог может быть доступен для записи недоверенным пользователям. По тем же причинам «-execdir» не позволяет отображать «{}» в названии команды для запуска.

Рон
источник
Не могли бы вы расширить свой ответ, почему «если точка присутствует в переменной PATH env, вы можете забрать исполняемый файл из неправильного каталога» ? какой неправильный каталог ? И почему мы должны сделать это для обеспечения безопасности ? Спасибо
αғsнιη
Я надеюсь, что вторая ссылка в моем обновленном посте ответит на ваш вопрос
Рон
3

Основная проблема заключается в значении системной переменной, 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
kenorb
источник
Вот sedчто, кажется, удаляет все, что findне нравится: askubuntu.com/questions/621132/…
Сиро Сантилли lli 新疆 中心 法轮功 六四 事件
3

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: /programming/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971

RTFS надеюсь, сокрушительный

Для тех, у кого есть надежда на то, что существует способ игнорировать findсамоуверенность, позвольте мне опустить это с некоторым источником:

Из этого мы видим, что, похоже, нет способа отключить проверку пути.

Точное правило, которое он проверяет: сбой, если PATHлибо пусто, либо не начинается с /.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник