Является ли json_encode достаточной защитой XSS?
У меня есть объект stdClass
в PHP, что-то вроде
$o = new stdClass;
$o->foo = $bar
Переменная $bar
содержит недоверенную строку.
Является ли следующий код шаблона PHP достаточной защитой XSS
<script type="text/javascript">
var o = <?php echo json_encode($o); ?>;
</script>
Моя первоначальная инстинктивная реакция заключается в том, что является безопасным, поскольку кодирование объекта в виде JSON гарантирует, что любые потенциальные эксплойты JavaScript будут инертными, если их включить в качестве объектов свойств строки JSON. Примерно так
$o = new stdClass;
$o->foo = "<script type=\"text/javascript\">alert(document.cookie)</script>";
?>
<script type="text/javascript">
var o = <?php echo json_encode($o) ?>;
</script>
В результате получается такой
<script type="text/javascript">
var o = {"foo":"<script type=\"text\/javascript\">alert(document.cookie) <\/script>"};
</script>
Если это известно как небезопасный, существует ли стандартный, зрелый способ сериализации простого объекта stdClass
в строку JSON для использования в части <script/>
HTML-документа.
В ожидании первого быстрого ответа я понимаю, что сработали бы любые HTML-теги или иная XSS-фильтрация каждого элемента объекта JSON, но я ищу краткий способ сделать это. Подобно тому, как это
//$eBar = addslashes($bar);
$sql = sprintf("SELECT * FROM table WHERE foo = '%s'",mysql_real_escape_string($bar));
и это
$sql = $db->select('SELECT * from table where foo = ?', $bar);
(в большинстве случаев) функционально эквивалентны, но последний считается лучшим, более безопасным кодом, поскольку конечному программисту не нужно беспокоиться об экранировании схем.
Ответы
Ответ 1
Кажется, что лучший ответ на этот вопрос лежит в другом вопросе.
Подводя итог, PHP JSON-кодер избегает всех несимвольных символов ASCII, поэтому новые строки/возвращаемые каретки не могут быть вставлены в пакетную часть Javascript-строки свойства JSON. Это может быть неверно для других кодеров JSON.
Однако передача исходной строки в JSON-кодирование может привести к обычной атаке XSS-атак, предлагается следующая комбинация констант.
var v= <?php echo json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS); ?>;
или убедитесь, что переменная, переданная в json_encode
, действительно является объектом.
Ответ 2
XSS очень широк, и на самом деле невозможно в любой момент узнать, безопасны ли ненадежные данные, которые вы используете.
Ответ на самом деле зависит от ситуации. json_encode
не запускается сам по себе - вы используете его только для сериализации. Функция escape, которую вы хотите использовать, будет htmlspecialchars
.
Однако зависит от того, хотите ли вы использовать htmlspecialchars
. Например, вы введете значение o.foo
с помощью innerHTML
или textContent
? Последнее привело бы к двойному побегу, но первый вложил бы script. Как насчет того, собираетесь ли вы использовать eval
(в JS)?
Кстати, addslashes
не, функционально эквивалентный экранированию mysql.
Я бы не стал смешивать JavaScript и PHP таким образом, чтобы начать, но это другая история.
Ответ 3
То, что я делаю, - это оценить объект json, прежде чем приступать к его безопасности. Я думаю, что метод evalJSON (true) в прототипе и jquery имеет аналогичную реализацию. Я не очень разбираюсь в стандартах xss с JSON, но это помогает мне
Ответ 4
Как говорили другие ответы; json_encode не создан для защиты от anti-xss. Если вы специально не кодируете небезопасную строку (или дезинфицируете должным образом), у вас будет потенциальная проблема.
Кроме того, после того, как эта строка будет извлечена из объекта JSON, она по-прежнему потенциально опасна, если ее ввести на страницу в любой момент. Например:
<?php $a->foo = "<script>alert(1)</script>"; ?>
var v = <?php echo json_encode($a); ?>
вряд ли будет выполняться (хотя вы не можете быть уверены). Но если вы должны были сделать:
$('#some-element').html(v.foo);
вы абсолютно столкнулись бы с уязвимостью.