Json: PHP для JavaScript безопасен или нет?

Я понимаю, что использование eval(json_str) на клиенте уязвимо для вредоносного кода. Мой вопрос: если json_str был массивом, созданным функцией PHP json_encode , я был бы в безопасности?

Например,

 json_str = json_encode(array(record1, record2, record3)); 

теперь было бы совершенно безопасно использовать eval(json_str) внутри клиентского кода?

Да и нет:

Да: PHP дает действительный JSON

Нет. PHP также может возвращать вредоносный код, как в JSON.

Если вы можете доверять источнику, или если у вас даже есть полный контроль над ним (потому что он ваш), нет проблем.

С точки зрения чистого JavaScript, да, вы в безопасности: вывод json_encode никогда не может содержать ничего, кроме статических значений, которые не будут иметь неожиданной стороны при передаче в eval . (Хотя вы обычно должны окружать строку JSON с помощью () при использовании eval , чтобы избежать неправильного интерпретации выражения объектного литерала как блока операторов.)

Кроме того: это не обязательно относится ко всем кодовым устройствам JSON, потому что есть некоторые символы, которые допустимы для включения raw в строку JSON, которые не являются корректными в JavaScript. В частности, U + 2028 и U + 2029, которые не могут не отображаться в строковых литералах JavaScript, поскольку они составляют новые строки. Однако кодер PHP кодирует все символы, отличные от ASCII (например, как "\u2028" ), поэтому здесь нет проблем.

С точки зрения JavaScript, встроенного в другой язык (обычно: HTML), вы не обязательно безопасны. Например:

 <script type="text/javascript"> var v= <?php echo json_encode($value); ?>; </script> 

В этом примере, если value содержит строку с символьной последовательностью </script ? Это позволит досрочно завершить работу блока сценариев и, таким образом, выйти в HTML-разметку, где затем может быть добавлен другой вредоносный скрипт.

Чтобы избежать этой проблемы, при включении содержимого JSON в HTML всегда кодируйте символ < string в строковых литералах, как \x3C или, в JSON-совместимых терминах, \u003C . Для совместимости с блоками сценариев XHTML, отличных от CDATA, do & . Для совместимости с JS внутри атрибутов обработчика событий также выполняйте кавычки.

PHP сделает это для вас с правильными параметрами json_encode() :

 var v= <?php echo json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>; 

(Вы можете определить функцию быстрого доступа, чтобы сделать это быстрее, чтобы писать.)

Если вы хотите использовать политику безопасности контента (CSP) , вам запрещается выполнять встроенные теги скриптов. Поэтому это сделало бы замечательный ответ bobince иначе удивительным, поскольку CSP требует, чтобы все JavaScript были в отдельных файлах.

Как получить свой JavaScript в отдельном файле:

Один из способов этого – html кодировать JSON с PHP (который должен предотвращать XSS), а затем эхо его скрытый элемент, а затем использовать JavaScript для получения содержимого этого тега (адаптированного из OWASP ):

Поместите это inline (обратите внимание, что это фактически не будет выполнено):

 <script id="jsonString" type="application/json"> <?php // OWASP uses a <script> tag with an invalid "type" attribute, but // you can just as easily use a <span style="display:none"> or other // hidden tag. // // Note, this probably won't actually be valid JSON because we are using // htmlspecialcharacters() on the JSON data. That doesn't matter because // this is never actually executed by the browser due to the incorrect // script type. We will decode it later into valid JSON. echo htmlspecialchars(json_encode($object), ENT_NOQUOTES); ?> </script> 

Затем в вашем файле JavaScript:

 var dataElement = document.getElementById('jsonString'); // Get innerText, which also has the side effect of html decoding // the string returned, which is just what we want var jsonString = dataElement.textContent || dataElement.innerText; // Now you can parse the JSON string var jsonObj = JSON.parse(jsonString); 

Не использовать eval для разбора JSON

Не делай этого.

Очень вероятно, что ваш сервер никогда не станет скомпрометированным и что ваше приложение будет в основном безопасным, бла-бла-бла, это не главное. Возможно, сервер становится частично скомпрометированным (слишком много векторов атаки, что, если функция php json_encode скомпрометирована на вашем сервере?).

Простое решение – не доверять никому, посланному кем-либо . Современные браузеры имеют собственные парсеры JSON, а http://www.json.org предоставляет длинный список парсеров JSON для разных языков. Версии JS вернутся к встроенной версии для скорости.

Все это означает, что нет веских оснований использовать eval для разбора JSON.

Он должен быть безопасным, но на клиенте вам не гарантируется, что json_str не был добавлен каким-либо другим источником.