Apa yang dimaksud dengan “penggunaan yang tidak benar” dari fitur Eval javascript? [Tutup]


13

Eval adalah fitur bahasa yang sangat kontroversial. Douglas Crockford langsung menolaknya. Saya bertanya-tanya apa risiko spesifik yang dihasilkan Eval. Menurut pertanyaan iniImproper use of eval opens up your code for injection attacks ,.

Apa saja penggunaan perintah Eval yang tidak tepat, dan lubang keamanan apa yang mereka buka?

Jawaban:


31

Kembali ketika saya sedang mengimplementasikan mesin JScript saya menganjurkan memiliki EVAL IS EVIL shirt dicetak tetapi sayangnya kami tidak pernah berhasil melakukannya.

Masalah terbesar saya dengan eval bukanlah serangan injeksi kode berbahaya yang jelas, meskipun itu tentu sangat memprihatinkan. Masalah terbesar saya adalah bahwa orang cenderung menggunakannya sebagai Palu yang Sangat Besar untuk menyelesaikan masalah yang sangat kecil. Sebagian besar penggunaan dunia nyata yang saya lihat dari "eval" di alam liar ketika saya berada di tim JScript bisa diselesaikan dengan mudah dengan menggunakan tabel pencarian; dan karena setiap objek dalam JScript sudah merupakan tabel pencarian tidak seperti itu adalah beban berat. Eval memulai kompilator lagi dan sepenuhnya menghancurkan kemampuan kompiler untuk mengoptimalkan kode Anda .

Untuk beberapa pemikiran lain dalam uraian ini, lihat artikel saya dari tahun 2003 tentang masalah ini:

Kejahatan umum:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/01/53329.aspx

Kejahatan serangan injeksi:

http://blogs.msdn.com/b/ericlippert/archive/2003/11/04/53335.aspx


Apa pendapat Anda tentang evalpotongan besar kode seperti yang diinginkan aplikasi seperti JSPacker? JSPacker + gzip biasanya menghasilkan ukuran file yang lebih kecil daripada kedua solusi itu sendiri, tetapi ketika Anda benar menunjukkan pada dasarnya menjalankan kompiler dua kali pada potongan kode yang sama, ditambah beberapa overhead untuk melakukan penggantian string.
Matthew Scharley

2
@ Matthew: Seringkali ada tradeoff antara ruang dan waktu, dan mengambil keuntungan dari tradeoff itu terkadang bisa menjadi kemenangan besar. Jika tujuan dari teknik ini adalah untuk meningkatkan kinerja maka pendapat saya adalah bahwa jika pengukuran yang cermat menunjukkan bahwa itu adalah kemenangan yang signifikan dalam skenario realistis tanpa memperkenalkan celah keamanan, bagus, lakukan itu. Tetapi saya tidak cukup tahu tentang teknik khusus untuk mengkritik detailnya.
Eric Lippert

Saya berharap salah satu dari jawaban yang saya telah melihat baik di sini atau di SO itu sendiri akan menyatakan apa yang Anda menyatakan link kedua: bahwa eval()adalah tidak resiko keamanan pada klien (browser) kode.
sq33G

4

Sebagian besar lubang keamanan adalah jenis lubang yang sama dengan injeksi SQL, yaitu menggabungkan input pengguna ke dalam kode JavaScript. Perbedaannya adalah bahwa meskipun ada cara untuk memastikan ini tidak terjadi dengan SQL, tidak banyak yang dapat Anda lakukan dengan JavaScript.

Sebagai contoh sepele dan tidak berguna, kalkulator JavaScript sederhana:

textbox1.value = eval(textbox2.value);

Salah satu contoh penggunaan yang benar adalah beberapa paket JavaScript yang memampatkan JavaScript dengan mengeluarkan kata-kata umum dan menggantinya dengan penggantian pendek 1-2 karakter. Packer kemudian menampilkan semua ini bersama dengan kode penggantian string berdasarkan pada kamus yang dihasilkan kemudian mengevaluasi hasilnya.


1

Ada beberapa hal yang tidak mungkin dilakukan di JS tanpa fungsi eval-seperti ( eval, Function, dan mungkin lebih).

Ambil applycontoh. Mudah digunakan saat menggunakannya pada panggilan fungsi biasa:

foo.apply(null, [a, b, c])

Tetapi bagaimana Anda melakukan ini untuk objek yang Anda buat melalui sintaks baru?

new Foo.apply(null, [a, b, c]) tidak berfungsi, atau bentuk yang serupa.

Tetapi Anda dapat mengatasi keterbatasan ini melalui evalatau Function(saya gunakan Functiondalam contoh ini):

Function.prototype.New = (function () {
    var fs = [];
    return function () {
        var f = fs[arguments.length];
        if (f) {
            return f.apply(this, arguments);
        }
        var argStrs = [];
        for (var i = 0; i < arguments.length; ++i) {
            argStrs.push("a[" + i + "]");
        }
        f = new Function("var a=arguments;return new this(" + argStrs.join() + ");");
        if (arguments.length < 100) {
            fs[arguments.length] = f;
        }
        return f.apply(this, arguments);
    };
}) ();

Contoh:

Foo.New.apply(null, [a, b, c]);

Tentu saja, Anda dapat secara manual membangun fungsi-fungsi yang Function.prototype.Newmenggunakan, tetapi tidak hanya verbose dan kikuk ini, itu (menurut definisi) harus terbatas. Functionmemungkinkan kode berfungsi untuk sejumlah argumen.


2
Benar, tetapi pertanyaan OP adalah " Apa saja penggunaan perintah Eval yang tidak tepat, dan lubang keamanan apa yang mereka buka? ", Bukan " Apa gunanya eval()? "
Ross Patterson

1
@RossPatterson: Tebak saya kebanyakan melihat judul pertanyaan haha.
Thomas Eding

Namun, +1 untuk menemukan penggunaan yang baik untuk fitur bahasa yang buruk :-)
Ross Patterson

1

Jawaban yang agak langsung dari saya adalah mengembangkan area pengujian API yang berorientasi pada pengembang. Kami memberi area teks pada halaman, dan tombol Run. Poin utama dari halaman ini adalah agar mereka dapat mencoba berbagai hal dalam Javascript terhadap API komunikasi iframe kami yang tidak begitu mudah dilakukan di lingkungan lokal.

Segala kejahatan yang bisa dilakukan dalam kasus itu juga bisa dilakukan oleh pengembang yang membuka alat F12 mereka.


0

Saya setuju bahwa itu harus sangat jarang digunakan, tetapi saya telah menemukan kasus penggunaan yang kuat untuk eval.

Ada fitur baru eksperimental di Firefox bernama asm.js yang telah saya kerjakan. Ini memungkinkan subset terbatas dari bahasa Javascript untuk dikompilasi ke dalam kode asli. Ya, ini sangat mengagumkan, tetapi memang memiliki keterbatasan. Anda dapat menganggap subset terbatas Javascript sebagai bahasa mirip-C yang tertanam dalam Javascript. Itu tidak dimaksudkan untuk dibaca atau ditulis oleh manusia.

Subset Javascript terbatas ini tidak memungkinkan saya untuk menyuntikkan kode yang dihasilkan runtime saya ke dalam kode yang dikompilasi setelah itu dikompilasi.

Saya telah menulis beberapa kode yang memungkinkan pengguna untuk menulis, dalam notasi yang umum, ekspresi matematis, dan mengubahnya dengan cepat menjadi kode asm.js. Kecuali saya ingin agar kode diproses di sisi server (yang tidak saya lakukan), evaladalah satu-satunya alat yang memungkinkan saya memproses kode yang dihasilkan oleh browser secara real-time.


0

Seperti yang ditunjukkan oleh orang lain, hal terpenting ketika bekerja dengannya evaladalah menjaganya tetap aman. Untuk itu, Anda ingin melakukan pemeriksaan argumen menyeluruh, dan menjaga evalkode sederhana karena umumnya jauh lebih sulit untuk mempertahankan dan mengamankan kode run-time yang dihasilkan.

Yang sedang berkata, saya menikmati menggunakan evaluntuk dua jenis hal (meskipun mungkin ada alternatif yang lebih baik, kurang jahat):

  1. Karena evalini merupakan cara "kode caching secara eksplisit", ini dapat digunakan untuk meningkatkan kinerja. Perhatikan bahwa pengoptimal selalu ditingkatkan, tetapi tidak ada jaminan apa yang dapat mereka lakukan untuk Anda. Dengan membuat hal-hal eksplisit dalam kode, Anda sebenarnya dapat membantu pengoptimal membuat keputusan yang lebih cerdas.
  2. Ini juga dapat digunakan untuk memberikan bentuk-bentuk dasar keamanan tipe, serta fitur bahasa lainnya yang kurang dimiliki JS, tanpa menurunkan kinerja.

Pendekatan iterator objek yang dikompilasi sebelumnya , misalnya, menunjukkan manfaat kinerja yang jelas saat menggunakan evaluntuk iterasi properti objek. Ini juga menunjukkan awal dari sistem tipe kuat yang dapat memberikan pengecekan kendala implisit dan banyak lagi, dengan sedikit atau tanpa biaya.

Banyak pengembang Javascript berpengalaman mungkin akan menunjukkan bahwa ini adalah lubang kelinci, karena, jika Anda mulai menulis Javascript dengan cara ini, pada dasarnya Anda mengubah cara Anda menggunakan bahasa. Namun itu mungkin tidak selalu menjadi hal buruk bagi mereka yang menikmati Javascript tetapi juga kehilangan fitur bahasa mendasar yang hanya dapat dicapai dengan mengubah cara kita menggunakan bahasa itu sendiri.


-3

Saya memiliki situasi di mana eval terlihat seperti cara untuk pergi, mengevaluasi string dan mengembalikan variabel yang sudah ada yang namanya sama dengan string.

Saya punya beberapa tabel: table1ResultsTable, table2ResultsTable, tableNResultsTable. Saya memiliki variabel yang disetel dengan nama yang sama, yaitu objek yang dapat didatangkan jQuery. Saya menggunakan ini untuk mengatur tabel dan memanggil fungsi yang bisa didatangkan jQuery pada mereka.

Setiap tabel memiliki class = "resultsTable" yang ditugaskan. Sekarang, saya perlu mendapatkan variabel ketika tabel diklik. Saya sedang melakukan ini:

$('resultsTable).on('click', 'td', function(event) {
    var cResultsTable = eval(event.target.parentElement.parentElement.parentElement.id);
    [etc]
});

Jadi saya mendapatkan id dari tabel di mana sel diklik, yang memiliki nama yang sama dengan variabel objek datatable yang sesuai dengannya. Jika seseorang memiliki saran untuk perbaikan, saya ingin mengetahuinya.


1
Mengapa Anda perlu eval? Id harus berupa string biasa, bukan kode. Bagaimanapun, event.target.parentElement.parentElement.parentElementitu mengerikan. Lebih lanjut, saya berharap panggilan eval menghasilkan kesalahan "referensi: [id] tidak didefinisikan", kecuali Anda sengaja menggunakan id yang dapat dievaluasi (yang rusak, salah, dan mungkin menyebabkan hal-hal aneh terjadi jika Anda mengakhiri menghasilkan id duplikat).
Brian

Mungkin aku tidak membuat diriku jelas. ID ADALAH string biasa. Itu id dari tabel yang telah diklik. Saya juga memiliki variabel objek (set dengan metode jQuery datatable (), referensi tabel yang sama) dengan nama yang sama dengan id. Saya mencoba untuk mendapatkan variabel itu, untuk mengakses fungsinya (sebenarnya, untuk menambahkan kelas "row_selected" ke baris yang dipilih), ketika tabel diklik. Sejak saya menulis ini, saya membuat perbaikan. Saya hanya menempatkan semua referensi objek dalam array, beri nama elemen yang sama dengan id, dan pasang string id ke dalamnya untuk mendapatkan objek ref.
BobRodes

Brian, jika Anda memiliki cara yang lebih baik untuk menemukan id dari tabel yang telah diklik, saya dengar. Untuk fungsi datatables, saya perlu menangani event klik terhadap sel, dan menambahkan kelas row_selected ke parentNode-nya. Mengapa saya tidak bisa begitu saja menangani acara baris dan menambahkan kelas secara langsung ke dalamnya, saya tidak tahu, tetapi baris tidak ditampilkan sebagai yang dipilih ketika saya melakukan itu.
BobRodes

1
Mungkin aku tidak membuat diriku jelas. Jika Anda memanggil eval pada string biasa (yaitu, non-JS), Anda akan melempar pengecualian. Jadi, penggunaan eval Anda tidak masuk akal. Jika Anda kebetulan membuat variabel objek dengan nama yang sama dengan id, kode Anda akan berfungsi ... tetapi menganggap saya rusak. Saya lebih suka membuat variabel dengan menggunakan document.getElementById(ID).MySpecialProperty = MYSPECIALPROPERTYVALUE(bukan untuk mengatakan itu bagus juga, tetapi lebih baik daripada eval). Seperti yang ditunjukkan Eric Lippert, "setiap objek dalam JScript sudah merupakan tabel pencarian."
Brian

Oke, jadi Anda mengatakan untuk menambahkan properti ke referensi elemen dan mengaturnya ke referensi objek yang dapat didata? Itu terdengar lebih ketat bagi saya juga.
BobRodes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.