Jak mogę bezpiecznie tworzyć i uzyskiwać dostęp do plików tymczasowych ze skryptów powłoki?

14

Przeczytałem, że przekierowanie danych wyjściowych do pliku o stałej nazwie /tmpmoże stanowić zagrożenie bezpieczeństwa, ponieważ jeśli atakujący (lub malkontent) zauważy, że plik /tmp/tmpfileformyscript.tmpjest tworzony po uruchomieniu skryptu (nawet jeśli nie ma on dostępu do odczytu skrypt), może na przykład utworzyć dowiązanie symboliczne, ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmpktóre spowoduje, że zniszczę .bashrcplik po uruchomieniu skryptu.

Zamiast tego mogę użyć czegoś takiego filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename".

Chciałbym jednak czasami użyć pliku tmp do buforowania, w którym to przypadku chciałbym wiedzieć, czy „tmpfile.tmp. *” Pasuje do czegoś, /tmpa jeśli tak, użyj tego pliku zamiast tworzyć nowy. Niestety, testo [ -f filename ]ile mi wiadomo, odpowiednik nie obsługuje globowania plików.

Zatem moje pytanie jest dwojakie:

  1. Jak mogę bezpiecznie utworzyć plik tymczasowy? Czy "predictablename.$RANDOM"możliwa jest do przyjęcia praktyka lub czy istnieje lepszy (bezpieczniejszy, łatwiejszy) sposób?
  2. Jak mogę łatwo uzyskać dostęp do pliku i / lub ustalić jego istnienie później, sprawdzając go predictablename?
Dzika karta
źródło

Odpowiedzi:

13

Użyj mktempnarzędzia, aby utworzyć plik tymczasowy o nieprzewidzianej nazwie. Nie jest standaryzowany przez POSIX, ale jest dostępny na * BSD oraz Linux.

> /tmp/predictable.$RANDOMnie jest dobrym wyborem, ponieważ jest w większości przewidywalny¹, co powoduje otwarcie skryptu na atak, w którym osoba atakująca może oszukać skrypt, aby nadpisał plik, do którego masz uprawnienia do zapisu, lub daje mu dostęp do pliku tymczasowego. Jest to niepewna tymczasowa luka w zabezpieczeniach plików . mktempnie ma tej luki, ponieważ tworzy plik bezpiecznie (nie zastąpi istniejącego pliku, nawet jeśli w grę wchodzą dowiązania symboliczne) i używa wystarczająco nieprzewidywalnej nazwy, aby uniknąć odmowy usługi.

Jeśli utworzenie jednego pliku tymczasowego i praca z nim nie jest wystarczająco dobra, utwórz katalog tymczasowy mktemp -di tam pracuj.

mktempdba również o użycie, $TMPDIRjeśli zmienna jest ustawiona, wracając do, /tmpjeśli jest nieuzbrojona.

Coraz więcej dystrybucji tworzy TMPDIRprywatny katalog, np. /run/1234/tmpGdzie 1234jest twój UID. Eliminuje to ryzyko tymczasowych luk w zabezpieczeniach plików, kosztem niemożności udostępniania plików tymczasowych między użytkownikami (co jest czasami przydatne, ale niezbyt często; /tmpjest nadal dostępne, po prostu nie TMPDIR).

Jeśli potrzebujesz odtwarzalnej nazwy pliku, utwórz plik o dobrze zdefiniowanej nazwie (bez losowego komponentu) w katalogu osobistym użytkownika. Nowoczesna konwencja to specyfikacja katalogu użytkowników XDG . Jeśli plik można usunąć bez powodowania utraty danych, użyj XDG_CACHE_HOMEzmiennej środowiskowej, domyślnie jest to ~/.cache. Prawdopodobnie powinieneś utworzyć podkatalog nazwany na podstawie swojej aplikacji i tam pracować.

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

¹ Nie tylko $RANDOMprzyjmuje 32767 możliwych wartości, ale łatwo jest przewidzieć, nawet nie próbując wielu wartości. Generator liczb losowych Basha to LCG obsadzony PID i czasem pierwszego użycia. Zsh jest platformą randobsadzoną czasem uruchamiania. ATT Ksh jest platformą randobsadzoną przez PID. Mksh's to LCG z bardziej złożonym, ale wciąż nie jakościowym zabezpieczeniem. Wszystkie z nich można przewidzieć w innym procesie z dość dużą szansą na sukces.

Gilles „SO- przestań być zły”
źródło
Właściwie to twoja dyskusja $TMPDIRi ~/.cachejest dokładnie tym, czego potrzebowałem. Po kilku dalszych myślach zdałem sobie sprawę, że jedynym powodem, dla którego chciałem to zrobić, /tmpbył podział na partycje - więc pamięć podręczna nie mogła zapełnić /homepartycji. Ale w tym przypadku użycia jest to kompletny problem, więc podkatalog ~/.cacheidealnie pasuje do moich potrzeb i pozwala uniknąć problemu z bezpieczeństwem.
Wildcard
mktempnie jest dostępny w systemie AIX ani w powłoce Git w systemie Windows. Wygląda na file.$RANDOM$RANDOMto, że jest to rozwiązanie przenośne. $RANDOM$RANDOMPowinno zwiększyć przestrzeń do 2 ^ 32, przy założeniu, atakujących losowe są one niezależne i nie słaby.
@jww Losowe wyniki Basha są słabe: jest to LCG, która jest tak przewidywalna, jak to tylko możliwe, a jednocześnie wystarczająca dla wielu aplikacji, które nie wymagają nieprzewidywalności.
Gilles „SO- przestań być zły”
9

mktemp został do tego zaprojektowany. Ze strony podręcznika:

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

mktemp utworzy plik lub zakończy działanie z niezerowym statusem wyjścia. Logiczne lub (||) zapewnia, że ​​skrypt zakończy działanie, jeśli mktemp nie będzie mógł utworzyć pliku. Po tym poleceniu możesz być pewien, że plik jest dostępny. Nie ma potrzeby sprawdzania tego ponownie. Jedyne, co może być konieczne do dodania, to oczyszczenie pliku na końcu skryptu.

I być może także wtedy, gdy skrypt zakończy się sygnałem. To, czy jest to konieczne, czy nie, należy do decyzji.

Oba można wykonać za pomocą trappolecenia.

Bram
źródło
Ach! To bardzo przydatne; to nie muszę dzwonić $RANDOM. Ale potem część druga mojego pytania - jak mogę uzyskać dostęp do tego pliku później lub sprawdzić, czy istnieje on już przy kolejnym uruchomieniu skryptu? (Aby wdrożyć bardzo prostą pamięć podręczną.)
Wildcard