Mengapa menggunakan tindakan '-execdir' tidak aman untuk direktori yang ada di PATH?

19

Mengapa tidak aman menggunakan kombinasi -execdirtindakan mencari saat menggunakan -execbukan?

Ketika saya menjalankan perintah di bawah ini saya menerima pesan prompt berikut:

/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)

Apa yang menyebabkan prompt ini muncul?

αғsнιη
sumber

Jawaban:

22

Anda bisa menjalankan program yang salah. Seseorang dapat membuat Anda menjalankan program mereka.

The -execdirtindakan menjalankan perintah Anda dari direktori yang berisi file (s) ditemukan. Ketika $PATHberisi jalur relatif, seperti .atau apa pun yang tidak dimulai/ , -execdirtidak aman karena direktori tempat file ditemukan (atau direktori lain yang diselesaikan relatif terhadapnya) juga bisa berisi executable dengan nama yang sama dengan yang Anda coba untuk berlari. Eksekusi yang berpotensi tidak dipercaya itu kemudian akan dijalankan.

Ini dapat dengan sengaja dieksploitasi oleh pengguna lain untuk menyebabkan Anda menjalankan program mereka, yang dapat menyebabkan kerusakan atau melanggar keamanan data, alih-alih program yang Anda coba jalankan. Atau, yang lebih jarang, itu hanya dapat mengakibatkan program yang salah dijalankan secara tidak sengaja, bahkan tanpa ada yang berusaha membuat masalah terjadi.

Jika segala sesuatu di Anda PATHvariabel lingkungan adalah path absolut, kesalahan ini seharusnya tidak terjadi, bahkan jika direktori yang Anda cari dan -execdiring dari yang terkandung dalam PATH. (Saya telah memeriksa apakah ini berfungsi.) Jika Anda yakin Anda tidak memiliki direktori relatif $PATHtetapi masih mendapatkan kesalahan ini, harap perbarui pertanyaan Anda dengan perincian termasuk output dari echo "$PATH".

Contoh nyata.

Sebagai contoh apa yang bisa salah, anggap:

  • Alice memiliki .di dalam dirinya $PATHkarena dia ingin dapat menjalankan program di direktori apa pun dia cdakan, tanpa repot-repot untuk mengawali nama mereka dengan ./.
  • Hawa frenemy Alice telah berbagi /home/eve/shareddengan Alice.
  • Alice ingin statistik (baris, kata, byte) pada .cfile yang telah dibagikan Eve dengannya.

Jadi Alice menjalankan:

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

Sayangnya untuk Alice, Eve telah membuat skripnya sendiri, menamainya wc, mengaturnya executable ( chmod +x), dan menempatkannya secara sembunyi-sembunyi di salah satu direktori di bawah /home/eve/shared. Script Eve terlihat seperti ini:

#!/bin/sh
/usr/bin/wc "$@"
do_evil    # Eve replaces this command with whatver evil she wishes to do

Jadi ketika Alice menggunakan finddengan -execdiruntuk menjalankan wcpada file yang Hawa telah bagikan, dan itu akan ke file dalam direktori yang sama dengan wcskrip kustom Hawa, Hawa wcberjalan - dengan semua hak istimewa Alice!

(Menjadi licik, Hawa telah membuat wcskripnya bertindak sebagai pembungkus untuk sistem wc, sehingga Alice bahkan tidak akan tahu ada yang tidak beres, yaitu yang do_evildijalankan. Namun, variasi yang lebih sederhana - dan juga lebih canggih - dimungkinkan. )

Bagaimana findmencegahnya?

findmencegah masalah keamanan ini terjadi dengan menolak untuk mengambil -execdirtindakan ketika $PATHberisi direktori relatif.

find menawarkan dua pesan diagnostik tergantung pada situasi spesifik.

  • Jika .ada di $PATH, maka (seperti yang Anda lihat) dikatakan:

    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)

    Mungkin memiliki pesan khusus untuk .kasus ini karena sangat umum.

  • Jika path relatif selain .--say, foo--appears di $PATHdan Anda menjalankan finddengan -execdir, ia mengatakan:

    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

Lebih baik tidak memiliki jalur relatif $PATHsama sekali.

Risiko memiliki .atau jalur relatif lain $PATHsecara khusus meningkat ketika menggunakan utilitas yang secara otomatis mengubah direktori, yang mengapa findtidak akan membiarkan Anda menggunakan -execdirdalam situasi ini.

Tetapi memiliki jalur relatif, khususnya ., dalam diri Anda $PATHsecara inheren berisiko dan sebaiknya dihindari. Perhatikan situasi fiksi dalam contoh di atas. Misalkan bukannya berjalan find, Alice hanya cds untuk ~eve/shared/blahdan berjalan wc *.c. Jika blahmengandung wcskrip Eve , do_eviljalankan sebagai Alice.

Eliah Kagan
sumber
2
Saya tidak tahu apakah Anda pernah mendengar ini sebelumnya bahwa Anda akan menjadi guru yang sangat baik :)
heemayl
5
@heemayl semua orang yang menulis hal-hal yang berguna di internet, sudah menjadi guru :-)
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
5

Ada banyak informasi terperinci di sini . Referensi hebat lainnya ada di sini . Mengutip dari referensi pertama:

Opsi -execdir adalah opsi yang lebih modern yang diperkenalkan di GNU find adalah upaya untuk membuat versi -exec yang lebih aman. Ini memiliki semantik yang sama dengan -exec dengan dua perangkat tambahan penting:

Selalu menyediakan path absolut ke file (menggunakan path relatif ke file sangat berbahaya jika -exec).

Selain memberikan path absolut, ia juga memeriksa variabel PATH untuk keamanan (jika ada titik dalam variabel PATH env, Anda dapat mengambil executable dari direktori yang salah)

Dari referensi kedua:

Tindakan '-execdir' menolak untuk melakukan apa pun jika direktori saat ini termasuk dalam variabel lingkungan $ PATH. Ini diperlukan karena '-execdir' menjalankan program di direktori yang sama tempat file ditemukan - secara umum, direktori seperti itu mungkin dapat ditulis oleh pengguna yang tidak dipercaya. Untuk alasan yang sama, '-execdir' tidak mengizinkan '{}' muncul atas nama perintah untuk dijalankan.

Ron
sumber
Bisakah Anda memperluas jawaban Anda mengapa "jika ada titik dalam variabel PATH env, Anda dapat mengambil yang dapat dieksekusi dari direktori yang salah" ? direktori yang salah ? Dan mengapa kita harus melakukan ini untuk membuatnya aman ? Terima kasih
αғsнιη
Saya harap tautan kedua dalam posting saya yang diperbarui akan menjawab pertanyaan Anda
Ron
3

Masalah utama adalah dengan nilai variabel sistem PATHyang berisi folder relatif di dalamnya, jadi untuk alasan keamanan findperintah tidak akan memungkinkan Anda untuk mengeksekusi binari, karena berpotensi ia dapat menjalankan program yang salah.


Jadi misalnya, jika Anda memiliki dir Anda saat ini di PATH Anda sesuai peringatan yang Anda dapatkan:

Direktori saat ini termasuk dalam variabel lingkungan PATH.

dan Anda akan menjalankan perintah Anda:

find . -type f -name 'partOfFileNames*' -execdir rm -- {} +

jika Anda memiliki skrip lokal ( rmdengan flag yang dapat dieksekusi) yang berisi rm -fr /di dalamnya, ia dapat menghapus semua file Anda, karena alih-alih mengeksekusi yang diharapkan /bin/rm, Anda akan mengeksekusi rmdari direktori saat ini, jadi mungkin itu bukan yang Anda inginkan.


Sebagai catatan, ini adalah masalah yang diketahui di Travis CI ( GH # 2811 ) ketika gagal dengan kesalahan:

find: Path relatif `./node_modules/.bin 'termasuk dalam variabel lingkungan PATH, yang tidak aman dalam kombinasi dengan aksi -execdir dari find. Harap hapus entri itu dari $ PATH

Jadi solusinya adalah menghapus entri yang terpengaruh dari variabel PATH, misalnya

PATH=`echo $PATH | sed -e 's/:\.\/node_modules\/\.bin//'`

seperti yang diusulkan oleh drogus . Kemajuan bug ini, bisa diikuti di GH # 4862 .


Ini adalah solusi untuk versi Bash:

PATH=${PATH//:\.\/node_modules\/\.bin/}

Contoh penggunaan (meneruskan filter PATHke perintah tertentu):

env PATH=${PATH//:\.\/node_modules\/\.bin/} find . -type f
kenorb
sumber
Inilah sedyang tampaknya menghapus semua hal yang findtidak disukainya: askubuntu.com/questions/621132/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
3

xargsdan bash -c cdsolusinya

Oke, saya menyerah:

find . -type f |
  xargs -I '{}' bash -c 'cd "$(dirname "{}")" && pwd && echo "$(basename "{}")"'

sed solusi

Sedikit kurang baik dari solusi sebelumnya:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" find . -execdir echo '{}' \;

Sebuah testcase:

[ "$(printf '/a/b::c/d:/e/f\n' | sed -E 's/(^|:)[^\/][^:]*//g')" = '/a/b:/e/f' ] || echo fail

Untuk renamesecara spesifik, Anda juga dapat bekerja dengan beberapa regex-fu Perl: /programming/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971

RTFS berharap hancur

Bagi mereka yang memiliki harapan bahwa ada cara untuk mengabaikan pendapat find, biarkan saya hancurkan dengan beberapa sumber:

Dari itu kita melihat bahwa tampaknya tidak ada cara untuk mematikan pemeriksaan jalan.

Aturan persis yang diperiksa adalah: gagal jika PATHkosong atau tidak dimulai /.

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber