Bagaimana saya bisa dengan aman membuat dan mengakses file temp dari skrip shell?

14

Saya telah membaca bahwa mengarahkan keluaran ke file nama tetap di /tmpdapat menjadi risiko keamanan, karena jika penyerang (atau tidak puas) memperhatikan bahwa file /tmp/tmpfileformyscript.tmpdibuat ketika saya menjalankan skrip saya (bahkan jika dia tidak memiliki akses baca ke saya script), misalnya dia dapat membuat symlink ln -s ~wildcard/.bashrc /tmp/tmpfileformyscript.tmpyang akan menyebabkan saya menghancurkan .bashrcfile saya ketika saya menjalankan script saya.

Jadi sebagai gantinya saya bisa menggunakan sesuatu seperti filename="tmpfile.tmp.$RANDOM" ; echo outputtext > "$filename".

Namun, saya ingin menggunakan file tmp untuk caching kadang-kadang, dalam hal ini saya ingin tahu apakah "tmpfile.tmp. *" Cocok dengan apa pun di dalam /tmpdan jika demikian, gunakan file itu daripada membuat yang baru. Sayangnya testdan yang setara [ -f filename ]tidak mendukung globbing file sejauh yang saya tahu.

Jadi pertanyaan saya ada dua:

  1. Bagaimana saya bisa dengan aman membuat tempfile? Apakah "predictablename.$RANDOM"praktik yang dapat diterima atau ada cara yang lebih baik (lebih aman, lebih mudah)?
  2. Bagaimana saya dapat dengan mudah mengakses file dan / atau membangun keberadaannya nanti dengan memeriksa predictablename?
Wildcard
sumber

Jawaban:

13

Gunakan mktemputilitas untuk membuat file sementara dengan nama yang tidak dapat diprediksi. Ini tidak distandarisasi oleh POSIX, tetapi tersedia di * BSD dan juga Linux.

> /tmp/predictable.$RANDOMbukanlah pilihan yang baik karena sebagian besar dapat diprediksi¹, yang membuka skrip Anda untuk serangan di mana penyerang dapat menipu skrip Anda untuk menimpa file yang Anda miliki akses tulisnya, atau memberi mereka akses ke file sementara. Ini adalah kerentanan file sementara tidak aman . mktemptidak memiliki kerentanan ini karena membuat file dengan aman (tidak akan menimpa file yang sudah ada, bahkan jika tautan simbolis terlibat) dan menggunakan nama yang cukup tidak terduga untuk menghindari penolakan layanan.

Jika membuat satu file sementara dan bekerja dengannya tidak cukup baik, buat direktori sementara dengan mktemp -d, dan bekerja di sana.

mktempjuga berhati-hati menggunakan $TMPDIRjika variabel diatur, kembali ke /tmpjika tidak disetel.

Semakin banyak distribusi yang disetel TMPDIRmenjadi direktori pribadi, mis. Di /run/1234/tmpmana 1234UID Anda. Ini menghilangkan risiko kerentanan file sementara, dengan biaya tidak lagi dapat berbagi file sementara antara pengguna (yang kadang-kadang berguna, tetapi tidak terlalu sering; /tmpmasih tersedia, hanya saja tidak TMPDIR).

Jika Anda memerlukan nama file yang dapat direproduksi, maka buat file dengan nama yang jelas (tanpa komponen acak) di bawah direktori home pengguna. Konvensi modern adalah spesifikasi direktori pengguna XDG . Jika file dapat dihapus tanpa menyebabkan kehilangan data, gunakan XDG_CACHE_HOMEvariabel lingkungan, default ke ~/.cache. Anda mungkin harus membuat subdirektori bernama setelah aplikasi Anda dan bekerja di sana.

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

¹ Tidak hanya $RANDOMmembutuhkan 32767 nilai yang mungkin, tetapi juga mudah diprediksi tanpa mencoba banyak nilai. Generator angka acak Bash adalah LCG yang diunggulkan oleh PID dan waktu penggunaan pertama. Zsh's adalah platform yang randdiunggulkan oleh waktu startup. ATT Ksh's adalah platform yang randdiunggulkan oleh PID. Mksh's adalah LCG dengan seed yang lebih kompleks, tetapi masih belum berkualitas keamanan. Semuanya dapat diprediksi oleh proses lain dengan peluang keberhasilan yang cukup besar.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
Sebenarnya diskusi Anda tentang $TMPDIRdan ~/.cachepersis apa yang saya butuhkan. Setelah beberapa pemikiran lebih lanjut, saya menyadari bahwa satu-satunya alasan saya menginginkannya /tmpadalah mempartisi — sehingga cache tidak dapat mengisi /homepartisi. Tetapi untuk use case ini benar-benar non-isu lengkap, jadi subdirektori ~/.cachesesuai dengan kebutuhan saya dengan sempurna dan menghindari masalah keamanan.
Wildcard
mktemptidak tersedia pada AIX atau Git shell pada Windows. Sepertinya file.$RANDOM$RANDOMadalah solusi portabel. The $RANDOM$RANDOMharus meningkatkan ruang untuk 2 ^ 32, dengan asumsi Bash hasil random yang independen dan tidak lemah.
@jww Hasil acak Bash lemah: ini adalah LCG, yang dapat diprediksi dan cukup baik untuk banyak aplikasi yang tidak memerlukan ketidakpastian.
Gilles 'SANGAT berhenti menjadi jahat'
9

mktemp dirancang untuk ini. Dari halaman manual:

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

mktemp akan membuat file atau keluar dengan status keluar yang tidak nol. Logical or (||) memastikan bahwa skrip akan keluar jika mktemp tidak dapat membuat file. Setelah perintah ini, Anda dapat memastikan bahwa file tersebut tersedia. Tidak perlu memeriksanya lagi. Satu-satunya hal yang perlu Anda tambahkan adalah pembersihan file di akhir skrip Anda.

Dan mungkin juga saat skrip diakhiri oleh sinyal. Apakah itu perlu atau tidak adalah sesuatu yang harus Anda putuskan.

Keduanya bisa dilakukan menggunakan trapperintah.

Bram
sumber
Ah! Itu sangat berguna; maka saya tidak perlu menelepon $RANDOM. Tetapi kemudian bagian 2 dari pertanyaan saya — bagaimana saya bisa mengakses file itu nanti atau mengecek apakah file itu sudah ada pada skrip berikutnya? (Untuk menerapkan cache yang sangat sederhana.)
Wildcard