Mengapa fitur mirip eval dianggap jahat, berbeda dengan fitur yang mungkin berbahaya lainnya?

51

Sebagian besar bahasa modern (yang entah bagaimana ditafsirkan) memiliki semacam fungsi eval . Fungsi semacam itu mengeksekusi kode bahasa yang arbitrer, sebagian besar waktu berlalu sebagai argumen utama sebagai string (bahasa yang berbeda dapat menambahkan lebih banyak fitur ke fungsi eval).

Saya memahami pengguna tidak boleh diizinkan untuk menjalankan fungsi ini ( sunting yaitu mengambil input arbitrase langsung atau tidak langsung dari pengguna arbitrer untuk diteruskan eval), terutama dengan perangkat lunak sisi server, karena mereka dapat memaksa proses untuk mengeksekusi kode berbahaya. Dengan cara itu, tutorial dan komunitas memberi tahu kami untuk tidak menggunakan eval. Namun, ada beberapa kali eval berguna dan digunakan:

  • Aturan akses khusus ke elemen perangkat lunak (IIRC OpenERP memiliki objek ir.ruleyang dapat menggunakan kode python dinamis).
  • Perhitungan dan / atau kriteria khusus (OpenERP memiliki bidang seperti itu untuk memungkinkan perhitungan kode khusus).
  • Parser laporan OpenERP (ya saya tahu saya membuat Anda takut dengan hal-hal OpenERP ... tapi itu adalah contoh utama yang saya miliki).
  • Coding efek mantra di beberapa game RPG.

Jadi mereka memiliki penggunaan yang baik, selama mereka digunakan dengan benar. Keuntungan utama adalah bahwa fitur memungkinkan admin untuk menulis kode khusus tanpa harus membuat lebih banyak file dan memasukkannya (meskipun sebagian besar kerangka kerja menggunakan fitur eval juga memiliki cara untuk menentukan file, modul, paket, ... untuk membaca dari).

Namun, eval adalah kejahatan dalam budaya populer. Hal-hal seperti membobol sistem Anda datang ke pikiran.

Namun, ada fungsi lain yang bisa berbahaya jika entah bagaimana diakses oleh pengguna: memutuskan tautan, membaca, menulis (semantik file), alokasi memori dan aritmatika pointer, akses model database (bahkan jika tidak mempertimbangkan kasus SQL-injeksi).

Jadi, pada dasarnya, sebagian besar waktu ketika kode apa pun tidak ditulis dengan benar atau tidak ditonton dengan benar (sumber daya, pengguna, lingkungan, ...), kode tersebut jahat dan bahkan dapat mengakibatkan dampak ekonomi.

Tapi ada sesuatu yang spesial dengan evalfungsi (terlepas dari bahasa)

Pertanyaan : Apakah ada fakta historis untuk rasa takut ini menjadi bagian dari budaya populer, alih-alih memberikan perhatian yang sama pada fitur-fitur berbahaya lainnya?

Luis Masuelli
sumber
11
Saya tidak setuju bahwa ini terlalu luas, dan sebagai bukti saya menyajikan empat jawaban yang cukup panjang.
12
Mereka memilih untuk menutup karena terlalu luas ? (Saya belum bisa melihat suara dekat di komunitas ini) Alasan dekat itu menjadi alasan wildcard tanpa arti sama sekali akhir-akhir ini. Khususnya ketika titik yang saya tanyakan cukup jelas dengan contoh dan titik khusus untuk ditanyakan. Saya akan menanyakan topik ini dalam Meta ...
Luis Masuelli
13
Mengapa itu menjadi bagian dari budaya populer, dengan lebih banyak perhatian daripada fitur berbahaya lainnya? Karena alliteration eval - evil mudah diingat
Bergi
5
Alokasi memori dan pointer aritmatika yang dipandang sebagai kejahatan, oleh banyak.
user253751
5
Perlu dicatat bahwa OpenERP (sekarang Odoo) tidak hanya memanggil eval, ia memiliki fungsi internal yang disebut safe_evalsedang mempersiapkan lingkungan untuk mencegah kode melakukan hal-hal berbahaya. Bug telah ditemukan, karena Python adalah bahasa yang cukup fleksibel, dan karenanya sulit dikendalikan.
André Paramés

Jawaban:

76

Suatu evalfungsi dengan sendirinya bukanlah kejahatan, dan ada hal halus yang menurut saya tidak Anda buat:

Mengizinkan program untuk mengeksekusi input pengguna sewenang-wenang adalah buruk

Saya telah menulis kode yang menggunakan evaljenis fungsi dan aman: program dan parameternya adalah hard-coded. Terkadang, tidak ada fitur bahasa atau pustaka untuk melakukan apa yang dibutuhkan oleh program dan menjalankan perintah shell adalah jalur pendek. "Saya harus menyelesaikan pengkodean ini dalam beberapa jam, tetapi menulis Java / .NET / PHP / kode apa pun akan memakan waktu dua hari. Atau saya bisa evalmelakukannya dalam lima menit."

Setelah Anda mengizinkan pengguna untuk mengeksekusi apa pun yang mereka inginkan, bahkan jika dikunci oleh hak istimewa pengguna atau di belakang layar "aman", Anda membuat vektor serangan. Setiap minggu, beberapa CMS acak, perangkat lunak blog, dll. Memiliki lubang keamanan yang ditambal di mana penyerang dapat mengeksploitasi lubang seperti ini. Anda mengandalkan seluruh tumpukan perangkat lunak untuk melindungi akses ke fungsi yang dapat digunakan rm -rf /atau hal lain yang menimbulkan bencana (catatan: perintah itu tidak mungkin berhasil, tetapi akan gagal setelah menyebabkan sedikit kerusakan).

Apakah ada fakta historis untuk rasa takut ini menjadi bagian dari budaya populer, daripada menaruh perhatian yang sama pada fitur-fitur berbahaya lainnya?

Ya, ada preseden historis. Karena banyak bug yang telah diperbaiki selama bertahun-tahun dalam berbagai perangkat lunak yang memungkinkan penyerang jarak jauh untuk mengeksekusi kode sewenang-wenang, ide evalsebagian besar tidak disukai. Bahasa dan perpustakaan modern memiliki serangkaian fungsi yang kaya yang membuat evalkurang penting, dan ini bukan kebetulan. Keduanya membuat fungsi lebih mudah digunakan dan mengurangi risiko eksploitasi.

Telah banyak perhatian diberikan pada banyak fitur yang berpotensi tidak aman dalam bahasa populer. Apakah seseorang menerima lebih banyak perhatian terutama adalah masalah pendapat, tetapi evalfitur - fiturnya tentu memiliki masalah keamanan yang dapat dibuktikan yang mudah dipahami. Untuk satu, mereka memungkinkan menjalankan perintah sistem operasi termasuk built-in shell dan program eksternal yang standar (misalnya rmatau del). Dua, digabungkan dengan eksploit lain, penyerang mungkin dapat mengunggah skrip executable atau shell mereka sendiri kemudian mengeksekusinya melalui perangkat lunak Anda, membuka pintu untuk hampir semua hal terjadi (tidak ada yang baik).

Ini masalah yang sulit. Perangkat lunaknya kompleks, dan tumpukan perangkat lunak (misalnya LAMP ) adalah banyak perangkat lunak yang saling berinteraksi dengan cara yang rumit. Hati-hati bagaimana Anda menggunakan fitur bahasa seperti ini, dan jangan pernah mengizinkan pengguna untuk mengeksekusi perintah sewenang-wenang.


sumber
2
Kaulah :). Meskipun jika ada contoh terkenal yang berkontribusi pada budaya ini, saya ingin melihatnya dalam jawabannya.
Luis Masuelli
5
Saya tidak mengetahui adanya satu contoh pun , saya percaya ini lebih merupakan "kematian dengan seribu luka" dengan banyak contoh eksploitasi yang digunakan dan ditambal. Saya tidak melebih-lebihkan ketika saya mengatakan bahwa beberapa eksploit remote ditambal setiap minggu di beberapa perangkat lunak.
1
IDE saya adalah program yang memungkinkan saya - pengguna - untuk mengeksekusi input sewenang-wenang. Saya menemukan itu berguna daripada buruk.
Den
3
@Den itu akan menjadi pengecualian. Menjadi IDE, saya yakin Anda dapat menyebabkan kekacauan tanpa kemampuan itu. Tulis saja dalam kode sumber Anda. Selain itu, Anda sudah memiliki akses penuh ke komputer yang menjalankannya. Implikasinya di sini adalah bahwa suatu hak evaldapat meningkatkan hak istimewa. yang tidak menjadi masalah jika mereka sudah meningkat.
3
@Den: Itulah yang dirangkum Raymond Chen sebagai "sisi lain dari airlock". Anda sudah dapat menjalankan rm -rf /, tidak perlu melakukan itu dengan cara yang rumit melalui IDE. Masalahnya evaladalah itu membuka kemampuan itu bagi banyak aktor yang seharusnya tidak memiliki kemampuan itu.
MSalters
38

Sebagian darinya hanyalah nuansa yang sulit. Mudah untuk mengatakan hal seperti tidak pernah menggunakan goto, bidang publik, interpolasi string untuk kueri sql, atau eval. Pernyataan-pernyataan ini seharusnya tidak dipahami dengan mengatakan bahwa tidak pernah ada, dalam keadaan apa pun, alasan untuk menggunakannya. Tetapi menghindari mereka sebagai aturan umum adalah ide yang bagus.

Eval sangat tidak dianjurkan karena menggabungkan beberapa masalah umum.

Pertama, rentan terhadap serangan injeksi. Ini seperti injeksi SQL dimana ketika data yang dikontrol pengguna dimasukkan ke dalam kode, mudah untuk secara tidak sengaja memungkinkan kode arbitrer untuk dimasukkan.

Kedua, pemula cenderung menggunakan eval untuk mendapatkan kode yang terstruktur dengan buruk. Seorang programmer pemula dapat menulis kode yang terlihat seperti:

x0 = "hello"
x1 = "world"
x2 = "how"
x3 = "are"
x4 = "you?"
for index in range(5):
   print eval("x" + index)

Ini berfungsi, tetapi sebenarnya cara yang salah untuk menyelesaikan masalah ini. Jelas, menggunakan daftar akan jauh lebih baik.

Ketiga, eval biasanya tidak efisien. Banyak upaya dihabiskan untuk mempercepat implementasi bahasa pemrograman kami. Tetapi eval sulit untuk dipercepat dan menggunakannya biasanya akan memiliki efek yang merugikan pada kinerja Anda.

Jadi, eval bukanlah kejahatan. Kita dapat mengatakan bahwa eval itu jahat, karena well, ini cara yang mudah untuk mengatakannya. Setiap programmer pemula harus benar-benar menjauh dari eval karena apa pun yang mereka ingin lakukan, eval hampir pasti merupakan solusi yang salah. Untuk kasus penggunaan tingkat lanjut tertentu, eval masuk akal, dan Anda harus menggunakannya, tetapi jelas berhati-hatilah dengan perangkapnya.

Winston Ewert
sumber
13
Kasus kedua Anda sangat penting. Dalam bahasa yang memiliki eval tetapi juga dikompilasi, mengevaluasi string untuk menghasilkan referensi variabel adalah non-sepele. Misalnya, jika var x = 3; print(x)sedang disusun maka tidak perlu setiap run-time pengetahuan bahwa sumber menggunakan nama "x". Agar var x = 3; print(eval("x"))dapat bekerja, pemetaan itu perlu direkam. Ini adalah masalah nyata: dalam Common Lisp (let ((x 3)) (print (eval 'x)))akan membuang pengecualian variabel tidak terikat karena variabel leksikal x tidak memiliki koneksi dengan nama setelah kode dikompilasi.
Joshua Taylor
@JohnuaTaylor Maksud Anda alasan ketiga , bukan yang kedua?
user253751
1
@ Imibis, saya pikir dia mengacu pada kode di alasan kedua. Tapi Anda benar, itu benar-benar berkaitan dengan alasan ketiga: kinerja.
Winston Ewert
Lihat pertanyaan ini , bukan? ;)
jpmc26
@ jpmc26, tidak. Tetapi saya telah melihat banyak hal seperti itu.
Winston Ewert
20

Intinya adalah bahwa "eksekusi kode arbitrer" adalah teknologi-bicara untuk "mampu melakukan apa saja." Jika seseorang dapat mengeksploitasi eksekusi kode arbitrer dalam kode Anda, ini secara harfiah adalah kerentanan keamanan terburuk yang mungkin terjadi, karena itu berarti mereka dapat melakukan apa saja yang mungkin dilakukan oleh sistem Anda.

"Bug lain yang mungkin berbahaya" mungkin memiliki batasan, yang berarti bahwa mereka, menurut definisi, tidak lebih berbahaya daripada eksekusi kode arbitrer yang dieksploitasi.

Mason Wheeler
sumber
2
Demi argumen, penyalahgunaan pointer juga mengarah ke eksekusi kode arbitrer , namun pointer disukai jauh lebih sedikit daripada yang evalada.
Dmitry Grigoryev
12
@DmitryGrigoryev Apakah mereka benar-benar? Di luar C ++, pointer umumnya dianggap sangat berbahaya dan dihindari. C # mendukung pointer, misalnya, tetapi cenderung menjadi hal terakhir yang Anda coba setelah Anda menghabiskan semua opsi lain (biasanya, karena alasan kinerja pada manipulasi data). Sebagian besar bahasa modern tidak memiliki dukungan untuk pointer. Bahkan C ++ sendiri sedang bergerak ke arah pointer "aman" yang mencoba untuk meringankan masalah dengan pointer sewenang-wenang (misalnya menggunakan daftar benar / array bukan hanya pointer, menggunakan safe_ptr, melewati referensi ...).
Luaan
2
@DmitryGrigoryev: Bisakah Anda memberikan referensi untuk siapa saja yang mengatakan pointer lebih berbahaya daripada eval?
JacquesB
2
@ JacquesB di sini Anda pergi :)
Dmitry Grigoryev
1
@ JacquesB, ya; itu dimaksudkan sebagai lelucon (saya berharap senyum akan membuatnya cukup jelas). OP membuat pernyataan itu, bukan saya, jadi Anda harus meminta bukti padanya.
Dmitry Grigoryev
15

Ada alasan praktis dan teoretis.

Alasan praktisnya adalah bahwa kita mengamatinya sering menyebabkan masalah. Jarang eval menghasilkan solusi yang baik, dan seringkali menghasilkan solusi buruk di mana Anda akan mendapatkan yang lebih baik pada akhirnya jika Anda pura-pura eval tidak ada dan mendekati masalah secara berbeda. Jadi saran yang disederhanakan adalah untuk mengabaikannya, dan jika Anda menemukan sebuah kasus di mana Anda ingin mengabaikan saran yang disederhanakan, yah, semoga Anda telah memikirkannya secara cukup untuk memahami mengapa saran yang disederhanakan tidak berlaku dan yang umum perangkap tidak akan memengaruhi Anda.

Alasan yang lebih teoretis adalah bahwa jika sulit untuk menulis kode yang baik, bahkan lebih sulit untuk menulis kode yang menulis kode yang baik. Apakah Anda menggunakan eval, atau membuat pernyataan SQL dengan menggabungkan string, atau menulis kompiler JIT, apa yang Anda coba seringkali lebih sulit dari yang Anda harapkan. Potensi injeksi kode berbahaya adalah salah satu bagian besar dari masalah, tetapi selain itu pada umumnya lebih sulit untuk mengetahui kode Anda benar jika kode Anda bahkan tidak ada sampai runtime. Jadi saran yang disederhanakan adalah untuk menjaga hal-hal lebih mudah untuk diri Anda sendiri: "gunakan query SQL parameterized", "jangan gunakan eval".

Mengambil contoh efek mantra Anda: membangun kompua atau penerjemah Lua (atau apa pun) ke dalam gim Anda adalah untuk memungkinkan perancang permainan bahasa yang lebih mudah daripada C ++ (atau apa pun) untuk menggambarkan efek mantra. Sebagian besar "masalah eval" tidak berlaku jika semua yang Anda lakukan adalah mengevaluasi kode yang telah ditulis dan diuji dan dimasukkan dalam permainan atau dalam DLC atau apa pun yang Anda miliki. Itu hanya bahasa campuran. Masalah besar menghantam Anda ketika Anda mencoba untuk menghasilkan Lua (atau C ++, atau SQL, atau perintah shell, atau apa pun) dengan cepat, dan mengacaukannya.

Steve Jessop
sumber
1
Tentu saja, pembuatan kode runtime dapat dilakukan dengan benar, dan eval dapat bermanfaat. Misalnya saya sering menggunakan eval untuk metaprogramming / hal-hal seperti makro, terutama ketika saya ingin kinerja lebih dari OOP "bersih" atau solusi fungsional bisa memberikan. Kode yang dihasilkan seringkali lebih baik dan lebih sederhana karena memiliki lebih sedikit boilerplate. Namun, menyadari berbagai masalah mengenai sandboxing, mekanisme melarikan diri, injeksi kode, aturan pelingkupan, pelaporan kesalahan, optimisasi, dll. Membutuhkan tingkat kemahiran berbahasa yang tidak trivial, dan eval secara positif berbahaya tanpa pengetahuan itu.
amon
11

Tidak, tidak ada fakta sejarah yang jelas.

Kejahatan eval jelas terlihat dari awal. Fitur lainnya agak berbahaya. Orang dapat menghapus data. Orang dapat melihat data yang seharusnya tidak mereka lihat. Orang dapat menulis data yang seharusnya tidak mereka lakukan. Dan mereka hanya dapat melakukan sebagian besar dari hal-hal itu jika Anda entah bagaimana mengacaukan dan tidak memvalidasi input pengguna.

Dengan eval, mereka dapat meretas pentagon dan membuatnya tampak seperti Anda melakukannya. Mereka dapat memeriksa penekanan tombol Anda untuk mendapatkan kata sandi Anda. Dengan asumsi bahasa lengkap Turing, mereka benar-benar dapat melakukan apa pun yang mampu dilakukan komputer Anda.

Dan Anda tidak dapat memvalidasi input. Ini adalah string bentuk bebas sewenang-wenang. Satu-satunya cara untuk memvalidasinya adalah dengan membuat mesin analisis parser dan kode untuk bahasa yang dimaksud. Semoga beruntung dengan itu.

Telastyn
sumber
1
... atau masukan dari sumber tepercaya, seperti file definisi ejaan untuk game.
user253751
3
@ imibis tetapi jika input sudah ditentukan dan diuji aman mengapa menggunakan eval ketika itu dapat dimasukkan dalam sumber sistem?
Jules
3
@immibis - karena tidak ada yang pernah
meretas
2
... bukan itu yang dimaksud dengan "Turing complete" (Kelengkapan Turing adalah satu langkah lagi dari komputasi yang tidak relevan ke dunia nyata).
Leushenko
1
@ Telastyn: Yang tidak bisa dilakukan oleh program Javascript. Atau bahkan program C ++. Javascript berjalan di dalam kotak pasir (browser) yang dengan sendirinya di kotak pasir lain (dering 3 di x86 berbicara). Vektor interupsi berada di luar kotak pasir itu, di bawah kendali OS. Dan kotak pasir luar itu, ring 3, diberlakukan CPU.
MSalters
6

Saya pikir itu bermuara pada aspek-aspek berikut:

  • Kebutuhan
  • (Dijaga) Penggunaan
  • Mengakses
  • Verifikasi
  • Serangan multi-tahap

Kebutuhan

Halo, saya telah menulis alat pengeditan gambar yang sangat keren ini (tersedia seharga $ 0,02). Setelah Anda membuka gambar, Anda dapat melewati banyak filter di atas gambar Anda. Anda bahkan dapat membuat skrip sendiri menggunakan Python (program tempat saya menulis aplikasi ini). Saya hanya akan menggunakan evalinput Anda, memercayai Anda untuk menjadi pengguna yang terhormat.

(kemudian)

Terima kasih telah membelinya. Seperti yang Anda lihat, fungsinya persis seperti yang saya janjikan. Oh, Anda ingin membuka gambar? Tidak, kamu tidak bisa. Saya tidak akan menggunakan readmetode ini karena agak tidak aman. Penghematan? Tidak, saya tidak akan menggunakan write.

Yang ingin saya katakan adalah: Anda perlu membaca / menulis untuk hampir semua alat dasar. Sama untuk menyimpan skor tinggi dari game oh-begitu-mengagumkan Anda.

Tanpa baca / tulis, editor gambar Anda tidak berguna. Tanpa eval? Saya akan menulis plugin khusus untuk Anda!

(Dijaga) Penggunaan

Banyak metode yang berpotensi berbahaya. Seperti, misalnya readdan write. Contoh umum adalah layanan web yang memungkinkan Anda membaca gambar dari direktori tertentu dengan menyebutkan namanya. Namun, 'nama' sebenarnya dapat berupa jalur (relatif) yang valid pada sistem, memungkinkan Anda membaca semua file yang dapat diakses oleh layanan web, bukan hanya gambar. Menyalahgunakan contoh sederhana ini disebut 'path traversal'. Jika aplikasi Anda memungkinkan jalur traversal, itu buruk. A readtanpa bertahan melawan untuk jalur traversal bisa disebut kejahatan.

Namun, dalam kasus lain, string untuk readsepenuhnya di bawah kendali programer (mungkin hardcoded?). Dalam hal ini, hampir tidak jahat untuk digunakan read.

Mengakses

Sekarang, contoh sederhana lainnya, menggunakan eval.

Di suatu tempat di aplikasi web Anda, Anda menginginkan beberapa konten dinamis. Anda akan mengizinkan administrator untuk memasukkan beberapa kode yang dapat dieksekusi. Melihat admin adalah pengguna tepercaya, ini secara teori bisa ok. Pastikan untuk tidak mengeksekusi kode yang dikirimkan oleh non-admin, dan Anda baik-baik saja.

(Yaitu, sampai Anda memecat admin yang bagus itu tetapi lupa untuk mencabut aksesnya. Sekarang aplikasi web Anda dibuang).

Verifikasi.

Aspek lain yang penting, saya pikir, adalah betapa mudahnya memverifikasi input pengguna.

Menggunakan input pengguna dalam panggilan baca? Pastikan (sangat) yakin bahwa input untuk panggilan baca tidak mengandung sesuatu yang berbahaya. Normalisasi jalur, dan verifikasi file yang dibuka ada di direktori media Anda. Nah, itu aman.

Input pengguna pada panggilan tulis? Sama!

Injeksi SQL? Hanya menghindarinya, atau gunakan pertanyaan parametris dan Anda aman.

Eval? Bagaimana Anda akan memverifikasi input yang digunakan untuk evalpanggilan? Anda dapat bekerja sangat keras, tetapi sangat sulit (jika bukan tidak mungkin) untuk membuatnya bekerja dengan aman.

Serangan multi-tahap

Sekarang, setiap kali Anda menggunakan input pengguna, Anda perlu mempertimbangkan manfaat menggunakannya, melawan bahaya. Lindungi penggunaannya sebanyak yang Anda bisa.

Pertimbangkan lagi evalhal-hal yang bisa di contoh admin. Saya bilang itu tidak apa-apa.

Sekarang, pertimbangkan bahwa sebenarnya ada tempat di aplikasi web Anda di mana Anda lupa untuk melarikan diri dari konten pengguna (HTML, XSS). Itu pelanggaran yang lebih rendah daripada eval yang dapat diakses pengguna. Tetapi, dengan menggunakan konten pengguna yang tidak terhapus, pengguna dapat mengambil alih browser web dari admin, dan menambahkan evalgumpalan yang mampu melalui sesi admin, memungkinkan lagi akses sistem penuh.

(Serangan multi-tahap yang sama dapat dilakukan dengan injeksi SQL, bukan XSS, atau beberapa file arbitrer menulis menggantikan kode yang dapat dieksekusi alih-alih menggunakan eval)

Sjoerd Job Postmus
sumber
2
"Anda dapat bekerja sangat keras, tetapi sangat sulit (jika bukan tidak mungkin) untuk membuatnya bekerja dengan aman." - Ini adalah mustahil. Bukti sederhana: bukannya mencoba untuk mencari tahu apakah atau tidak kode pengguna yang diberikan adalah "aman", hanya mencoba untuk mencari tahu sesuatu yang jauh, jauh lebih sederhana, dan melihat seberapa keras yang sudah: apakah kode yang disediakan oleh pengguna berhenti?
Jörg W Mittag
2
@ JörgWMittag: beri saya program yang ditulis dalam Coq dan saya akan membuktikannya.
André Paramés
1
@ JörgWMittag: Setuju. Tergantung pada bahasa, dan ruang lingkup input pengguna. Bisa juga begitu eval("hard coded string" + user_input_which_should_be_alphanumeric + "remainder"). Memverifikasi bahwa input adalah alfanumerik dimungkinkan. Juga, 'apakah itu berhenti' adalah ortogonal untuk 'apakah ia memodifikasi / mengakses keadaan yang tidak boleh disentuh' dan 'apakah itu metode yang seharusnya tidak dipanggil'.
Sjoerd Job Postmus
3
@ JörgWMittag Tidak mungkin membuktikan bahwa program yang diberikan tidak akan melakukan sesuatu, tetapi tidak mustahil untuk secara konservatif mendefinisikan seperangkat program terbatas yang dapat Anda buktikan, dan untuk menegakkan bahwa program input adalah anggota set itu.
user253751
3

Agar fitur ini berfungsi sama sekali, itu berarti saya harus menyimpan lapisan refleksi di sekitar yang memungkinkan akses penuh ke keadaan internal seluruh program.

Untuk bahasa yang ditafsirkan, saya cukup menggunakan status juru bahasa, yang mudah, tetapi dalam kombinasi dengan kompiler JIT masih meningkatkan kompleksitas secara signifikan.

Tanpa eval, kompiler JIT sering dapat membuktikan bahwa data lokal thread tidak diakses dari kode lain, sehingga sangat dapat diterima untuk menyusun ulang akses, menghilangkan kunci dan cache data yang sering digunakan untuk waktu yang lebih lama. Ketika utas lain mengeksekusi evalpernyataan, mungkin perlu menyinkronkan kode JIT yang dikompilasi yang berjalan terhadap hal itu, jadi tiba-tiba kode yang dihasilkan JIT memerlukan mekanisme mundur yang kembali ke eksekusi yang tidak dioptimalkan dalam kerangka waktu yang masuk akal.

Jenis kode ini cenderung memiliki banyak bug yang halus, sulit direproduksi, dan pada saat yang sama juga membatasi optimasi pada kompiler JIT.

Untuk bahasa yang dikompilasi, pengorbanannya bahkan lebih buruk: Kebanyakan optimasi dilarang, dan saya perlu menyimpan informasi simbol yang luas dan penerjemah, sehingga fleksibilitas tambahan umumnya tidak sepadan - seringkali lebih mudah untuk mendefinisikan antarmuka ke beberapa internal struktur, misalnya dengan memberikan scripting pandangan dan pengendali akses bersamaan ke program Model .

Simon Richter
sumber
"Agar fitur ini berfungsi sama sekali, itu berarti saya harus menyimpan lapisan refleksi di sekitar yang memungkinkan akses penuh ke seluruh kondisi internal program" - tidak, hanya ke bagian yang ingin Anda pengaruhi. Dalam kasus OpenERP / Odoo, kode yang ditelusuri hanya memiliki akses ke sejumlah variabel dan fungsi yang dapat dipanggil, dan semuanya adalah utas-lokal.
André Paramés
1

Saya menolak premis yang evaldianggap lebih jahat daripada aritmatika pointer atau lebih berbahaya daripada memori langsung dan akses sistem file. Saya tidak tahu ada pengembang masuk akal yang akan percaya itu. Selain itu, bahasa yang mendukung aritmatika pointer / akses memori langsung biasanya tidak mendukung evaldan sebaliknya, jadi saya perhatikan seberapa sering perbandingan semacam itu akan relevan.

Tetapi evalmungkin kerentanan yang lebih terkenal , karena alasan sederhana bahwa itu didukung oleh JavaScript. JavaScript adalah bahasa berpasir tanpa memori langsung atau akses sistem file, jadi ia tidak memiliki kerentanan ini selain dari kelemahan dalam implementasi bahasa itu sendiri. EvalOleh karena itu salah satu fitur bahasa yang paling berbahaya, karena membuka kemungkinan eksekusi kode arbitrer. Saya percaya lebih banyak pengembang berkembang dalam JavaScript daripada di C / C ++, jadi evalcukup penting untuk diperhatikan daripada buffer overflows untuk sebagian besar pengembang.

JacquesB
sumber
0

Tidak ada programmer serius yang menganggap Eval sebagai "Jahat". Ini hanyalah alat pemrograman, seperti yang lainnya. Ketakutan (jika ada ketakutan) dari fungsi ini tidak ada hubungannya dengan budaya populer. Ini hanyalah perintah berbahaya yang sering disalahgunakan, dan dapat menimbulkan celah keamanan yang serius, dan menurunkan kinerja. Dari pengalaman saya sendiri, saya akan mengatakan bahwa jarang menemukan masalah pemrograman yang tidak dapat diselesaikan dengan lebih aman dan efisien dengan cara lain. Programmer yang paling mungkin menggunakan eval, adalah mereka yang mungkin paling tidak memenuhi syarat untuk melakukannya dengan aman.

Karena itu, ada bahasa di mana penggunaan eval sesuai. Perl datang ke pikiran. Namun saya pribadi merasa sangat jarang dibutuhkan dalam bahasa lain yang lebih modern, yang secara asli mendukung penanganan pengecualian terstruktur.

pengguna1751825
sumber
ini bahkan tidak berusaha menjawab pertanyaan yang diajukan, "Apakah ada fakta historis karena rasa takut ini menjadi bagian dari budaya populer". Lihat Bagaimana Menjawab
nyamuk
Pertanyaannya, menurut saya, didasarkan pada premis yang salah, jadi saya menjawabnya demikian.
user1751825
0

Saya pikir Anda membahasnya dengan baik di bagian berikut dari pertanyaan Anda (penekanan saya):

mereka memiliki penggunaan yang baik, asalkan digunakan dengan benar

Bagi 95% yang mungkin menggunakannya dengan benar, semuanya baik dan bagus; tetapi akan selalu ada orang yang tidak menggunakannya dengan benar. Beberapa dari mereka akan kekurangan pengalaman dan kurangnya kemampuan, sisanya akan berbahaya.

Akan selalu ada orang yang ingin mendorong batas-batas dan menemukan celah keamanan - beberapa untuk kebaikan, beberapa untuk buruk.

Adapun aspek fakta historisnya, evalfungsi ketik pada dasarnya memungkinkan eksekusi kode sewenang-wenang yang sebelumnya telah dieksploitasi di CMS web populer, Joomla! . Dengan Joomla! menyalakan lebih dari 2,5 juta situs di seluruh dunia , itu banyak potensi kerusakan tidak hanya bagi pengunjung ke situs-situs tersebut, tetapi juga berpotensi pada infrastruktur tempat hostingnya dan juga reputasi situs / perusahaan yang telah dieksploitasi.

Joomla! Contohnya mungkin sederhana, tapi itu sudah dicatat.

gabe3886
sumber
0

Ada beberapa alasan bagus untuk mencegah penggunaan eval(meskipun beberapa khusus untuk bahasa tertentu).

  • Lingkungan (leksikal dan dinamis) yang digunakan oleh evalsering mengejutkan (yaitu, Anda pikir eval(something here)harus melakukan satu hal, tetapi melakukan hal lain, mungkin memicu pengecualian)
  • Seringkali ada cara yang lebih baik untuk mencapai hal yang sama (gabungan dari penutupan leksikal yang dibangun kadang-kadang merupakan solusi yang lebih baik, tetapi itu mungkin merupakan masalah umum spesifik)
  • Jauh terlalu mudah untuk berakhir dengan data yang tidak aman sedang dievaluasi (meskipun ini sebagian besar dapat dilindungi).

Secara pribadi, saya tidak akan mengatakan bahwa itu jahat, tetapi saya akan selalu menentang penggunaan evaldalam tinjauan kode, dengan kata-kata di sepanjang baris "apakah Anda mempertimbangkan beberapa kode di sini ?" (jika saya punya waktu untuk membuat setidaknya pengganti sementara), atau "apakah Anda yakin eval benar-benar solusi terbaik di sini?" (jika saya tidak).

Vatine
sumber
ini bahkan tidak berusaha menjawab pertanyaan yang diajukan, "Apakah ada fakta historis karena rasa takut ini menjadi bagian dari budaya populer". Lihat Bagaimana Menjawab
nyamuk
0

Dalam Masyarakat Pikiran Minsky , Bab 6.4, katanya

Ada satu cara bagi pikiran untuk menonton dirinya sendiri dan tetap melacak apa yang terjadi. Bagilah otak menjadi dua bagian, A dan B. Hubungkan input dan output otak-A ke dunia nyata - sehingga dapat merasakan apa yang terjadi di sana. Tapi jangan menghubungkan otak-B dengan dunia luar sama sekali; alih-alih hubungkan sehingga otak-A adalah dunia otak-B!

Ketika satu program (B) menulis program lain (A) berfungsi sebagai program-meta. Subjek B adalah program A.

Ada program C. Itulah yang ada di kepala Anda yang menulis program B.

Bahayanya adalah mungkin ada seseorang (C ') dengan niat jahat, yang dapat mengganggu proses ini, sehingga Anda mendapatkan hal-hal seperti injeksi SQL.

Tantangannya adalah membuat perangkat lunak lebih pintar tanpa membuatnya lebih berbahaya.

Mike Dunlavey
sumber
Dua upvotes, dan dua downvotes. Sepertinya mungkin ini menyentuh saraf.
Mike Dunlavey
0

Anda memiliki banyak jawaban bagus di sini dan alasan utamanya jelas bahwa eksekusi kode arbitrer adalah mmmkay buruk, tetapi saya akan menambahkan satu faktor lain yang hanya disentuh orang lain di tepi:

Hal ini benar-benar sulit untuk kode permasalahan yang sedang dievaluasi dari string teks. Alat debugging normal Anda cukup banyak langsung keluar dari jendela dan Anda direduksi menjadi tracing atau gema sekolah yang sangat tua. Jelas itu tidak terlalu penting jika Anda memiliki sebuah fragmen dalam satu-liner yang Anda inginkan evaltetapi sebagai programmer yang berpengalaman Anda mungkin dapat menemukan solusi yang lebih baik untuk itu, sedangkan generasi kode skala yang lebih besar mungkin ada di suatu tempat di mana fungsi evaluasi menjadi sekutu yang berpotensi berguna.

glenatron
sumber