FlawOpen

flawopen.com/Разбор JSON/JSON.parse() vs eval()

JSON.parse() безопаснее, чем eval()?

Справочное руководство
Краткий ответ

Представьте входные данные как записку: JSON.parse() считывает поля структурированной формы, а eval() передает записку интерпретатору как инструкции для выполнения. JSON.parse() следует грамматике JSON и не выполняет JavaScript из текста; полученные значения все равно нужно проверить перед использованием.

ОПАСНО — старый шаблон
// Не интерпретируйте недоверенные данные как исходный код.
const data = eval("(" + untrustedJson + ")");
БЕЗОПАСНО
const data = JSON.parse(untrustedJson);
// Разбор JSON как данных; неверный JSON вызывает SyntaxError.

Почему возникает этот вопрос

До широкого распространения JSON.parse() некоторые старые программы на JavaScript использовали eval() для чтения JSON, поскольку текст JSON пересекается с синтаксисом выражений JavaScript. Такой подход выполняет программу JavaScript: данные под контролем атакующего могут стать кодом, а не ограниченным набором значений JSON. Для JSON используйте JSON-парсер.

От чего JSON.parse() не защищает

JSON.parse() не проверяет бизнес-правила, не авторизует действия и не делает разобранные значения безопасными для HTML, SQL, команд оболочки или URL. Проверяйте ожидаемую структуру данных и применяйте контекстное кодирование вывода или параметризованные API. Если передан reviver, предоставленный приложением callback выполняется во время разбора; он должен быть доверенным, простым и не создавать побочных эффектов на основе значений под контролем атакующего.

Вопросы и ответы

Может ли JSON.parse() выполнить код приложения?

Сам текст JSON разбирается как данные, а не выполняется как JavaScript. Но если приложение передает reviver, этот доверенный callback вызывается для разобранных значений и может выполнять код. Не позволяйте данным под контролем атакующего выбирать или создавать исполняемую логику callback.

Делает ли JSON.parse() ввод безопасным для дальнейшего использования?

Нет. Сверяйте разобранное значение с ожидаемой схемой приложения и правилами авторизации. Для HTML используйте кодирование вывода, для SQL — параметризованные запросы; разбор не очищает данные для этих контекстов.

Источники

См. также Загрязнение прототипа JavaScript: причины и защита Защищён ли lodash.merge() от загрязнения прототипа? Object.assign() и Prototype Pollution: что безопасно? Вызывает ли JSON.parse() загрязнение прототипа?