JSON.parse проти eval ()


94

My Spider Sense попереджає мене, що використання eval()синтаксичного аналізу вхідних файлів JSON - погана ідея. Мені просто цікаво, чи JSON.parse()є, як я вважаю, частиною JavaScript, а не функцією браузера, більш безпечним.


Щодо продуктивності, JSON.parseце швидше, ніж eval, принаймні, у V8 (двигун JS від Chromium). Джерело .
Пол

Відповіді:


110

Ви більш уразливі для атак при використанні eval: JSON є підмножиною Javascript і JSON.parse просто розбирає JSON , тоді evalб залишити відчинені двері всіх виразів JS.


"Ви вразливіші до атак" , я абсолютно не згоден!
Hydroper

4
Вибач, Матей, я повинен погодитися. Проблема полягає в тому, що ви використовуєте eval () для інтерпретації "введення користувачем" - це БУДЬ-ЯКЕ джерело, зовнішнє від вашого JavaScript (включаючи повернені значення із сервлетів чи інших веб-служб, які ви викликали). Ви не можете гарантувати, що користувачі не вводили шкідливий JavaScript ні безпосередньо у вашу клієнтську програму, ні опосередковано через неправомірні дані, що зберігаються в базі даних сервера, а потім передаються вашій програмі за допомогою виклику у стилі AJAX. Можливо, вам все одно доведеться перевірити окремі поля, щоб уникнути атак "заплутаного заступника", але використання JSON.parse - хороший перший крок.
JackLThornton

1
@Hydro Короткий доказ концепції: спробуйте eval('alert(1)');.
Валеріо Бозз

37

Усі JSON.parseреалізації, швидше за все, використовуютьeval()

JSON.parseбазується на рішенні Дугласа Крокфорда , який використовує eval()саме там, на рядку 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 + ')');

Перевага в JSON.parseтому, що він перевіряє, чи аргумент правильний синтаксис JSON.


56
так, за винятком того, що рядок прямо перед цим підтверджує, що це безпечний та дійсний рядок.
nickf

6
Я тестував JSON.parse()у Firefox 28 та Chromium 33 у своїй системі Linux Mint. Це було вдвічі швидше, ніж eval()у Firefox, і в чотири рази швидше в Chromium. Я не впевнений, який вихідний код ви публікуєте, але це не одне і те ж у моїх браузерах.
jbo5112

"Перевага" @plodder, мабуть, не дешева, щоб перевірити це.
ммм

2
Сучасні браузери забезпечують власну JSON.parse()реалізацію, яка є безпечнішою та швидшою, ніж eval()парсери на базі.
Мохаммед Альхашаш,

15

Не всі браузери мають власну підтримку JSON, тому іноді вам потрібно буде використовувати eval() рядок JSON. Використовуйте синтаксичний аналізатор JSON з http://json.org, оскільки це набагато простіше для вас.

Eval() є злом, але проти деяких браузерів є необхідним злом, але там, де ви можете цього уникнути, зробіть це !!!!!


12

Існує різниця між тим, що прийматимуть JSON.parse () та eval (). Спробуйте оцінити на цьому:

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

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

Дивіться цей приклад .


1
eval не працює, оскільки аналізує рядки як оператори коду і, отже, розглядає "{...}" як вираз коду замість виразу оголошення значення. якщо видалити двозначність (наприклад, "[{....}]"), немає сумнівів у природі виразу, а eval will створює масив, що містить проаналізований об'єкт
Charles HETIER

1
Так. Традиційно х буде обернуто дужками: eval ("(" + x + ")"). Те, що я сказав, все ще залишається: при використанні JSON.parse () немає однозначності.
Джефф Лоуері,

9

Якщо ви аналізуєте JSON за допомогою eval, ви дозволяєте рівню, який аналізується, містити абсолютно будь-що, тож замість того, щоб бути лише набором даних, ви можете виконати виклики функцій або що завгодно.

Крім того, JSON parseприймає додатковий параметр, відновлення, який дозволяє вказати, як поводитися з певними значеннями, такими як дати (більше інформації та приклад у вбудованій документації тут )


4

JSON - це лише підмножина JavaScript. Але evalоцінює повну мову JavaScript, а не тільки підмножину, яка є JSON.


Правильно, я це знаю. Ви маєте на увазі, що JSON.parse () ТОЛЬКО обчислює JSON і не працює на всіх інших вхідних даних? Або це просто обгортка для: var myObject = eval ('(' + responseText + ')'); ??
Kevin Major

6
@Kevin Major: Так, вбудована JSON.parse(безпосередньо реалізована в движку JavaScript) аналізує лише JSON. Але інші реалізації, що не є місцевими, виконують певну перевірку розумності, а потім використовують evalз міркувань продуктивності.
Гамбо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.