Как я могу безопасно создавать и получать доступ к временным файлам из сценариев оболочки?

14

Я читал, что перенаправление вывода в файл с фиксированным именем в /tmpможет быть угрозой безопасности, потому что, если злоумышленник (или недовольный) замечает, что файл /tmp/tmpfileformyscript.tmpсоздается, когда я запускаю свой скрипт (даже если у него нет доступа на чтение к моему скрипт), например, он может создать символическую ссылку, ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmpкоторая заставит меня уничтожить .bashrcфайл при запуске скрипта.

Так что вместо этого я могу использовать что-то вроде filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename".

Тем не менее, я хотел бы иногда использовать tmp-файл для кэширования, и в этом случае я хотел бы знать, соответствует ли tmpfile.tmp. * Что-нибудь в /tmpэтом файле, и если да, то использовать этот файл, а не создавать новый. К сожалению, testи эквивалент [ -f filename ]не поддерживает глобализацию файлов, насколько я могу судить.

Таким образом, мой вопрос состоит из двух частей:

  1. Как я могу безопасно создать временный файл? Это "predictablename.$RANDOM"приемлемая практика или есть лучший (более безопасный, простой) способ?
  2. Как я могу легко получить доступ к файлу и / или установить его существование позже, проверяя predictablename?
Wildcard
источник

Ответы:

13

Используйте mktempутилиту для создания временного файла с непредсказуемым именем. Он не стандартизирован POSIX, но доступен на * BSD и Linux.

> /tmp/predictable.$RANDOMэто не лучший выбор, потому что он в основном предсказуемый », который открывает ваш сценарий для атаки, где злоумышленник может обмануть ваш сценарий, перезаписав файл, к которому у вас есть права на запись, или предоставив им доступ к временному файлу. Это небезопасная временная уязвимость файла . mktempне имеет этой уязвимости, потому что создает файл безопасно (он не будет перезаписывать существующий файл, даже если задействованы символические ссылки) и использует достаточно непредсказуемое имя, чтобы избежать отказа в обслуживании.

Если создать один временный файл и работать с ним недостаточно хорошо, создайте временный каталог mktemp -dи работайте там.

mktempтакже заботится о том, чтобы использовать, $TMPDIRесли переменная установлена, возвращаясь к, /tmpесли она не установлена.

Все больше и больше дистрибутивов создаются TMPDIRкак частные каталоги, например, /run/1234/tmpгде1234 находится ваш UID. Это исключает риск временных уязвимостей файлов за счет того, что они больше не могут обмениваться временными файлами между пользователями (что иногда полезно, но не очень часто; /tmpвсе еще доступно, просто нет TMPDIR).

Если вам нужно воспроизводимое имя файла, создайте файл с четко определенным именем (без случайного компонента) в домашнем каталоге пользователя. Современное соглашение - спецификация каталога пользователя XDG . Если файл может быть удален без потери данных, используйте XDG_CACHE_HOMEпеременную окружения по умолчанию ~/.cache. Вам, вероятно, следует создать подкаталог с именем вашего приложения и работать там.

CACHE_DIR="${XDG_CACHE_HOME:-"$HOME/.cache"}"/Wildcard-scripts
[ -d "$CACHE_DIR" ] || mkdir -p -- "$CACHE_DIR"
CACHE_FILE="$CACHE_DIR/tmpfileformyscript"

¹ Мало того, что он $RANDOMпринимает только 32767 возможных значений, но его легко предсказать, даже не пытаясь использовать много значений. Генератор случайных чисел Bash представляет собой LCG, засеянный PID и временем первого использования. Zsh - это платформа, которую randсеют по времени запуска. ATT Ksh - это платформа, засеянная randPID. Mksh's - это LCG с более сложным, но все еще не обеспеченным качеством семенем. Все они могут быть предсказаны другим процессом с довольно большим шансом на успех.

Жиль "ТАК - перестань быть злым"
источник
На самом деле ваше обсуждение $TMPDIRи ~/.cacheэто именно то, что мне нужно. После некоторых дальнейших размышлений я понял, что единственная причина, по которой я хотел этого, - это /tmpразбиение на разделы - чтобы кеш не мог заполнить /homeраздел. Но для этого варианта использования это действительно не проблема, поэтому подкаталог полностью ~/.cacheсоответствует моим потребностям и позволяет избежать проблем с безопасностью.
Подстановочный
mktempнедоступно в AIX или в оболочке Git в Windows. Похоже, file.$RANDOM$RANDOMэто портативное решение. $RANDOM$RANDOMДолжно увеличить пространство до 2 ^ 32, предполагая Баш случайных результаты являются независимыми и не слабыми.
@jww Случайные результаты Bash слабые: это LCG, который настолько же предсказуем, насколько он возможен, и в то же время достаточно хорош для многих приложений, которые не требуют непредсказуемости.
Жиль "ТАК - перестань быть злым"
9

mktemp был разработан для этого. Со страницы руководства:

TMPFILE=`mktemp /tmp/example.XXXXXXXXXX` || exit 1
echo "program output" >> $TMPFILE

mktemp создаст файл или выйдет с ненулевым статусом выхода. Логическое или (||) гарантирует, что скрипт завершится, если mktemp не сможет создать файл. После этой команды вы можете быть уверены, что файл доступен. Нет необходимости проверять это снова. Единственное, что вам может понадобиться добавить - это очистка файла в конце вашего скрипта.

И, возможно, также, когда сценарий завершается сигналом. Нужно это или нет - это то, что вы должны решить.

И то, и другое можно сделать с помощью trapкоманды.

Брэм
источник
Ах! Это очень полезно; тогда мне не нужно звонить $RANDOM. Но затем часть 2 моего вопроса - как я могу получить доступ к этому файлу позже или проверить, существует ли он уже при последующем запуске сценария? (Для реализации очень простого кэша.)
Wildcard