Я понимаю, что использование 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 были в отдельных файлах.
Один из способов этого – 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);
Не делай этого.
Очень вероятно, что ваш сервер никогда не станет скомпрометированным и что ваше приложение будет в основном безопасным, бла-бла-бла, это не главное. Возможно, сервер становится частично скомпрометированным (слишком много векторов атаки, что, если функция php json_encode
скомпрометирована на вашем сервере?).
Простое решение – не доверять никому, посланному кем-либо . Современные браузеры имеют собственные парсеры JSON, а http://www.json.org предоставляет длинный список парсеров JSON для разных языков. Версии JS вернутся к встроенной версии для скорости.
Все это означает, что нет веских оснований использовать eval
для разбора JSON.
Он должен быть безопасным, но на клиенте вам не гарантируется, что json_str
не был добавлен каким-либо другим источником.