Apakah selalu aman untuk menggunakan `eval echo`?

20

Penggunaan evalsering tidak dianjurkan karena memungkinkan eksekusi kode arbitrer. Namun, jika kita gunakan eval echo, maka sepertinya seluruh string akan menjadi argumen echosehingga harus aman. Apakah saya benar dalam hal ini?

Cyker
sumber
1
tidak selalu aman Anda bisa membungkus bom garpu atau rm jahat -fR *
μολὼν.λαβέ
Mungkin ini hanya eksperimen pikiran, tetapi jika Anda benar-benar berpikir untuk melakukan ini untuk melewatinya seperti beberapa argumen -n, Anda bisa melakukannya dengan variabel yang tidak dikutip seperti echo $argumentsatau jika $argumentsarray echo "${arguments[@]}". Menggunakan eval echoadalah sia-sia bahkan jika itu adalah aman.
JoL

Jawaban:

40

Contoh tandingan:

DANGEROUS=">foo"
eval echo $DANGEROUS

Argumen sewenang-wenang untuk echobisa melakukan sesuatu yang lebih jahat daripada membuat file yang disebut "foo".

Celada
sumber
6
Juga DANGEROUS="hello;ls":, untuk perintah sewenang-wenang menggantikan ls.
Kusalananda
2
Juga: DANGEROUS='$(ls)'(lebih banyak melarikan diri mungkin diperlukan).
wizzwizz4
Akan eval echo '"'"$DANGEROUS"'"'bekerja Tampaknya untuk goo.gl/L2pPQP
Ismael Miguel
@IsmaelMiguel Itu tidak berfungsi untuk contoh wizzwizz, Cyker, atau sorontar, atau untuk apa pun dengan tanda kutip ganda dalam string (misalnya DANGEROUS='">foo"').
Gordon Davisson
Menisik. Saya pikir saya menemukan sesuatu yang sedikit membantu
Ismael Miguel
26

@Celada telah memberikan jawaban yang sangat baik. Untuk menunjukkan evalitu benar-benar jahat, berikut ini sesuatu yang lebih jahat daripada membuat file bernama "foo" :

DANGEROUS='$(rm foo)'
eval echo "$DANGEROUS"

Dan tentu saja bisa ada sesuatu yang lebih jahat daripada sesuatu yang lebih jahat daripada membuat file yang disebut "foo" .

Cyker
sumber
8
+1 untuk menunjukkan bahwa mengutip variabel suka "$THIS"daripada hanya suka $THISsaja tidak membantu!
Celada
Mengirimkan sepasang kutipan tambahan sepertinya membantu. Sesuatu seperti eval echo '"'"$DANGEROUS"'"'. Cobalah di goo.gl/L2pPQP
Ismael Miguel
Sebenarnya, contoh Anda tidak lebih jahat dari itu >foo, karena "membuat file bernama 'foo'" belum tentu >foodemikian. Satu-satunya perbedaan nyata yang dimiliki contoh Anda adalah tidak meninggalkan file kosong. Isinya masih hilang.
flarn2006
12

Tidak, itu tidak selalu aman. Sebuah eval bisa menjalankan perintah apa pun.

Perintah yang aman, seperti ini (tanggal tidak dieksekusi karena berada di dalam tanda kutip tunggal):

$ echo '$(date)'
$(date)

Menjadi berbahaya jika digunakan dengan eval:

$ eval echo '$(date)'
Sat Dec 24 22:55:55 UTC 2016

Tentu saja, date bisa berupa perintah apa saja .

Salah satu cara untuk meningkatkan ini adalah dengan mengutip argumen untuk eval:

$ eval echo '\$(date)'
$(date)

Tetapi biasanya sulit untuk mengutip dengan benar dua kali ekspresi.

Dan menjadi tidak mungkin untuk mengontrol kutipan yang benar jika ekspresi dapat diatur oleh penyerang eksternal, seperti:

$ var='$(date);echo Hello!'
$ eval echo "$var"
Sat Dec 24 23:01:48 UTC 2016
Hello!
sorontar
sumber
1

Meskipun benar bahwa evalselalu perlu didekati dengan hati-hati, eval echokonstruksi tidak selalu sia-sia dan dapat digunakan dengan aman. Saya baru-baru ini membutuhkannya untuk mendapatkan beberapa ekspansi brace dievaluasi dalam urutan yang saya butuhkan.

bash melakukan beberapa ekspansi brace dari kiri ke kanan, jadi

xargs -I_ cat _/{11..15}/{8..5}.jpg

meluas ke

xargs -I_ cat _/11/8.jpg _/11/7.jpg _/11/6.jpg _/11/5.jpg _/12/8.jpg _/12/7.jpg _/12/6.jpg _/12/5.jpg _/13/8.jpg _/13/7.jpg _/13/6.jpg _/13/5.jpg _/14/8.jpg _/14/7.jpg _/14/6.jpg _/14/5.jpg _/15/8.jpg _/15/7.jpg _/15/6.jpg _/15/5.jpg

tapi saya perlu ekspansi brace kedua dilakukan pertama, menghasilkan

xargs -I_ cat _/11/8.jpg _/12/8.jpg _/13/8.jpg _/14/8.jpg _/15/8.jpg _/11/7.jpg _/12/7.jpg _/13/7.jpg _/14/7.jpg _/15/7.jpg _/11/6.jpg _/12/6.jpg _/13/6.jpg _/14/6.jpg _/15/6.jpg _/11/5.jpg _/12/5.jpg _/13/5.jpg _/14/5.jpg _/15/5.jpg

Yang terbaik yang bisa saya lakukan untuk melakukan itu adalah

xargs -I_ cat $(eval echo _/'{11..15}'/{8..5}.jpg)

Ini bekerja karena tanda kutip tunggal melindungi set kawat gigi pertama dari ekspansi selama penguraian evalbaris perintah, membiarkannya diperluas oleh subkulit yang dipanggil oleh eval.

Mungkin ada beberapa skema licik yang melibatkan ekspansi penjepit bersarang yang memungkinkan ini terjadi dalam satu langkah, tetapi jika ada saya terlalu tua dan bodoh untuk melihatnya. Ada juga cangkang selain bashyang memungkinkan cara yang lebih rapi untuk mencapai hal semacam ini. Namun bagaimanapun, penggunaan evalini aman karena argumennya adalah semua string tetap yang tidak mengandung ekspansi parameter.

flabdablet
sumber
Anda tidak perlu gema dan substitusi perintah di sini (yang juga memiliki ketergantungan pada $ IFS). Anda bisa melakukannyaeval xargs -I_ cat _/'{11..15}'/{8..5}.jpg
Stéphane Chazelas
Itu bekerja juga, tetapi itu membuat proses subshell menelurkan eval tetap di sekitar sampai proses xargs selesai; versi eval echo membuat subshell pergi sebelum xargs bahkan dimulai. Ini mungkin hanya penting bagi orang lain yang sama anal dengan saya tentang apa yang muncul dalam tampilan pohon htop dan set -x log :-)
flabdablet