JSON.parse vs. eval ()

94

Spider Sense saya memperingatkan saya bahwa menggunakan eval()untuk mengurai JSON yang masuk adalah ide yang buruk. Saya hanya ingin tahu apakah JSON.parse()- yang saya asumsikan sebagai bagian dari JavaScript dan bukan fungsi khusus browser - lebih aman.

Kevin Major
sumber
Dari segi kinerja, JSON.parselebih cepat daripada eval, setidaknya di V8 (mesin JS Chromium). Sumber .
Paul

Jawaban:

110

Anda lebih rentan terhadap serangan jika menggunakan eval: JSON adalah bagian dari Javascript dan json.parse hanya mem-parsing JSON sedangkan evalakan membiarkan pintu terbuka untuk semua ekspresi JS.

jldupont.dll
sumber
"Kamu lebih rentan terhadap serangan" , saya sangat tidak setuju!
Hydroper
4
Maaf, Matheus, saya harus setuju. Masalahnya adalah ketika Anda menggunakan eval () untuk menafsirkan "input pengguna" - yang merupakan sumber APAPUN di luar JavaScript Anda (termasuk nilai yang dikembalikan dari servlet atau layanan web lain yang Anda panggil). Anda tidak dapat menjamin pengguna tidak memasukkan JavaScript berbahaya baik secara langsung ke aplikasi klien Anda, atau secara tidak langsung karena data yang tidak divalidasi disimpan dalam database server dan kemudian diteruskan ke program Anda melalui panggilan gaya AJAX. Anda mungkin masih perlu memvalidasi kolom individu untuk menghindari serangan "wakil bingung", tetapi menggunakan JSON.parse adalah langkah pertama yang baik.
JackLThornton
1
@ Hidro Bukti singkat konsep: coba eval('alert(1)');.
Valerio Bozz
37

Semua JSON.parseimplementasi kemungkinan besar digunakaneval()

JSON.parsedidasarkan pada solusi Douglas Crockford , yang digunakan eval()di sana pada baris 497 .

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

j = eval('(' + text + ')');

Keuntungan dari JSON.parseadalah bahwa itu memverifikasi argumen sintaks JSON yang benar.

pekerja keras
sumber
56
ya, kecuali bahwa baris tepat sebelum itu memverifikasi bahwa itu adalah string yang aman dan valid.
nickf
6
Saya menguji JSON.parse()di Firefox 28 dan Chromium 33 pada sistem Linux Mint saya. Itu 2x secepat eval()di Firefox dan 4x lebih cepat di Chromium. Saya tidak yakin kode sumber apa yang Anda posting, tetapi itu tidak sama di browser saya.
jbo5112
@plodder "keuntungan" mungkin tidak murah untuk melakukan verifikasi itu.
mmm
2
Browser modern menyediakan JSON.parse()implementasi asli yang lebih aman dan lebih cepat daripada eval()pengurai berbasis.
Mohammad Alhashash
15

Tidak semua browser memiliki dukungan JSON asli sehingga ada saatnya Anda perlu menggunakan eval() string JSON. Gunakan parser JSON dari http://json.org karena itu menangani semuanya dengan lebih mudah untuk Anda.

Eval() adalah kejahatan tetapi terhadap beberapa browser, ini adalah kejahatan yang diperlukan tetapi di mana Anda dapat menghindarinya, lakukanlah !!!!!

AutomatedTester
sumber
12

Ada perbedaan antara apa yang akan diterima JSON.parse () dan eval (). Coba evaluasi ini:

var x = "{\" shoppingCartName \ ": \" shopping_cart: 2000 \ "}"

eval(x)         //won't work
JSON.parse(x)   //does work

Lihat contoh ini .

Jeff Lowery
sumber
1
eval tidak bekerja karena mengurai string sebagai pernyataan kode dan dengan demikian, menganggap "{...}" sebagai ekspresi kode alih-alih ekspresi deklarasi nilai. jika Anda menghapus ambiguitas ("[{....}]" misalnya), tidak ada keraguan tentang sifat ekspresi dan eval akan membuat larik yang berisi objek yang diurai
Charles HETIER
1
Iya. Secara tradisional, x akan dibungkus dengan tanda kurung: eval ("(" + x + ")"). Apa yang saya katakan masih berlaku: tidak ada ambiguitas saat menggunakan JSON.parse ().
Jeff Lowery
9

Jika Anda mengurai JSON dengan eval, Anda mengizinkan string yang diurai berisi apa saja, jadi alih-alih hanya menjadi sekumpulan data, Anda dapat menemukan diri Anda menjalankan panggilan fungsi, atau apa pun.

Selain itu, JSON parsemenerima parameter tambahan, reviver, yang memungkinkan Anda menentukan cara menangani nilai-nilai tertentu, seperti waktu (info lebih lanjut dan contoh dalam dokumentasi inline di sini )

David Hedlund
sumber
4

JSON hanyalah bagian dari JavaScript. Tetapi evalmengevaluasi bahasa JavaScript lengkap dan bukan hanya subset yang JSON.

Gumbo
sumber
Benar, saya tahu itu. Apakah Anda menyiratkan bahwa JSON.parse () HANYA mengevaluasi JSON dan gagal pada semua data masuk lainnya? Atau hanya pembungkus untuk: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major
6
@Kevin Major: Ya, implementasi asli JSON.parse(diterapkan langsung ke mesin JavaScript) hanya mem-parsing JSON. Tetapi penggunaan implementasi non-native lainnya melakukan pemeriksaan kewarasan dan kemudian digunakan evaluntuk alasan performa.
Gumbo